Пример #1
0
def get_callback_tail(event: Union[events.NewMessage.Event, Message,
                                   events.CallbackQuery.Event],
                      chat_id: int) -> str:
    if 0 > chat_id != event.chat_id and event.is_private:
        chat_id_str, _ = resolve_id(chat_id)
        return f'%{chat_id_str}'
    return ''
Пример #2
0
    async def _get_name(self, peer_id):
        if peer_id is None:
            return ''

        name = self._displays.get(peer_id)
        if name:
            return name

        # c = self.dumper.conn.cursor()
        _, kind = utils.resolve_id(peer_id)
        if kind == types.PeerUser:
            row = await db_user.find_one({'id': peer_id})
            if row:
                return f'{row["first_name"] or ""} {row["last_name"] or ""}'.strip(
                )
        elif kind == types.PeerChat:
            row = await db_user.find_one({'id': peer_id})
            if row:
                return row['title']
        elif kind == types.PeerChannel:
            row = await db_channel.find_one({'id': peer_id})
            if row:
                return row['title']
            row = await db_super_group.find_one({'id': peer_id})
            if row:
                return row['title']
        return ''
Пример #3
0
    def _get_name(self, peer_id):
        if peer_id is None:
            return ''

        name = self._displays.get(peer_id)
        if name:
            return name

        c = self.dumper.conn.cursor()
        _, kind = utils.resolve_id(peer_id)
        if kind == types.PeerUser:
            row = c.execute(
                'SELECT FirstName, LastName FROM User '
                'WHERE ID = ?', (peer_id, )).fetchone()
            if row:
                return '{} {}'.format(row[0] or '', row[1] or '').strip()
        elif kind == types.PeerChat:
            row = c.execute('SELECT Title FROM Chat '
                            'WHERE ID ?', (peer_id, )).fetchone()
            if row:
                return row[0]
        elif kind == types.PeerChannel:
            row = c.execute('SELECT Title FROM Channel '
                            'WHERE ID ?', (peer_id, )).fetchone()
            if row:
                return row[0]
            row = c.execute('SELECT Title FROM Supergroup '
                            'WHERE ID ?', (peer_id, )).fetchone()
            if row:
                return row[0]
        return ''
Пример #4
0
    async def get_portal_by_tgid(self, request: web.Request) -> web.Response:
        err = self.check_authorization(request)
        if err is not None:
            return err

        try:
            tgid, _ = resolve_id(int(request.match_info["tgid"]))
        except ValueError:
            return self.get_error_response(400, "tgid_invalid",
                                           "Given chat ID is not valid.")
        portal = Portal.get_by_tgid(tgid)
        if not portal:
            return self.get_error_response(404, "portal_not_found",
                                           "Portal to given Telegram chat not found.")
        user, _ = await self.get_user(request.query.get("user_id", None), expect_logged_in=None,
                                        require_puppeting=False)
        return web.json_response({
            "mxid": portal.mxid,
            "chat_id": get_peer_id(portal.peer),
            "peer_type": portal.peer_type,
            "title": portal.title,
            "about": portal.about,
            "username": portal.username,
            "megagroup": portal.megagroup,
            "can_unbridge": (await portal.can_user_perform(user, "unbridge")) if user else False,
        })
Пример #5
0
def get_callback_tail(event: Union[events.NewMessage.Event, Message,
                                   events.CallbackQuery.Event],
                      chat_id: int) -> str:
    if not event.is_private or event.chat.id == chat_id:
        return ''
    ori_chat_id, peer_type = resolve_id(chat_id)
    if peer_type is types.PeerChat:
        raise ValueError('Old-fashioned group chat is not supported')
    return f'%{ori_chat_id}' if ori_chat_id < 0 else f'%+{ori_chat_id}'
Пример #6
0
async def subscribe(event):
    """Send a message when the command /subscribe is issued."""
    # insert chat_id
    chat_id = event.message.chat.id
    find = utils.db.user.get_or_none(chat_id=chat_id)
    user_id = find
    if not find:  # 不存在用户信息
        await event.respond('Failed. Please input /start')
        raise events.StopPropagation

    text = event.message.text
    text = text.replace(',', ',')  # 替换掉中文逗号
    text = regex.sub(
        '\s*,\s*', ',', text
    )  # 确保英文逗号间隔中间都没有空格  如 "https://t.me/xiaobaiup, https://t.me/com9ji"
    splitd = [i for i in regex.split('\s+', text) if i]  # 删除空元素
    if len(splitd) <= 1:
        await event.respond(
            '输入需要订阅的关键字,支持js正则语法:`/[\s\S]*/ig`\n\nInput the keyword that needs to subscribe, support JS regular syntax:`/[\s\S]*/ig`'
        )
        cache.set('status_{}'.format(chat_id), {
            'current_status': '/subscribe keywords',
            'record_value': text
        },
                  expire=5 * 60)  #设置5m后过期
    elif len(splitd) == 3:
        command, keywords, channels = splitd
        result = await join_channel_insert_subscribe(
            user_id, parse_full_command(command, keywords, channels))
        if isinstance(result, str):
            logger.error('join_channel_insert_subscribe 错误:' + result)
            await event.respond(result, parse_mode=None)  # 提示错误消息
        else:
            msg = ''
            for key, channel, _chat_id in result:
                if _chat_id:
                    _chat_id, peer_type = telethon_utils.resolve_id(
                        int(_chat_id))

                if not channel:
                    channel = f'<a href="t.me/c/{_chat_id}/-1">{_chat_id}</a>'
                msg += f'keyword:{key}  channel:{channel}\n'
            if msg:
                msg = 'success subscribe:\n' + msg
                text, entities = html.parse(msg)  # 解析超大文本 分批次发送 避免输出报错
                for text, entities in telethon_utils.split_text(
                        text, entities):
                    await event.respond(text, formatting_entities=entities)
                #await event.respond('success subscribe:\n'+msg,parse_mode = None)
    raise events.StopPropagation
Пример #7
0
 def delete_all_conversations(self):
     all_peers = [
         utils.resolve_id(x[0])
         for x in self.client.session.entities.get_input_list()
     ]
     for peer in all_peers:
         log.debug("Deleting conversation with {}...".format(peer))
         try:
             input_entity = self.client.session.entities.get_input_entity(
                 peer[0])
             self.client(
                 DeleteHistoryRequest(input_entity,
                                      max_id=9999999999999999))
         except:
             log.error("Couldn't find {}".format(peer[0]))
Пример #8
0
    async def get_portal_by_tgid(self, request: web.Request) -> web.Response:
        err = self.check_authorization(request)
        if err is not None:
            return err

        try:
            tgid, _ = resolve_id(int(request.match_info["tgid"]))
        except ValueError:
            return self.get_error_response(400, "tgid_invalid",
                                           "Given chat ID is not valid.")
        portal = Portal.get_by_tgid(tgid)
        if not portal:
            return self.get_error_response(404, "portal_not_found",
                                           "Portal to given Telegram chat not found.")
        return await self._get_portal_response(UserID(request.query.get("user_id", "")), portal)
Пример #9
0
    async def get_input_entity(self, key):
        try:
            if key.SUBCLASS_OF_ID in (0xc91c90b6, 0xe669bf46, 0x40f202fd):
                # hex(crc32(b'InputPeer', b'InputUser' and b'InputChannel'))
                # We already have an Input version, so nothing else required
                return key
            # Try to early return if this key can be casted as input peer
            return utils.get_input_peer(key)
        except (AttributeError, TypeError):
            # Not a TLObject or can't be cast into InputPeer
            if isinstance(key, types.TLObject):
                key = utils.get_peer_id(key)
                exact = True
            else:
                exact = not isinstance(key, int) or key < 0

        result = None
        if isinstance(key, str):
            phone = utils.parse_phone(key)
            if phone:
                result = await self.get_entity_rows_by_phone(phone)
            else:
                username, invite = utils.parse_username(key)
                if username and not invite:
                    result = await self.get_entity_rows_by_username(username)
                else:
                    tup = utils.resolve_invite_link(key)[1]
                    if tup:
                        result = await self.get_entity_rows_by_id(tup, exact=False)

        elif isinstance(key, int):
            result = await self.get_entity_rows_by_id(key, exact)

        if not result and isinstance(key, str):
            result = await self.get_entity_rows_by_name(key)

        if result:
            entity_id, entity_hash = result  # unpack resulting tuple
            entity_id, kind = utils.resolve_id(entity_id)
            # removes the mark and returns type of entity
            if kind == types.PeerUser:
                return types.InputPeerUser(entity_id, entity_hash)
            elif kind == types.PeerChat:
                return types.InputPeerChat(entity_id)
            elif kind == types.PeerChannel:
                return types.InputPeerChannel(entity_id, entity_hash)
        else:
            raise ValueError('Could not find input entity with key ', key)
Пример #10
0
async def handler(update):
    #prints peer ids of channels
    result = await client.get_dialogs()
    print("\n List of channels:")
    for p in result:
        print(str(utils.resolve_id(p.id)[0]) + ": " + p.name)

    try:
        if str(update.message.to_id.channel_id) in channels:
            m = update.message
            media = m.media
            reply_msg = await m.get_reply_message()
            if reply_msg is None:
                text = "{}\n".format(m.message)
            else:
                text = "```REPLIED_TO:\n{}```{}\n".format(
                    reply_msg.message, m.message)

            if media is not None and utils.get_extension(media) == '.jpg':
                logger.info("Will download image")
                download_res = await client.download_media(
                    media, './downloads/')
                logger.info("Download done: {}".format(download_res))
                url = img_cli.upload_from_path(download_res, anon=True)['link']
                text += url + "\n"
                os.remove(download_res)
                logger.debug("File deleted")

            if not text == '':
                date = m.date.astimezone(timezone('Asia/Ulaanbaatar'))
                text += "`" + date.strftime("%Y-%m-%d %H:%M:%S GMT%Z") + "`\n"
                text += "==================================\n"
                msg = Webhook(channels[str(m.to_id.channel_id)], msg=text)
                msg.post()
                logger.info("Relaying Message from Channel ID: {}".format(
                    update.message.to_id.channel_id))
            else:
                logger.debug('Ignoring empty message: {}'.format(
                    update.message))
        else:
            logger.info("Ignoring Message from Channel: {}: {}".format(
                update.message.to_id.channel_id,
                update.message.to_id.channel_name))
    except:
        logger.debug('Exception occurred while handling:\n')
        logger.debug(update)
Пример #11
0
async def set_not_afk(event):
    current_message = event.message.message
    if ".afk" not in current_message and "yes" in borg.storage.USER_AFK:  # pylint:disable=E0602
        borg.storage.USER_AFK = {}  # pylint:disable=E0602
        borg.storage.afk_time = None  # pylint:disable=E0602
        # pylint:disable=E0602
        for chat_id in borg.storage.last_afk_message:
            await borg.storage.last_afk_message[chat_id].delete()
        borg.storage.last_afk_message = {}  # pylint:disable=E0602
        recvd_messages = "You received the following messages: \n"
        # pylint:disable=E0602
        for chat_id in borg.storage.recvd_messages:  # pylint:disable=E0602
            current_message = borg.storage.recvd_messages[chat_id]
            user_id = current_message.from_id
            message_id = current_message.id
            # check_condition = str(chat_id).startswith("-")
            # chat_id, _ = resolve_id(chat_id)
            # https://t.me/DeepLink/21
            # if not check_condition:
            #     recvd_messages += "👉 tg://openmessage?chat_id={}&message_id={} \n".format(chat_id, message_id)
            # else:
            #     recvd_messages += "👉 https://t.me/c/{}/{} \n\n".format(chat_id, message_id)
            chat_id, _ = resolve_id(chat_id)
            recvd_messages += "👉 tg://openmessage?chat_id={}&message_id={} \n".format(chat_id, message_id)
        try:
            if recvd_messages != "You received the following messages: \n":
                await borg.send_message(  # pylint:disable=E0602
                    Config.PRIVATE_GROUP_BOT_API_ID,  # pylint:disable=E0602
                    recvd_messages,
                    link_preview=False
                )
            await borg.send_message(  # pylint:disable=E0602
                Config.PRIVATE_GROUP_BOT_API_ID,  # pylint:disable=E0602
                "Set AFK mode to False"
            )
        except Exception as e:  # pylint:disable=C0103,W0703
            await borg.send_message(  # pylint:disable=E0602
                event.chat_id,
                "Please set `PRIVATE_GROUP_BOT_API_ID` " + \
                "for the proper functioning of afk functionality " + \
                "in @UniBorg\n\n `{}`".format(str(e)),
                reply_to=event.message.id,
                silent=True
            )
        borg.storage.recvd_messages = {}
Пример #12
0
 def get_entity(self, context_id, at_date=None):
     """
     Return the entity (user, chat or channel) corresponding to this context
     ID, at the given date (like all the specific methods). Context ID must
     be marked in the Bot API style, as with get_messages_from_context.
     """
     peer_type = utils.resolve_id(context_id)[1]
     if peer_type == types.PeerUser:
         return self.get_user(context_id, at_date=at_date)
     elif peer_type == types.PeerChat:
         return self.get_chat(context_id, at_date=at_date)
     elif peer_type == types.PeerChannel:
         supergroup = self.get_supergroup(context_id, at_date=at_date)
         if not supergroup:
             return self.get_channel(context_id, at_date=at_date)
         return supergroup
     else:
         raise ValueError('Invalid ID {} given'.format(context_id))
Пример #13
0
async def set_not_afk(event):
    current_message = event.message.message
    await event.edit("**I'm no longer AFK**")
    if Config.COMMAND_HAND_LER + "afk" not in current_message and "yes" in borg.storage.USER_AFK:  # pylint:disable=E0602
        borg.storage.USER_AFK = {}  # pylint:disable=E0602
        borg.storage.afk_time = None  # pylint:disable=E0602
        # pylint:disable=E0602
        for chat_id in borg.storage.last_afk_message:
            await borg.storage.last_afk_message[chat_id].delete()
        borg.storage.last_afk_message = {}  # pylint:disable=E0602
        recvd_messages = "You received the following messages: \n"
        # pylint:disable=E0602
        for chat_id in borg.storage.recvd_messages:  # pylint:disable=E0602
            current_message = borg.storage.recvd_messages[chat_id]
            user_id = current_message.from_id
            message_id = current_message.id
            chat_id, _ = resolve_id(chat_id)
            if isinstance(_, types.PeerUser):
                recvd_messages += f"👉 [{chat_id}](tg://user?id={chat_id})"
                # sadly, there is no way to goto a particular message by a user,
                # after the 5.5 Android update
            else:
                recvd_messages += f"👉 https://t.me/c/{chat_id}/{message_id} \n"
        try:
            if recvd_messages != "You received the following messages: \n":
                await borg.send_message(  # pylint:disable=E0602
                    Config.PRIVATE_GROUP_BOT_API_ID,  # pylint:disable=E0602
                    recvd_messages,
                    link_preview=False
                )
            await borg.send_message(  # pylint:disable=E0602
                Config.PRIVATE_GROUP_BOT_API_ID,  # pylint:disable=E0602
                "Set AFK mode to False"
            )
        except Exception as e:  # pylint:disable=C0103,W0703
            await borg.send_message(  # pylint:disable=E0602
                event.chat_id,
                "Please set `PRIVATE_GROUP_BOT_API_ID` " + \
                "for the proper functioning of afk functionality " + \
                "in @UniBorg\n\n `{}`".format(str(e)),
                reply_to=event.message.id,
                silent=True
            )
        borg.storage.recvd_messages = {}
async def test_update_info_group_user(helper, client, bot_group, channel,
                                      slave, bot_id, chat_type, alias, avatar):
    chat = slave.get_chat_by_criteria(chat_type=chat_type,
                                      alias=alias,
                                      avatar=avatar)

    # Set bot as admin if needed
    if await is_bot_admin(client, bot_id, bot_group):
        await client.edit_admin(bot_group,
                                bot_id,
                                change_info=True,
                                is_admin=True,
                                delete_messages=False)

    with link_chats(channel, (chat, ), bot_group):
        await client.send_message(bot_group, "/update_info")
        title = (await helper.wait_for_event(in_chats(bot_group)
                                             & new_title)).new_title
        if alias:
            assert chat.alias in title
        else:
            assert chat.name in title

        if avatar:
            await helper.wait_for_event(in_chats(bot_group) & new_photo)

        if chat_type == "GroupChat":
            # Get group description
            bot_group_t, peer_type = resolve_id(bot_group)
            if peer_type == PeerChannel:
                group: ChatFull = await client(
                    GetFullChannelRequest(bot_group_t))
            else:
                group: ChatFull = await client(GetFullChatRequest(bot_group_t))
            desc = group.full_chat.about

            chats_found = sum(
                int((i.name in desc) and  # Original name is found, and
                    (i.alias is None or i.alias in desc
                     )  # alias is found too if available
                    ) for i in chat.members)

            assert len(chat.members) >= 5
            assert chats_found >= 5, f"At least 5 members shall be found in the description: {desc}"
Пример #15
0
    def iter_resume_entities(self, context_id):
        """
        Returns an iterator over the entities that need resuming for the
        given context_id. Note that the entities are *removed* once the
        iterator is consumed completely.
        """
        c = self.conn.execute("SELECT ID, AccessHash FROM ResumeEntity "
                              "WHERE ContextID = ?", (context_id,))
        row = c.fetchone()
        while row:
            kind = resolve_id(row[0])[1]
            if kind == types.PeerUser:
                yield types.InputPeerUser(row[0], row[1])
            elif kind == types.PeerChat:
                yield types.InputPeerChat(row[0])
            elif kind == types.PeerChannel:
                yield types.InputPeerChannel(row[0], row[1])
            row = c.fetchone()

        c.execute("DELETE FROM ResumeEntity WHERE ContextID = ?",
                  (context_id,))
Пример #16
0
 async def get_resume_entities(self, context_id):
     """
     Returns an iterator over the entities that need resuming for the
     given context_id. Note that the entities are *removed* once the
     iterator is consumed completely.
     """
     rows = db_resume_entity.find({'context_id': context_id})
     count = await db_resume_entity.count_documents(
         {'context_id': context_id})
     logger.info(f'加载了【{count}】条待恢复数据')
     result = []
     async for row in rows:
         kind = resolve_id(row['id'])[1]
         if kind == types.PeerUser:
             result.append(
                 types.InputPeerUser(row['id'], row['access_hash']))
         elif kind == types.PeerChat:
             result.append(types.InputPeerChat(row['id']))
         elif kind == types.PeerChannel:
             result.append(
                 types.InputPeerChannel(row['id'], row['access_hash']))
     await db_resume_entity.delete_many({'context_id': context_id})
     return result
Пример #17
0
def get_channel_url(event_chat_username, event_chat__id):
    """
  获取频道/群组 url
  优先返回chat_id的url

  https://docs.telethon.dev/en/latest/concepts/chats-vs-channels.html#converting-ids

  Args:
      event_chat_username (str): 频道名地址 e.g. tianfutong 
      event_chat__id (str): 频道的非官方id。 e.g. -1001630956637
  """
    # event.is_private 无法判断
    # 判断私有频道
    # is_private = True if not event_chat_username else False
    host = 'https://t.me/'
    url = ''
    if event_chat__id:
        real_id, peer_type = telethon_utils.resolve_id(
            int(event_chat__id))  # 转换为官方真实id
        url = f'{host}c/{real_id}/'
    elif event_chat_username:
        url = f'{host}{event_chat_username}/'
    return url
Пример #18
0
async def join_channel_insert_subscribe(user_id, keyword_channel_list):
    """
  加入频道 且 写入订阅数据表

  支持传入频道id

  Raises:
      events.StopPropagation: [description]
  """
    res = []
    # 加入频道
    for k, c in keyword_channel_list:
        username = ''
        chat_id = ''
        try:
            if c.lstrip('-').isdigit():  # 整数
                real_id, peer_type = telethon_utils.resolve_id(int(c))
                channel_entity = await client.get_entity(real_id)
                chat_id = telethon_utils.get_peer_id(
                    PeerChannel(real_id))  # 转换为marked_id
                # channel_entity.title
            else:  # 传入普通名称
                channel_entity = await client.get_entity(
                    c
                )  # get_entity频繁请求会有报错 A wait of 19964 seconds is required (caused by ResolveUsernameRequest)
                chat_id = telethon_utils.get_peer_id(
                    PeerChannel(channel_entity.id))  # 转换为marked_id

            if channel_entity.username: username = channel_entity.username

            if channel_entity and not channel_entity.left:  # 已加入该频道
                res.append((k, username, chat_id))
            else:
                await client(JoinChannelRequest(channel_entity))
                res.append((k, username, chat_id))
        except Exception as _e:  # 不存在的频道
            logger.error(f'{c} JoinChannelRequest ERROR:{_e}')

            # 查询本地记录是否存在
            channel_name_or_chat_id = regex.sub(
                r'^(?:http[s]?://)?t.me/(?:c/)?', '', c)  # 清洗多余信息
            find = utils.db.connect.execute_sql(
                'select 1 from user_subscribe_list where status = 0 and (channel_name = ? or chat_id = ?)',
                (channel_name_or_chat_id, channel_name_or_chat_id)).fetchall()
            logger.warning(
                f'{c} JoinChannelRequest fail. cache join. cache find count: {len(find)}'
            )
            if find:
                if len(find) > 1:  # 存在1条以上的记录 则直接返回加入成功
                    if channel_name_or_chat_id.lstrip('-').isdigit():  # 整数
                        res.append((k, '', channel_name_or_chat_id))
                    else:
                        res.append((k, channel_name_or_chat_id, ''))
                else:
                    return '无法使用该频道:{}\n\nChannel error, unable to use: {}'.format(
                        c, _e)
            else:
                return '无法使用该频道:{}\n\nChannel error, unable to use: {}'.format(
                    c, _e)

    # 写入数据表
    result = []
    for keyword, channel_name, _chat_id in res:
        find = utils.db.user_subscribe_list.get_or_none(
            **{
                'user_id': user_id,
                'keywords': keyword,
                'channel_name': channel_name,
                'chat_id': _chat_id,
            })

        if find:
            re_update = utils.db.user_subscribe_list.update(status=0).where(
                utils.User_subscribe_list.id == find.id)  #更新状态
            re_update = re_update.execute()  # 更新成功返回1,不管是否重复执行
            if re_update:
                result.append((keyword, channel_name, _chat_id))
        else:
            insert_res = utils.db.user_subscribe_list.create(
                **{
                    'user_id':
                    user_id,
                    'keywords':
                    keyword,
                    'channel_name':
                    channel_name.replace('@', ''),
                    'create_time':
                    datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                    'chat_id':
                    _chat_id
                })
            if insert_res:
                result.append((keyword, channel_name, _chat_id))
    return result
Пример #19
0
async def handler(update):
    global temp_completed_path
    global FOLDER_GROUP
    try:

        real_id = get_peer_id(update.message.peer_id)
        CID, peer_type = resolve_id(real_id)

        if update.message.from_id is not None:
            logger.info(
                "USER ON GROUP => U:[%s]G:[%s]M:[%s]" %
                (update.message.from_id.user_id, CID, update.message.message))

        if update.message.media is not None and (not AUTHORIZED_USER
                                                 or CID in usuarios):
            if FOLDER_GROUP != update.message.date:
                logger.info(
                    "FOLDER_GROUP => [%s][%s][%s]" %
                    (FOLDER_GROUP, update.message.date, temp_completed_path))
                temp_completed_path = ''

        if update.message.media is not None and (not AUTHORIZED_USER
                                                 or CID in usuarios):
            file_name = 'NONAME'

            if isinstance(update.message.media, types.MessageMediaPhoto):
                file_name = '{}{}'.format(update.message.media.photo.id,
                                          get_extension(update.message.media))
                logger.info("MessageMediaPhoto  [%s]" % file_name)
            elif any(x in update.message.message for x in youtube_list):
                file_name = 'YOUTUBE VIDEO'
            else:
                attributes = update.message.media.document.attributes
                for attr in attributes:
                    if isinstance(attr, types.DocumentAttributeFilename):
                        file_name = attr.file_name
                    elif update.message.message:
                        file_name = re.sub(r'[^A-Za-z0-9 -!\[\]\(\)]+', ' ',
                                           update.message.message)

            mensaje = 'DOWNLOAD IN QUEUE [%s] [%s] => [%s]' % (time.strftime(
                '%d/%m/%Y %H:%M:%S',
                time.localtime()), file_name, temp_completed_path)
            logger.info(mensaje)
            message = await update.reply('Download in queue...')
            await queue.put([update, message, temp_completed_path])
        elif not AUTHORIZED_USER or CID in usuarios:
            if update.message.message == '/help':
                message = await update.reply(HELP)
                await queue.put([update, message])
            elif update.message.message == '/version':
                message = await update.reply(VERSION)
                await queue.put([update, message, temp_completed_path])
            elif update.message.message == '/alive':
                message = await update.reply('Keep-Alive')
                await queue.put([update, message, temp_completed_path])
            elif update.message.message == '/me' or update.message.message == '/id':
                message = await update.reply('id: {}'.format(CID))
                await queue.put([update, message, temp_completed_path])
                logger.info('me :[%s]' % (CID))
            else:
                time.sleep(2)
                if '/folder' in update.message.message:
                    folder = update.message.message
                    FOLDER_GROUP = update.message.date
                    temp_completed_path = os.path.join(
                        TG_DOWNLOAD_PATH, 'completed',
                        folder.replace('/folder ', '')
                    )  # SI VIENE EL TEXTO '/folder NAME_FOLDER' ESTE CREARÁ UNA CARPETA Y METERÁ ADENTRO TODOS LOS ARCHIVOS A CONTINUACION
                    logger.info("DOWNLOAD FILE IN :[%s]", temp_completed_path)
                elif ((update.message.message).startswith('/sendfiles')):
                    msg = await update.reply('Sending files...')
                    create_directory(os.path.join(download_path, 'sendFiles'))
                    ignored = {"*._process"}
                    basepath = os.path.join(download_path, 'sendFiles')
                    sending = 0
                    for root, subFolder, files in os.walk(basepath):
                        subFolder.sort()
                        files.sort()
                        for item in files:
                            if item.endswith('_process'):
                                #skip directories
                                continue
                            sending += 1
                            fileNamePath = str(os.path.join(root, item))
                            logger.info("SEND FILE :[%s]", fileNamePath)
                            await msg.edit('Sending {}...'.format(item))
                            loop = asyncio.get_event_loop()
                            task = loop.create_task(
                                tg_send_file(CID, fileNamePath, item))
                            download_result = await asyncio.wait_for(
                                task, timeout=maximum_seconds_per_download)
                            #message = await tg_send_file(fileNamePath)
                            shutil.move(fileNamePath,
                                        fileNamePath + "_process")
                    await msg.edit('{} files submitted'.format(sending))
                    logger.info("FILES SUBMITTED:[%s]", sending)
                elif ((update.message.message).startswith('#')):
                    folder = update.message.message
                    FOLDER_GROUP = update.message.date
                    temp_completed_path = os.path.join(
                        TG_DOWNLOAD_PATH, 'completed', folder.replace('#', '')
                    )  # SI VIENE EL TEXTO '/folder NAME_FOLDER' ESTE CREARÁ UNA CARPETA Y METERÁ ADENTRO TODOS LOS ARCHIVOS A CONTINUACION
                    logger.info("DOWNLOAD FILE IN :[%s]", temp_completed_path)

        elif update.message.message == '/me' or update.message.message == '/id':
            logger.info('UNAUTHORIZED USER: %s ', CID)
            message = await update.reply(
                'UNAUTHORIZED USER: %s \n add this ID to TG_AUTHORIZED_USER_ID'
                % CID)
    except Exception as e:
        message = await update.reply('ERROR: ' + str(e))
        logger.info('EXCEPTION USER: %s ', str(e))
Пример #20
0
def get_share_id(chat_id: int) -> int:
    return resolve_id(chat_id)[0]
Пример #21
0
async def join_channel_insert_subscribe(user_id, keyword_channel_list):
    """
  加入频道 且 写入订阅数据表

  支持传入频道id

  Raises:
      events.StopPropagation: [description]
  """
    res = []
    # 加入频道
    for k, c in keyword_channel_list:
        username = ''
        chat_id = ''
        try:
            is_chat_invite_link = False
            if c.lstrip('-').isdigit():  # 整数
                real_id, peer_type = telethon_utils.resolve_id(int(c))
                channel_entity = None
                # 不请求channel_entity
                # channel_entity = await client_get_entity(real_id, time.time() // 86400 )
                chat_id = telethon_utils.get_peer_id(
                    PeerChannel(real_id))  # 转换为marked_id
            else:  # 传入普通名称
                if regex.search('^\+', c):  # 邀请链接
                    is_chat_invite_link = True
                    c = c.lstrip('+')
                    channel_entity = None
                    chat_id = ''
                    chatinvite = await resolve_invit_hash(c)
                    if chatinvite:
                        chat_id, chat_title, channel_entity = chatinvite
                else:
                    channel_entity = await client_get_entity(
                        c,
                        time.time() // 86400)
                    chat_id = telethon_utils.get_peer_id(
                        PeerChannel(channel_entity.id))  # 转换为marked_id

            if channel_entity and hasattr(channel_entity, 'username'):
                username = channel_entity.username

            if channel_entity and not channel_entity.left:  # 已加入该频道
                logger.warning(
                    f'user_id:{user_id}触发检查  已加入该私有频道:{chat_id}  invite_hash:{c}'
                )
                res.append((k, username, chat_id))
            else:
                if is_chat_invite_link:
                    # 通过邀请链接加入私有频道
                    logger.info(f'user_id:{user_id}通过邀请链接加入私有频道{c}')
                    await client(ImportChatInviteRequest(c))
                    chatinvite = await resolve_invit_hash(c)
                    if chatinvite:
                        chat_id, chat_title, channel_entity = chatinvite
                        res.append((k, username, chat_id))
                else:
                    await client(JoinChannelRequest(channel_entity or chat_id))
                    res.append((k, username, chat_id))

        except errors.InviteHashExpiredError as _e:
            logger.error(f'{c} InviteHashExpiredError ERROR:{_e}')
            return f'无法使用该频道邀请链接:{c}\nLink has expired.'
        except errors.UserAlreadyParticipantError as _e:  # 重复加入私有频道
            logger.warning(f'{c} UserAlreadyParticipantError ERROR:{_e}')
            return f'无法使用该频道邀请链接:UserAlreadyParticipantError'
        except Exception as _e:  # 不存在的频道
            logger.error(f'{c} JoinChannelRequest ERROR:{_e}')

            # 查询本地记录是否存在
            channel_name_or_chat_id = regex.sub(
                r'^(?:http[s]?://)?t.me/(?:c/)?', '', c)  # 清洗多余信息
            find = utils.db.connect.execute_sql(
                'select 1 from user_subscribe_list where status = 0 and (channel_name = ? or chat_id = ?)',
                (channel_name_or_chat_id, channel_name_or_chat_id)).fetchall()
            logger.warning(
                f'{c} JoinChannelRequest fail. cache join. cache find count: {len(find)}'
            )
            if find:
                if len(find) > 1:  # 存在1条以上的记录 则直接返回加入成功
                    if channel_name_or_chat_id.lstrip('-').isdigit():  # 整数
                        res.append((k, '', channel_name_or_chat_id))
                    else:
                        res.append((k, channel_name_or_chat_id, ''))
                else:
                    return '无法使用该频道:{}\n\nChannel error, unable to use: {}'.format(
                        c, _e)
            else:
                return '无法使用该频道:{}\n\nChannel error, unable to use: {}'.format(
                    c, _e)

    # 写入数据表
    result = []
    for keyword, channel_name, _chat_id in res:
        if not channel_name: channel_name = ''

        find = utils.db.user_subscribe_list.get_or_none(
            **{
                'user_id': user_id,
                'keywords': keyword,
                'channel_name': channel_name,
                'chat_id': _chat_id,
            })

        if find:
            re_update = utils.db.user_subscribe_list.update(status=0).where(
                utils.User_subscribe_list.id == find.id)  #更新状态
            re_update = re_update.execute()  # 更新成功返回1,不管是否重复执行
            if re_update:
                result.append((keyword, channel_name, _chat_id))
        else:
            insert_res = utils.db.user_subscribe_list.create(
                **{
                    'user_id':
                    user_id,
                    'keywords':
                    keyword,
                    'channel_name':
                    channel_name.replace('@', ''),
                    'create_time':
                    datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                    'chat_id':
                    _chat_id
                })
            if insert_res:
                result.append((keyword, channel_name, _chat_id))
    return result
Пример #22
0
from telethon import events
from telethon.errors.rpcerrorlist import MessageDeleteForbiddenError
from telethon.tl.types import PeerChannel
from telethon.utils import resolve_id

CHATS = [-1001109500936, -1001200633650]
PEER_CHATS = [resolve_id(i)[0] for i in CHATS]


async def init(bot):
    @bot.on(events.NewMessage(chats=CHATS))
    async def handler(event):
        if isinstance(event.from_id, PeerChannel):
            if event.from_id.channel_id not in PEER_CHATS:
                try:
                    await event.delete()
                except MessageDeleteForbiddenError:
                    pass
Пример #23
0
async def common(event):
    """Echo the user message."""
    chat_id = event.message.chat.id
    text = event.text
    text = text.replace(',', ',')  # 替换掉中文逗号
    text = regex.sub(
        '\s*,\s*', ',', text
    )  # 确保英文逗号间隔中间都没有空格  如 "https://t.me/xiaobaiup, https://t.me/com9ji"

    find = cache.get('status_{}'.format(chat_id))
    if find:

        # 执行订阅
        if find['current_status'] == '/subscribe keywords':  # 当前输入关键字
            await event.respond(
                '输入需要订阅的频道url或者name:\n\nEnter the url or name of the channel to subscribe to:'
            )
            cache.set('status_{}'.format(chat_id), {
                'current_status': '/subscribe channels',
                'record_value': find['record_value'] + ' ' + text
            },
                      expire=5 * 60)  # 记录输入的关键字
            raise events.StopPropagation
        elif find['current_status'] == '/subscribe channels':  # 当前输入频道
            full_command = find['record_value'] + ' ' + text
            splitd = [i for i in regex.split('\s+', full_command)
                      if i]  # 删除空元素
            if len(splitd) != 3:
                await event.respond(
                    '关键字请不要包含空格 可使用正则表达式解决\n\nThe keyword must not contain Spaces.'
                )
                raise events.StopPropagation
            command, keywords, channels = splitd
            user_id = utils.db.user.get_or_none(chat_id=chat_id)
            result = await join_channel_insert_subscribe(
                user_id, parse_full_command(command, keywords, channels))
            if isinstance(result, str):
                await event.respond(result, parse_mode=None)  # 提示错误消息
            else:
                msg = ''
                for key, channel, _chat_id in result:
                    if _chat_id:
                        _chat_id, peer_type = telethon_utils.resolve_id(
                            int(_chat_id))
                    msg += 'keyword:{}  channel:{}\n'.format(
                        key, (channel if channel else f't.me/c/{_chat_id}'))
                if msg:
                    await event.respond('success subscribe:\n' + msg,
                                        parse_mode=None)

            cache.delete('status_{}'.format(chat_id))
            raise events.StopPropagation

        #取消订阅
        elif find['current_status'] == '/unsubscribe keywords':  # 当前输入关键字
            await event.respond(
                '输入需要**取消订阅**的频道url或者name:\n\nEnter the url or name of the channel where ** unsubscribe **is required:'
            )
            cache.set('status_{}'.format(chat_id), {
                'current_status': '/unsubscribe channels',
                'record_value': find['record_value'] + ' ' + text
            },
                      expire=5 * 60)  # 记录输入的关键字
            raise events.StopPropagation
        elif find['current_status'] == '/unsubscribe channels':  # 当前输入频道
            full_command = find['record_value'] + ' ' + text
            splitd = [i for i in regex.split('\s+', full_command)
                      if i]  # 删除空元素
            if len(splitd) != 3:
                await event.respond(
                    '关键字请不要包含空格 可使用正则表达式解决\n\nThe keyword must not contain Spaces.'
                )
                raise events.StopPropagation
            command, keywords, channels = splitd
            user_id = utils.db.user.get_or_none(chat_id=chat_id)
            result = update_subscribe(
                user_id, parse_full_command(command, keywords, channels))
            # msg = ''
            # for key,channel in result:
            #   msg += '{},{}\n'.format(key,channel)
            # if msg:
            #   await event.respond('success:\n'+msg,parse_mode = None)
            await event.respond('success unsubscribe..')

            cache.delete('status_{}'.format(chat_id))
            raise events.StopPropagation
        elif find['current_status'] == '/unsubscribe_id ids':  # 当前输入订阅id
            splitd = text.strip().split(',')
            user_id = utils.db.user.get_or_none(chat_id=chat_id)
            result = []
            for i in splitd:
                if not i.isdigit():
                    continue
                i = int(i)
                re_update = utils.db.user_subscribe_list.update(
                    status=1).where(
                        utils.User_subscribe_list.id == i,
                        utils.User_subscribe_list.user_id == user_id)  #更新状态
                re_update = re_update.execute()  # 更新成功返回1,不管是否重复执行
                if re_update:
                    result.append(i)
            await event.respond('success unsubscribe id:{}'.format(
                result if result else 'None'))
    raise events.StopPropagation
Пример #24
0
async def worker(name):
    while True:
        # Esperando una unidad de trabajo.

        queue_item = await queue.get()
        update = queue_item[0]
        message = queue_item[1]
        FOLDER_TO_GROUP = queue_item[2] if queue_item[2] else ''

        real_id = get_peer_id(update.message.peer_id)
        CID, peer_type = resolve_id(real_id)
        sender = await update.get_sender()
        username = sender.username

        # Comprobación de usuario
        if AUTHORIZED_USER and CID not in usuarios:
            logger.info('USUARIO: %s NO AUTORIZADO', CID)
            continue
        ###
        file_path = tmp_path
        file_name = 'FILENAME'
        if isinstance(update.message.media, types.MessageMediaPhoto):
            file_name = '{}{}'.format(update.message.media.photo.id,
                                      get_extension(update.message.media))
        elif any(x in update.message.message for x in youtube_list):
            try:
                url = update.message.message

                logger.info(f'INIT DOWNLOADING VIDEO YOUTUBE [{url}] ')
                await youtube_download(url, update, message)
                logger.info(f'FINIT DOWNLOADING VIDEO YOUTUBE [{url}] ')
                queue.task_done()
                continue
            except Exception as e:
                logger.info('ERROR: %s DOWNLOADING YT: %s' %
                            (e.__class__.__name__, str(e)))
                await message.edit('Error!')
                message = await message.edit('ERROR: %s DOWNLOADING YT: %s' %
                                             (e.__class__.__name__, str(e)))
                queue.task_done()
                continue
        else:
            attributes = update.message.media.document.attributes
            for attr in attributes:
                if isinstance(attr, types.DocumentAttributeFilename):
                    file_name = attr.file_name
                elif update.message.message:
                    file_name = re.sub(r'[^A-Za-z0-9 -!\[\]\(\)]+', ' ',
                                       update.message.message)
                else:
                    file_name = time.strftime('%Y%m%d %H%M%S',
                                              time.localtime())
                    file_name = '{}{}'.format(
                        update.message.media.document.id,
                        get_extension(update.message.media))
        file_path = os.path.join(file_path, file_name)
        _download_path, _complete_path = getDownloadPath(file_name, CID)
        logger.info(
            f"getDownloadPath FILE [{file_name}] to [{_download_path}]")
        await message.edit(
            f'Downloading {file_name} \ndownload in:\n{_download_path}')
        #time.sleep(1)
        logger.info('Downloading... ')
        mensaje = 'STARTING DOWNLOADING %s [%s] BY [%s]' % (time.strftime(
            '%d/%m/%Y %H:%M:%S', time.localtime()), file_path, (CID))
        logger.info(mensaje)
        try:
            loop = asyncio.get_event_loop()
            if (TG_PROGRESS_DOWNLOAD == True
                    or TG_PROGRESS_DOWNLOAD == 'True'):
                task = loop.create_task(
                    client.download_media(update.message,
                                          file_path,
                                          progress_callback=lambda x, y:
                                          callback(x, y, file_path, file_name,
                                                   message, _download_path)))
            else:
                task = loop.create_task(
                    client.download_media(update.message, file_path))
            download_result = await asyncio.wait_for(
                task, timeout=maximum_seconds_per_download)
            end_time = time.strftime('%d/%m/%Y %H:%M:%S', time.localtime())
            end_time_short = time.strftime('%H:%M', time.localtime())
            filename = os.path.split(download_result)[1]

            if FOLDER_TO_GROUP:
                final_path = os.path.join(FOLDER_TO_GROUP, filename)
                create_directory(FOLDER_TO_GROUP)
                os.chmod(FOLDER_TO_GROUP, 0o777)
            else:
                _path, final_path = getDownloadPath(filename, CID)
                create_directory(_path)
            ######
            logger.info("RENAME/MOVE [%s] [%s]" %
                        (download_result, final_path))
            #create_directory(completed_path)
            shutil.move(download_result, final_path)
            os.chmod(final_path, 0o666)
            if TG_UNZIP_TORRENTS:
                if zipfile.is_zipfile(final_path):
                    with zipfile.ZipFile(final_path, 'r') as zipObj:
                        for fileName in zipObj.namelist():
                            if fileName.endswith('.torrent'):
                                zipObj.extract(fileName, download_path_torrent)
                                logger.info("UNZIP TORRENTS [%s] to [%s]" %
                                            (fileName, download_path_torrent))

            ######
            mensaje = 'DOWNLOAD FINISHED %s [%s] => [%s]' % (
                end_time, file_name, final_path)
            logger.info(mensaje)
            await message.edit('Downloading finished:\n%s \nIN: %s\nat %s' %
                               (file_name, _path, end_time_short))
        except asyncio.TimeoutError:
            logger.info('[%s] Time exceeded %s' %
                        (file_name,
                         time.strftime('%d/%m/%Y %H:%M:%S', time.localtime())))
            await message.edit('Error!')
            message = await update.reply(
                'ERROR: Time exceeded downloading this file')
        except Exception as e:
            logger.critical(e)
            logger.info('[EXCEPCION]: %s' % (str(e)))
            logger.info('[%s] Excepcion %s' %
                        (file_name,
                         time.strftime('%d/%m/%Y %H:%M:%S', time.localtime())))
            await message.edit('Error!')
            message = await update.reply('ERROR: %s downloading : %s' %
                                         (e.__class__.__name__, str(e)))

        # Unidad de trabajo terminada.
        queue.task_done()