def start(bot, update, session, chat, user): """Send the start text.""" if chat.is_maintenance or chat.is_newsfeed: call_tg_func(update.message.chat, 'send_message', ['Hello there'], {'reply_markup': get_main_keyboard(admin=True)}) else: call_tg_func(update.message.chat, 'send_message', [start_text], {'reply_markup': get_main_keyboard(user), 'parse_mode': 'Markdown'})
def cancel(bot, update, session, chat, user): """Send a help text.""" if not send_tagged_count_message(session, bot, user, chat): keyboard = get_main_keyboard( admin=True) if chat.is_maintenance else get_main_keyboard(user) call_tg_func(update.message.chat, 'send_message', ['All running commands are canceled'], {'reply_markup': keyboard}) chat.cancel(bot)
def handle_next(session, bot, chat, tg_chat, user): """Handle the /next call or the 'next' button click.""" # We are tagging a whole sticker set. Skip the current sticker if chat.tag_mode == TagMode.STICKER_SET: # Check there is a next sticker stickers = chat.current_sticker.sticker_set.stickers for index, sticker in enumerate(stickers): if sticker == chat.current_sticker and index + 1 < len(stickers): # We found the next sticker. Send the messages and return chat.current_sticker = stickers[index + 1] send_tag_messages(chat, tg_chat, user) return # There are no stickers left, reset the chat and send success message. chat.current_sticker.sticker_set.completely_tagged = True call_tg_func(tg_chat, 'send_message', ['The full sticker set is now tagged.'], {'reply_markup': get_main_keyboard(user)}) send_tagged_count_message(session, bot, user, chat) chat.cancel(bot) # Find a random sticker with no changes elif chat.tag_mode == TagMode.RANDOM: base_query = session.query(Sticker) \ .outerjoin(Sticker.changes) \ .join(Sticker.sticker_set) \ .filter(Change.id.is_(None)) \ .filter(StickerSet.is_default_language.is_(True)) \ .filter(StickerSet.banned.is_(False)) \ .filter(StickerSet.nsfw.is_(False)) \ .filter(StickerSet.furry.is_(False)) \ # Let the users tag the deluxe sticker set first. # If there are no more deluxe sets, just tag another random sticker. sticker = base_query.filter(StickerSet.deluxe.is_(True)) \ .order_by(func.random()) \ .limit(1) \ .one_or_none() if sticker is None: sticker = base_query \ .order_by(func.random()) \ .limit(1) \ .one_or_none() # No stickers for tagging left :) if not sticker: call_tg_func(tg_chat, 'send_message', ['It looks like all stickers are already tagged :).'], {'reply_markup': get_main_keyboard(user)}) chat.cancel(bot) # Found a sticker. Send the messages chat.current_sticker = sticker send_tag_messages(chat, tg_chat, user, send_set_info=True)
def cleanup(bot, update, session, chat, user): """Triggering a one time conversion from text changes to tags.""" threshold = datetime.strptime('Jan 1 2000', '%b %d %Y') full_cleanup(session, threshold, update=update) call_tg_func(update.message.chat, 'send_message', ['Cleanup finished.'], {'reply_markup': get_main_keyboard(admin=True)})
def set_is_default_language(bot, update, session, chat, user): """Change the language of the user to the default langage.""" user.is_default_language = True keyboard = get_main_keyboard(user) text = "Your tags will now be marked as english and you won't see any sticker sets with non-english content." call_tg_func(update.message.chat, 'send_message', [text], {'reply_markup': keyboard})
def handle_check_user(session, bot, context): """Handle all actions from the check_user task.""" task = session.query(Task).get(context.payload) # Ban the user if CallbackResult(context.action).name == 'ban': task.user.banned = True call_tg_func(context.query, 'answer', ['User banned']) elif CallbackResult(context.action).name == 'unban': task.user.banned = False call_tg_func(context.query, 'answer', ['User ban reverted']) message = f'Your ban has been lifted.' call_tg_func(bot, 'send_message', [task.user.id, message], {'reply_markup': get_main_keyboard(task.user)}) # Revert user changes elif CallbackResult(context.action).name == 'revert': task.reverted = True revert_user_changes(session, task.user) call_tg_func(context.query, 'answer', ['All user changes reverted']) elif CallbackResult(context.action).name == 'undo_revert': task.reverted = False undo_user_changes_revert(session, task.user) call_tg_func(context.query, 'answer', ['User changes revert undone']) # Change the language of all changes of this task. elif CallbackResult(context.action).name == 'change_language': change_language_of_task_changes(session, task) call_tg_func(context.query, 'answer', ['Language changed']) elif CallbackResult(context.action).name == 'ok': if not task.reviewed: task.reviewed = True check_maintenance_chat(session, context.tg_chat, context.chat) keyboard = check_user_tags_keyboard(task) call_tg_func(context.query.message, 'edit_reply_markup', [], {'reply_markup': keyboard})
def undeluxe_user(bot, update, session, chat, user): """Change the language of the user to the non default langage.""" if not user.deluxe: return "You're already opt out of deluxe sticker packs." user.deluxe = False call_tg_func(update.message.chat, 'send_message', ["You will now see all sticker sets again."], {'reply_markup': get_main_keyboard(user)})
def deluxe_user(bot, update, session, chat, user): """Limit the result set of a user's search to deluxe stickers.""" if user.deluxe: return "You're already opt in for deluxe sticker packs." user.deluxe = True call_tg_func(update.message.chat, 'send_message', ["You will now only see deluxe sticker sets."], {'reply_markup': get_main_keyboard(user)})
def send_tagged_count_message(session, bot, user, chat): """Send a user a message that displays how many stickers he already tagged.""" if chat.tag_mode in [TagMode.STICKER_SET, TagMode.RANDOM]: count = session.query(Sticker) \ .join(Sticker.changes) \ .filter(Change.user == user) \ .count() call_tg_func( bot, 'send_message', [user.id, f'You already tagged {count} stickers. Thanks!'], {'reply_markup': get_main_keyboard(user)})
def handle_cancel_tagging(session, bot, context): """Cancel tagging for now.""" # Send a message to the user, which shows how many stickers he already tagged, # if the user was just tagging some stickers. # Otherwise just send the normal cancel success message. if not send_tagged_count_message(session, bot, context.user, context.chat): call_tg_func(context.query, 'answer', ['All active commands have been canceled']) call_tg_func(context.tg_chat, 'send_message', ['All running commands are canceled'], {'reply_markup': get_main_keyboard(context.user)}) context.chat.cancel(bot)
def start_tasks(bot, update, session, chat, user): """Start the handling of tasks.""" if not chat.is_maintenance and not chat.is_newsfeed: call_tg_func(update.message.chat, 'send_message', ['The chat is neither a maintenance nor a newsfeed chat'], {'reply_markup': get_main_keyboard(admin=True)}) return elif chat.current_task: return 'There already is a task active for this chat.' if chat.is_maintenance: check_maintenance_chat(session, update.message.chat, chat) if chat.is_newsfeed: check_newsfeed_chat(bot, session, chat)
def refresh_ocr(bot, update, session, chat, user): """Refresh all stickers and rescan for text.""" sticker_sets = session.query(StickerSet).all() call_tg_func(update.message.chat, 'send_message', args=[f'Found {len(sticker_sets)} sticker sets.']) count = 0 for sticker_set in sticker_sets: refresh_stickers(session, sticker_set, bot, refresh_ocr=True) count += 1 if count % 200 == 0: progress = f'Updated {count} sets ({len(sticker_sets) - count} remaining).' call_tg_func(update.message.chat, 'send_message', args=[progress]) call_tg_func(update.message.chat, 'send_message', ['All sticker sets are refreshed.'], {'reply_markup': get_main_keyboard(admin=True)})
def refresh_sticker_sets(bot, update, session, chat, user): """Refresh all stickers.""" sticker_sets = session.query(StickerSet) \ .filter(StickerSet.deleted.is_(False)) \ .all() progress = f'Found {len(sticker_sets)} sets.' call_tg_func(update.message.chat, 'send_message', args=[progress]) count = 0 for sticker_set in sticker_sets: refresh_stickers(session, sticker_set, bot) count += 1 if count % 500 == 0: progress = f'Updated {count} sets ({len(sticker_sets) - count} remaining).' call_tg_func(update.message.chat, 'send_message', args=[progress]) call_tg_func(update.message.chat, 'send_message', ['All sticker sets are refreshed.'], {'reply_markup': get_main_keyboard(admin=True)})
def random_set(bot, update, session, chat, user): """Get random sticker_set.""" sticker_count = func.count(Sticker.file_id).label("sticker_count") sticker_set = session.query(StickerSet)\ .join(StickerSet.stickers) \ .filter(StickerSet.is_default_language.is_(True)) \ .filter(StickerSet.nsfw.is_(False)) \ .filter(StickerSet.furry.is_(False)) \ .filter(StickerSet.banned.is_(False)) \ .group_by(StickerSet) \ .having(sticker_count > 0) \ .order_by(func.random()) \ .limit(1) \ .one_or_none() if sticker_set is not None: chat.current_sticker = sticker_set.stickers[0] call_tg_func(update.message.chat, 'send_sticker', args=[sticker_set.stickers[0].file_id], kwargs={'reply_markup': get_main_keyboard(user)})
def broadcast(bot, update, session, chat, user): """Broadcast a message to all users.""" message = update.message.text.split(' ', 1)[1].strip() chats = session.query(Chat) \ .filter(Chat.type == 'private') \ .all() call_tg_func(update.message.chat, 'send_message', args=[f'Sending broadcast to {len(chats)} chats.']) deleted = 0 for chat in chats: try: call_tg_func(bot, 'send_message', [chat.id, message], {'parse_mode': 'Markdown'}) # The chat doesn't exist any longer, delete it except BadRequest as e: if e.message == 'Chat not found': # noqa deleted += 1 session.delete(chat) continue # We are not allowed to contact this user. except Unauthorized: deleted += 1 session.delete(chat) continue # Sleep one second to not trigger flood prevention time.sleep(1) call_tg_func(update.message.chat, 'send_message', [f'All messages sent. Deleted {deleted} chats.'], {'reply_markup': get_main_keyboard(user)})
def check_maintenance_chat(session, tg_chat, chat, job=False): """Get the next task and send it to the maintenance channel.""" task = session.query(Task) \ .filter(Task.reviewed.is_(False)) \ .filter(Task.type.in_([ Task.CHECK_USER_TAGS, Task.REPORT, ])) \ .order_by(Task.created_at.asc()) \ .limit(1) \ .one_or_none() if task is None: chat.current_task = None # Don't send messages if we are calling this from a job. if job: return call_tg_func(tg_chat, 'send_message', ['There are no more tasks for processing.'], {'reply_markup': get_main_keyboard(admin=True)}) return chat.current_task = task if task.type == Task.CHECK_USER_TAGS: changes = task.changes_to_check # Compile task text text = [ f'User {task.user.username} ({task.user.id}) tagged {len(changes)} sticker' ] text.append(f'Detected at {task.created_at}: \n') for change in changes: if len(change.added_tags) > 0: text.append(f'Added: {change.added_tags_as_text()}') if len(change.removed_tags) > 0: text.append(f'Removed: {change.removed_tags_as_text()}') keyboard = check_user_tags_keyboard(task) elif task.type == Task.REPORT: # Compile task text text = ['Ban sticker set? \n'] for ban in task.sticker_set.reports: text.append(ban.reason) keyboard = get_report_keyboard(task) # Send first sticker of the set call_tg_func(tg_chat, 'send_sticker', args=[task.sticker_set.stickers[0].file_id]) text_chunks = split_text(text) while len(text_chunks) > 0: chunk = text_chunks.pop(0) # First chunks, just send the text if len(text_chunks) > 0: call_tg_func(tg_chat, 'send_message', args=[chunk]) # Last chunk. Send the text and the inline keyboard else: call_tg_func(tg_chat, 'send_message', args=[chunk], kwargs={'reply_markup': keyboard}) return True
def send_admin_help_text(bot, update, session, chat, user): """Send the admin help text.""" call_tg_func(update.message.chat, 'send_message', [admin_help_text], {'reply_markup': get_main_keyboard(user), 'parse_mode': 'Markdown'})
def stats(bot, update, session, chat, user): """Send a help text.""" # Users one_month_old = datetime.now() - timedelta(days=30) month_user_count = session.query(User) \ .join(User.inline_queries) \ .filter(InlineQuery.created_at > one_month_old) \ .group_by(User) \ .count() one_week_old = datetime.now() - timedelta(days=7) week_user_count = session.query(User) \ .join(User.inline_queries) \ .filter(InlineQuery.created_at > one_week_old) \ .group_by(User) \ .count() total_user_count = session.query(User).join( User.inline_queries).group_by(User).count() # Tags and emojis total_tag_count = session.query(sticker_tag.c.sticker_file_id) \ .join(Tag, sticker_tag.c.tag_name == Tag.name) \ .filter(Tag.emoji.is_(False)) \ .count() english_tag_count = session.query(Tag) \ .filter(Tag.is_default_language.is_(True)) \ .filter(Tag.emoji.is_(False)) \ .count() international_tag_count = session.query(Tag) \ .filter(Tag.is_default_language.is_(False)) \ .filter(Tag.emoji.is_(False)) \ .count() emoji_count = session.query(Tag).filter(Tag.emoji.is_(True)).count() # Stickers and sticker/text sticker/tag ratio sticker_count = session.query(Sticker).count() tagged_sticker_count = session.query(distinct(sticker_tag.c.sticker_file_id)) \ .join(Tag, sticker_tag.c.tag_name == Tag.name) \ .filter(Tag.emoji.is_(False)) \ .count() text_sticker_count = session.query(Sticker) \ .filter(Sticker.text.isnot(None)) \ .count() # Sticker set stuff sticker_set_count = session.query(StickerSet).count() normal_set_count = session.query(StickerSet) \ .filter(StickerSet.nsfw.is_(False)) \ .filter(StickerSet.furry.is_(False)) \ .filter(StickerSet.banned.is_(False)) \ .filter(StickerSet.is_default_language.is_(True)) \ .count() deluxe_set_count = session.query(StickerSet).filter( StickerSet.deluxe.is_(True)).count() nsfw_set_count = session.query(StickerSet).filter( StickerSet.nsfw.is_(True)).count() furry_set_count = session.query(StickerSet).filter( StickerSet.furry.is_(True)).count() banned_set_count = session.query(StickerSet).filter( StickerSet.banned.is_(True)).count() not_english_set_count = session.query(StickerSet).filter( StickerSet.is_default_language.is_(False)).count() # Inline queries total_queries_count = session.query(InlineQuery).count() last_day_queries_count = session.query(InlineQuery)\ .filter(InlineQuery.created_at > datetime.now() - timedelta(days=1)) \ .count() stats = f"""Users: => last week: {week_user_count} => last month: {month_user_count} => total: {total_user_count} Tags: => total: {total_tag_count} => english: {english_tag_count} => international: {international_tag_count} => emojis: {emoji_count} Stickers: => total: {sticker_count} => with tags: {tagged_sticker_count} => with text: {text_sticker_count} Sticker sets: => total: {sticker_set_count} => normal: {normal_set_count} => deluxe: {deluxe_set_count} => nsfw: {nsfw_set_count} => furry: {furry_set_count} => banned: {banned_set_count} => international: {not_english_set_count} Total queries : {total_queries_count} => last day: {last_day_queries_count} """ call_tg_func(update.message.chat, 'send_message', [stats], {'reply_markup': get_main_keyboard(admin=True)})