Exemple #1
0
async def export_chat_data(message, chat, strings):
    chat_id = chat['chat_id']
    key = 'export_lock:' + str(chat_id)
    if redis.get(key) and message.from_user.id not in OPERATORS:
        ttl = format_timedelta(timedelta(seconds=redis.ttl(
            key)), strings['language_info']['babel'])
        await message.reply(strings['exports_locked'] % ttl)
        return

    redis.set(key, 1)
    redis.expire(key, 7200)

    msg = await message.reply(strings['started_exporting'])
    data = {
        'general': {
            'chat_name': chat['chat_title'],
            'chat_id': chat_id,
            'date': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            'version': VERSION
        }
    }

    for module in [m for m in LOADED_MODULES if hasattr(m, '__export__')]:
        await asyncio.sleep(0)  # Switch to other events before continue
        if k := await module.__export__(chat_id):
            data.update(k)
Exemple #2
0
async def importfbans_cmd(message, fed, strings):
    fed_id = fed['fed_id']
    key = 'importfbans_lock:' + str(fed_id)
    if redis.get(key) and message.from_user.id not in OPERATORS:
        ttl = format_timedelta(timedelta(seconds=redis.ttl(key)),
                               strings['language_info']['babel'])
        await message.reply(strings['importfbans_locked'] % ttl)
        return

    redis.set(key, 1)
    redis.expire(key, 600)

    if 'document' in message:
        document = message.document
    else:
        if 'reply_to_message' not in message:
            await ImportFbansFileWait.waiting.set()
            await message.reply(strings['send_import_file'])
            return

        elif 'document' not in message.reply_to_message:
            await message.reply(strings['rpl_to_file'])
            return
        document = message.reply_to_message.document

    await importfbans_func(message, fed, document=document)
Exemple #3
0
async def setflood_command(message: Message, chat: dict, strings: dict):
    try:
        args = int(get_args(message)[0])
    except ValueError:
        return await message.reply(strings['invalid_args:setflood'])
    if args > 200:
        return await message.reply(strings['overflowed_count'])

    await AntiFloodConfigState.expiration_proc.set()
    redis.set(f"antiflood_setup:{chat['chat_id']}", args)
    await message.reply(
        strings['config_proc_1'],
        reply_markup=InlineKeyboardMarkup().add(
            InlineKeyboardButton(
                text=strings['cancel'],
                callback_data=cancel_state.new(user_id=message.from_user.id))))
Exemple #4
0
async def join_expired(chat_id, user_id, message_id, wlkm_msg_id):
    user = await bot.get_chat_member(chat_id, user_id)
    if user.status != 'restricted':
        return

    bot_user = await bot.get_chat_member(chat_id, BOT_ID)
    if 'can_restrict_members' not in bot_user or bot_user[
            'can_restrict_members'] is False:
        return

    key = 'leave_silent:' + str(chat_id)
    redis.set(key, user_id)

    await unmute_user(chat_id, user_id)
    await kick_user(chat_id, user_id)
    await tbot.delete_messages(chat_id, [message_id, wlkm_msg_id])
Exemple #5
0
async def kick_user_cmd(message, chat, user, args, strings):
    chat_id = chat['chat_id']
    user_id = user['user_id']

    if user_id == BOT_ID:
        await message.reply(strings['kick_texas'])
        return

    elif user_id == message.from_user.id:
        await message.reply(strings['kick_self'])
        return

    elif await is_user_admin(chat_id, user_id):
        await message.reply(strings['kick_admin'])
        return

    text = strings['user_kicked'].format(
        user=await get_user_link(user_id),
        admin=await get_user_link(message.from_user.id),
        chat_name=chat['chat_title']
    )

    # Add reason
    if args:
        text += strings['reason'] % args

    # Check if silent
    silent = False
    if get_cmd(message) == 'skick':
        silent = True
        key = 'leave_silent:' + str(chat_id)
        redis.set(key, user_id)
        redis.expire(key, 30)
        text += strings['purge']

    await kick_user(chat_id, user_id)

    msg = await message.reply(text)

    # Del msgs if silent
    if silent:
        to_del = [msg.message_id, message.message_id]
        if 'reply_to_message' in message and message.reply_to_message.from_user.id == user_id:
            to_del.append(message.reply_to_message.message_id)
        await asyncio.sleep(5)
        await tbot.delete_messages(chat_id, to_del)
Exemple #6
0
async def get_chat_lang(chat_id):
    r = redis.get('lang_cache_{}'.format(chat_id))
    if r:
        return r
    else:
        db_lang = await db.lang.find_one({'chat_id': chat_id})
        if db_lang:
            # Rebuild lang cache
            redis.set('lang_cache_{}'.format(chat_id), db_lang['lang'])
            return db_lang['lang']
        user_lang = await db.user_list.find_one({'user_id': chat_id})
        if user_lang and user_lang['user_lang'] in LANGUAGES:
            # Add telegram language in lang cache
            redis.set('lang_cache_{}'.format(chat_id), user_lang['user_lang'])
            return user_lang['user_lang']
        else:
            return 'en'
Exemple #7
0
async def import_fun(message, document, chat, strings):
    chat_id = chat['chat_id']
    key = 'import_lock:' + str(chat_id)
    if redis.get(key) and message.from_user.id not in OPERATORS:
        ttl = format_timedelta(timedelta(seconds=redis.ttl(
            key)), strings['language_info']['babel'])
        await message.reply(strings['imports_locked'] % ttl)
        return

    redis.set(key, 1)
    redis.expire(key, 7200)

    msg = await message.reply(strings['started_importing'])
    if document['file_size'] > 52428800:
        await message.reply(strings['big_file'])
        return
    data = await bot.download_file_by_id(document.file_id, io.BytesIO())
    try:
        data = rapidjson.load(data)
    except ValueError:
        return await message.reply(strings['invalid_file'])

    if 'general' not in data:
        await message.reply(strings['bad_file'])
        return

    file_version = data['general']['version']

    if file_version > VERSION:
        await message.reply(strings['file_version_so_new'])
        return

    imported = []
    for module in [m for m in LOADED_MODULES if hasattr(m, '__import__')]:
        module_name = module.__name__.replace('utah.modules.', '')
        if module_name not in data:
            continue
        if not data[module_name]:
            continue

        imported.append(module_name)
        await asyncio.sleep(0)  # Switch to other events before continue
        await module.__import__(chat_id, data[module_name])

    await msg.edit_text(strings['import_done'])
Exemple #8
0
async def fban_export(message, fed, strings):
    fed_id = fed['fed_id']
    key = 'fbanlist_lock:' + str(fed_id)
    if redis.get(key) and message.from_user.id not in OPERATORS:
        ttl = format_timedelta(timedelta(seconds=redis.ttl(key)),
                               strings['language_info']['babel'])
        await message.reply(strings['fbanlist_locked'] % ttl)
        return

    redis.set(key, 1)
    redis.expire(key, 600)

    msg = await message.reply(strings['creating_fbanlist'])
    fields = ['user_id', 'reason', 'by', 'time', 'banned_chats']
    with io.StringIO() as f:
        writer = csv.DictWriter(f, fields)
        writer.writeheader()
        async for banned_data in db.fed_bans.find({'fed_id': fed_id}):
            await asyncio.sleep(0)

            data = {'user_id': banned_data['user_id']}

            if 'reason' in banned_data:
                data['reason'] = banned_data['reason']

            if 'time' in banned_data:
                data['time'] = int(time.mktime(
                    banned_data['time'].timetuple()))

            if 'by' in banned_data:
                data['by'] = banned_data['by']

            if 'banned_chats' in banned_data:
                data['banned_chats'] = banned_data['banned_chats']

            writer.writerow(data)

        text = strings['fbanlist_done'] % html.escape(fed['fed_name'], False)
        f.seek(0)
        await message.answer_document(InputFile(f, filename='fban_export.csv'),
                                      text)
    await msg.delete()
Exemple #9
0
async def all_errors_handler(update: Update, error):
    if update.message is not None:
        message = update.message
    elif update.callback_query is not None:
        message = update.callback_query.message
    elif update.edited_message is not None:
        message = update.edited_message
    else:
        return True  # we don't want other guys in playground

    chat_id = message.chat.id
    err_tlt = sys.exc_info()[0].__name__
    err_msg = str(sys.exc_info()[1])

    log.warn('Error caused update is: \n' +
             html.escape(str(parse_update(message)), quote=False))

    if redis.get(chat_id) == str(error):
        # by err_tlt we assume that it is same error
        return True

    if err_tlt == 'BadRequest' and err_msg == 'Have no rights to send a message':
        return True

    ignored_errors = ('FloodWaitError', 'RetryAfter', 'SlowModeWaitError',
                      'InvalidQueryID')
    if err_tlt in ignored_errors:
        return True

    if err_tlt in ('NetworkError', 'TelegramAPIError', 'RestartingTelegram'):
        log.error("Conn/API error detected", exc_info=error)
        return True

    text = "<b>Sorry, I encountered a error!</b>\n"
    text += f'<code>{html.escape(err_tlt, quote=False)}: {html.escape(err_msg, quote=False)}</code>'
    redis.set(chat_id, str(error), ex=600)
    await bot.send_message(chat_id, text)
Exemple #10
0
async def connect_to_chat_direct(message, strings):
    user_id = message.from_user.id
    chat_id = message.chat.id

    if user_id == 1087968824:
        # just warn the user that connections with admin rights doesn't work
        return await message.reply(
            strings['anon_admin_conn'],
            reply_markup=InlineKeyboardMarkup().add(
                InlineKeyboardButton(
                    strings['click_here'], callback_data="anon_conn_cb")
            )
        )

    chat = await db.chat_list.find_one({'chat_id': chat_id})
    chat_title = chat['chat_title'] if chat is not None else message.chat.title
    text = strings['pm_connected'].format(chat_name=chat_title)

    try:
        await bot.send_message(user_id, text)
        await def_connect_chat(message, user_id, chat_id, chat_title)
    except (BotBlocked, CantInitiateConversation):
        await message.reply(strings['connected_pm_to_me'].format(chat_name=chat_title))
        redis.set('texas_connected_start_state:' + str(user_id), 1)
Exemple #11
0
            if len(args) > 1:
                text += strings['reason'] % ' '.join(args[1:])
        else:
            await message.reply(strings['enter_time'])
            return
    else:
        # Add reason
        if args is not None and len(args := args.split()) > 0:
            text += strings['reason'] % ' '.join(args[0:])

    # Check if silent
    silent = False
    if curr_cmd in ('smute', 'stmute'):
        silent = True
        key = 'leave_silent:' + str(chat_id)
        redis.set(key, user_id)
        redis.expire(key, 30)
        text += strings['purge']

    await mute_user(chat_id, user_id, until_date=until_date)

    msg = await message.reply(text)

    # Del msgs if silent
    if silent:
        to_del = [msg.message_id, message.message_id]
        if 'reply_to_message' in message and message.reply_to_message.from_user.id == user_id:
            to_del.append(message.reply_to_message.message_id)
        await asyncio.sleep(5)
        await tbot.delete_messages(chat_id, to_del)
Exemple #12
0
async def welcome_security_handler(message: Message, strings):
    if len(message.new_chat_members) > 1:
        # FIXME: Texas doesnt support adding multiple users currently
        return

    new_user = message.new_chat_members[0]
    chat_id = message.chat.id
    user_id = new_user.id

    if user_id == BOT_ID:
        return

    db_item = await get_greetings_data(message.chat.id)
    if not db_item or 'welcome_security' not in db_item:
        return

    if not await check_admin_rights(message, chat_id, BOT_ID,
                                    ['can_restrict_members']):
        await message.reply(strings['not_admin_ws'])
        return

    user = await message.chat.get_member(user_id)
    # Check if user was muted before
    if user['status'] == 'restricted':
        if user['can_send_messages'] is False:
            return

    # Check on OPs and chat owner
    if await is_user_admin(chat_id, user_id):
        return

    # check if user added is a bot
    if new_user.is_bot and await is_user_admin(chat_id, message.from_user.id):
        return

    # Mute user
    try:
        await mute_user(chat_id, user_id)
    except BadRequest as error:
        return await message.reply(
            f'welcome security failed due to {error.args[0]}')

    if 'security_note' not in db_item:
        db_item['security_note'] = {}
        db_item['security_note']['text'] = strings['default_security_note']
        db_item['security_note']['parse_mode'] = 'md'

    text, kwargs = await t_unparse_note_item(message, db_item['security_note'],
                                             chat_id)

    kwargs['reply_to'] = (None if 'clean_service' in db_item
                          and db_item['clean_service']['enabled'] is True else
                          message.message_id)

    kwargs['buttons'] = [] if not kwargs['buttons'] else kwargs['buttons']
    kwargs['buttons'] += [
        Button.inline(strings['click_here'], f'ws_{chat_id}_{user_id}')
    ]

    msg = await send_note(chat_id, text, **kwargs)

    redis.set(f'welcome_security_users:{user_id}:{chat_id}', msg.id)

    if raw_time := db_item['welcome_security'].get('expire', None):
        time = convert_time(raw_time)
Exemple #13
0
        db_item['note'] = {
            'text': strings['default_welcome'],
            'parse_mode': 'md'
        }
    reply_to = (message.message_id if 'clean_welcome' in db_item
                and db_item['clean_welcome']['enabled'] is not False else None)
    text, kwargs = await t_unparse_note_item(message, db_item['note'], chat_id)
    msg = await send_note(chat_id, text, reply_to=reply_to, **kwargs)
    # Clean welcome
    if 'clean_welcome' in db_item and db_item['clean_welcome'][
            'enabled'] is not False:
        if 'last_msg' in db_item['clean_welcome']:
            with suppress(MessageToDeleteNotFound, MessageCantBeDeleted):
                if value := redis.get(_clean_welcome.format(chat=chat_id)):
                    await bot.delete_message(chat_id, value)
        redis.set(_clean_welcome.format(chat=chat_id), msg.id)

    # Welcome mute
    if user_id == BOT_ID:
        return
    if 'welcome_mute' in db_item and db_item['welcome_mute'][
            'enabled'] is not False:
        user = await bot.get_chat_member(chat_id, user_id)
        if 'can_send_messages' not in user or user['can_send_messages'] is True:
            if not await check_admin_rights(message, chat_id, BOT_ID,
                                            ['can_restrict_members']):
                await message.reply(strings['not_admin_wm'])
                return

            await restrict_user(chat_id,
                                user_id,
Exemple #14
0
async def change_chat_lang(chat_id, lang):
    redis.set('lang_cache_{}'.format(chat_id), lang)
    await db.lang.update_one({'chat_id': chat_id}, {"$set": {'chat_id': chat_id, 'lang': lang}}, upsert=True)