Exemple #1
0
def __load_users_from_mtproto(chat_id: int) -> [UserInfo]:
    """
    Loading from the mtproto means that telethon available on system, and we can load list of users from the channel.
    """
    if not TELETHON_ENABLED:
        return []
    users = telethon_client.iter_participants(InputPeerChat(chat_id))
    result = []
    for user in users:
        if user.bot:
            continue
        result.append(UserInfo(user.id, user.username, user.first_name, user.last_name))
    return result
Exemple #2
0
def add_users_to_group(input_file, target_group, add_mode = 0, start_index = 0):
    global client

    mode = 0
    error_count = 0
    user_add_count = 0

    mode_set = False
    isChannel = False

    # validate mode when in auto-add mode
    if add_mode in [1, 2]:
        mode = int(add_mode)
        mode_set = True
    elif add_mode != 0:
        logger.error('Invalid Add Mode')

    # convert target_group to InputPeer
    if isinstance(target_group, Chat):
        target_group_entity = InputPeerChat(target_group.id)
        isChannel = False
    elif isinstance(target_group, Channel):
        target_group_entity = InputPeerChannel(target_group.id, target_group.access_hash)
        isChannel = True
    else:
        logger.error("%s is not a valid InputPeer", target_group.__class__.__name__)
        exit(5)

    while not mode_set:
        try:
            print('Add By:\n1. username\n2. user ID ( requires access hash to be in CSV )\n3. Auto-detect from CSV header')
            mode = int(input('How do you want to add users? '))
            mode_set = True
        except:
            logger.error('ValueError: invalid literal \n')
            continue

        # auto-detect mode from CSV header
        if mode == 3:
            csv_header_fieldnames = csv.DictReader(
                                        open(input_file, encoding='UTF-8'),
                                        delimiter=",",
                                        lineterminator="\n",
                                        skipinitialspace=True
                                    ).fieldnames
            logger.debug(csv_header_fieldnames)
            if len(csv_header_fieldnames) > 1:
                logger.error('CSV file has more than one column. Cannot auto-detect add mode. \n')
                mode_set = False
                continue
            elif csv_header_fieldnames[0] == 'username':
                mode = 1
            elif csv_header_fieldnames[0] == 'user id':
                mode = 2
            else:
                logger.error('Could not detect add mode from CSV file. Try again. \n')
                mode_set = False
                continue

        if mode not in [1, 2]:
            logger.error('Invalid Mode Selected. Try Again. \n')
            mode_set = False

    with open(input_file, encoding='UTF-8') as f:
        # convert csv dict into a list
        # to index it by an integer
        # to be able to resume from arbitrary points
        # https://stackoverflow.com/a/55790863
        users = list(csv.DictReader(f, delimiter=",", lineterminator="\n"))
        for i in range(start_index, len(users)):
            user = users[i]

            logger.debug('### ===== BEGIN USER ===== ###')
            logger.debug(user)

            if mode == 1:
                if user['username'] == "":
                    logger.warning("%s doesn't have a username", user)
                    continue
                user_to_add = client.get_input_entity(user['username'])
                logger.debug("Adding @%s", user['username'])
            elif mode == 2:
                try:
                    user_to_add = client.get_input_entity(int(user['user id']))
                except:
                    logger.error("User ID %s is invalid", user['user id'])
            else:
                sys.exit("Invalid Mode Selected. Please Try Again.")
            logger.debug(user_to_add)

            try:
                if isChannel:
                    updates = client(InviteToChannelRequest(target_group_entity, [user_to_add]))
                    logger.debug(updates.stringify())
                else:
                    updates = client(AddChatUserRequest(target_group_entity.chat_id, user_to_add, fwd_limit=1000000000))
                    logger.debug(updates.stringify())
                user_add_count += 1
                wait_time = random.randrange(60, 300)
                logger.debug("Waiting for %s seconds", wait_time)
                time.sleep(wait_time)
            except (
                    InputUserDeactivatedError,
                    UserNotMutualContactError,
                    UserPrivacyRestrictedError
                   ) as e:
                message = re.search('(?<=user).*', str(e)).group(0)
                logger.error("%s: %s%s", e.__class__.__name__, user_to_add, message)
            except PeerFloodError as e:
                logger.error("%s: %s", e.__class__.__name__, e)
                logger.info("to continue from the last position, run:\n\tpython3 %s %s %s %s %s",
                    sys.argv[0],
                    input_file,
                    target_group.id,
                    mode,
                    start_index + user_add_count
                )
                exit(6)
            except Exception as e:
                logger.exception(e.__class__.__name__)
                error_count += 1
                if error_count > 10:
                    sys.exit('too many errors')
                continue

            logger.debug('### ===== END USER ===== ### \n')
Exemple #3
0
    def message(self, iq):
        """
        Обработчик входящих сообщений из XMPP
        :param iq:
        :return:
        """
        jid = iq['from'].bare

        if iq['to'] == self.config['jid'] and iq[
                'type'] == 'chat':  # Пишут транспорту
            if iq['body'].startswith('!'):
                self.process_command(iq)
            else:
                self.gate_reply_message(
                    iq, 'Only commands accepted. Try !help for more info.')
        else:  # Пишут в Telegram
            if jid in self.tg_connections and self.tg_connections[
                    jid].is_user_authorized():
                if iq['body'].startswith('!'):  # Команда из чата
                    print('command received')
                    if iq['to'].bare.startswith('u'):
                        self.process_chat_user_command(iq)
                    elif iq['to'].bare.startswith(
                            'g') or iq['to'].bare.startswith('s'):
                        self.process_chat_group_command(iq)
                    else:
                        self.gate_reply_message(iq, 'Error.')
                else:  # Обычное сообщение
                    print('sent message')
                    tg_id = int(iq['to'].node[1:])
                    tg_peer = None
                    msg = iq['body']
                    reply_mid = None

                    if msg.startswith('>'):  # Проверка на цитирование
                        msg_lines = msg.split('\n')
                        matched = re.match(r'>[ ]*(?P<mid>[\d]+)[ ]*',
                                           msg_lines[0]).groupdict()

                        if 'mid' in matched:  # Если нашли ID сообщения, то указываем ответ
                            reply_mid = int(matched['mid'])
                            msg = '\n'.join(msg_lines[1:])

                    if iq['to'].bare.startswith('u'):  # Обычный пользователь
                        tg_peer = InputPeerUser(
                            tg_id,
                            self.tg_dialogs[jid]['users'][tg_id].access_hash)
                    elif iq['to'].bare.startswith('g'):  # Обычная группа
                        tg_peer = InputPeerChat(tg_id)
                    elif iq['to'].bare.startswith('s') or iq[
                            'to'].bare.startswith('c'):  # Супергруппа
                        tg_peer = InputPeerChannel(
                            tg_id, self.tg_dialogs[jid]['supergroups']
                            [tg_id].access_hash)

                    if tg_peer:
                        # Отправляем сообщение и получаем новый апдейт
                        result = self.tg_connections[jid].invoke(
                            SendMessageRequest(tg_peer,
                                               msg,
                                               generate_random_long(),
                                               reply_to_msg_id=reply_mid))
                        msg_id = None

                        # Ищем ID отправленного сообщения
                        if type(result) is Updates:  # Супегруппа / канал
                            for upd in result.updates:
                                if type(upd) is UpdateMessageID:
                                    msg_id = upd.id
                        elif type(result
                                  ) is UpdateShortSentMessage:  # ЛС / Группа
                            msg_id = result.id
Exemple #4
0
    def tg_process_dialogs(self, jid):
        # Инициализируем словари для диалогов
        self.tg_dialogs[jid] = dict()
        self.tg_dialogs[jid]['raw'] = list()
        self.tg_dialogs[jid]['users'] = dict()
        self.tg_dialogs[jid]['groups'] = dict()
        self.tg_dialogs[jid]['supergroups'] = dict()

        # Оффсеты для получения диалогов
        last_peer = InputPeerEmpty()
        last_msg_id = 0
        last_date = None

        while True:  # В цикле по кускам получаем все диалоги
            dlgs = self.tg_connections[jid].invoke(
                GetDialogsRequest(offset_date=last_date,
                                  offset_id=last_msg_id,
                                  offset_peer=last_peer,
                                  limit=100))

            self.tg_dialogs[jid]['raw'].append(dlgs)

            for usr in dlgs.users:
                self.tg_dialogs[jid]['users'][usr.id] = usr
            for cht in dlgs.chats:
                if type(cht) in [Chat, ChatForbidden]:  # Старая группа
                    self.tg_dialogs[jid]['groups'][cht.id] = cht
                elif type(cht) in [Channel, ChannelForbidden]:  # Супергруппа
                    self.tg_dialogs[jid]['supergroups'][cht.id] = cht

            for dlg in dlgs.dialogs:
                if type(dlg.peer) is PeerUser:
                    usr = self.tg_dialogs[jid]['users'][dlg.peer.user_id]
                    vcard = self.plugin['xep_0054'].make_vcard()
                    u_jid = 'u' + str(usr.id) + '@' + self.boundjid.bare

                    if usr.deleted:
                        vcard['FN'] = 'Deleted account'
                        vcard[
                            'DESC'] = 'This user no longer exists in Telegram'
                    else:
                        vcard['FN'] = display_tg_name(usr.first_name,
                                                      usr.last_name)
                        if usr.first_name:
                            vcard['N']['GIVEN'] = usr.first_name
                        if usr.last_name:
                            vcard['N']['FAMILY'] = usr.last_name
                        if usr.username:
                            vcard[
                                'DESC'] = 'Telegram Username: @' + usr.username

                            if usr.bot:
                                vcard['DESC'] += ' [Bot]'

                        vcard['NICKNAME'] = vcard['FN']

                    vcard['JABBERID'] = u_jid
                    self.plugin['xep_0054'].publish_vcard(jid=u_jid,
                                                          vcard=vcard)
                    self.plugin['xep_0172'].publish_nick(nick=vcard['FN'],
                                                         ifrom=u_jid)

                    self.send_presence(pto=jid, pfrom=u_jid, ptype='subscribe')

                    if usr.bot:
                        self.send_presence(pto=jid, pfrom=u_jid, pstatus='Bot')
                    else:
                        if type(usr.status) is UserStatusOnline:
                            self.send_presence(pto=jid, pfrom=u_jid)
                        elif type(usr.status) is UserStatusRecently:
                            self.send_presence(pto=jid,
                                               pfrom=u_jid,
                                               pshow='away',
                                               pstatus='Last seen recently')
                        elif type(usr.status) is UserStatusOffline:
                            self.send_presence(
                                pto=jid,
                                pfrom=u_jid,
                                ptype='xa',
                                pstatus=usr.status.was_online.strftime(
                                    'Last seen at %H:%M %d/%m/%Y'))
                        else:
                            self.send_presence(
                                pto=jid,
                                pfrom=u_jid,
                                ptype='unavailable',
                                pstatus='Last seen a long time ago')

                if type(dlg.peer) in [PeerChat, PeerChannel]:
                    g_type = ''
                    cht = None

                    if type(dlg.peer) is PeerChat:  # Старая группа
                        cht = self.tg_dialogs[jid]['groups'][dlg.peer.chat_id]
                        c_jid = 'g' + str(cht.id) + '@' + self.boundjid.bare
                        g_type = 'G'
                    elif type(dlg.peer) is PeerChannel:  # Супергруппа
                        cht = self.tg_dialogs[jid]['supergroups'][
                            dlg.peer.channel_id]

                        if cht.broadcast:
                            g_type = 'C'
                            c_jid = 'c' + str(
                                cht.id) + '@' + self.boundjid.bare
                        else:
                            g_type = 'SG'
                            c_jid = 's' + str(
                                cht.id) + '@' + self.boundjid.bare

                    vcard = self.plugin['xep_0054'].make_vcard()
                    vcard['FN'] = '[{}] {}'.format(g_type, cht.title)
                    vcard['NICKNAME'] = vcard['FN']
                    vcard['JABBERID'] = c_jid
                    self.plugin['xep_0054'].publish_vcard(jid=c_jid,
                                                          vcard=vcard)
                    self.plugin['xep_0172'].publish_nick(nick=vcard['FN'],
                                                         ifrom=c_jid)

                    self.send_presence(pto=jid, pfrom=c_jid, ptype='subscribe')
                    self.send_presence(pto=jid, pfrom=c_jid)

            if len(dlgs.dialogs
                   ) == 0:  # Если все диалоги получены - прерываем цикл
                break
            else:  # Иначе строим оффсеты
                last_msg_id = dlgs.dialogs[
                    -1].top_message  # Нужен последний id сообщения. Наркоманы.
                last_peer = dlgs.dialogs[-1].peer

                last_date = next(
                    msg for msg in dlgs.messages  # Ищем дату среди сообщений
                    if type(msg.to_id) is type(last_peer)
                    and msg.id == last_msg_id).date

                if type(last_peer) is PeerUser:  # Пользователь
                    access_hash = self.tg_dialogs[jid]['users'][
                        last_peer.user_id].access_hash
                    last_peer = InputPeerUser(last_peer.user_id, access_hash)
                elif type(last_peer) in [Chat, ChatForbidden]:  # Группа
                    last_peer = InputPeerChat(last_peer.chat_id)
                elif type(last_peer) in [Channel,
                                         ChannelForbidden]:  # Супергруппа
                    access_hash = self.tg_dialogs[jid]['supergroups'][
                        last_peer.channel_id].access_hash
                    last_peer = InputPeerChannel(last_peer.channel_id,
                                                 access_hash)