Source code for spotted.handlers.spot

"""/spot command"""

from random import choice

from telegram import Update
from telegram.ext import (
    CallbackContext,
    CallbackQueryHandler,
    CommandHandler,
    ConversationHandler,
    MessageHandler,
    filters,
)

from spotted.data import Config, User
from spotted.data.data_reader import read_md
from spotted.utils import EventInfo, conv_cancel, get_confirm_kb, get_preview_kb

from .constants import CHAT_PRIVATE_ERROR, INVALID_MESSAGE_TYPE_ERROR, ConversationState


[docs] def spot_conv_handler() -> ConversationHandler: """Creates the spot conversation handler. The states are: - posting: submit the spot. Expects text, photo or many other formats - confirm: confirm or cancel the spot submission. Expects an inline query Returns: conversation handler """ return ConversationHandler( entry_points=[CommandHandler("spot", spot_cmd, filters=filters.ChatType.PRIVATE)], states={ ConversationState.POSTING.value: [ MessageHandler(~filters.COMMAND & ~filters.UpdateType.EDITED_MESSAGE, spot_msg), ], ConversationState.POSTING_PREVIEW.value: [ CallbackQueryHandler(spot_preview_query, pattern=r"^post_preview,.+") ], ConversationState.POSTING_CONFIRM.value: [ CallbackQueryHandler(spot_confirm_query, pattern=r"^post_confirm,.+") ], }, fallbacks=[CommandHandler("cancel", conv_cancel("spot"))], allow_reentry=False, )
[docs] async def spot_cmd(update: Update, context: CallbackContext) -> int: """Handles the /spot command. Checks that the user is in a private chat and it's not banned and start the post conversation Args: update: update event context: context passed by the handler Returns: next state of the conversation """ info = EventInfo.from_message(update, context) user = User(info.user_id) if not info.is_private_chat: # you can only post from a private chat await info.bot.send_message(chat_id=info.chat_id, text=CHAT_PRIVATE_ERROR) return ConversationState.END.value if user.is_banned: # the user is banned await info.bot.send_message(chat_id=info.chat_id, text="Sei stato bannato 😅") return ConversationState.END.value if user.is_pending: # there is already a post in pending await info.bot.send_message(chat_id=info.chat_id, text="Hai già un post in approvazione 🧐") return ConversationState.END.value await info.bot.send_message(chat_id=info.chat_id, text="Invia il post che vuoi pubblicare") return ConversationState.POSTING.value
[docs] async def spot_msg(update: Update, context: CallbackContext) -> int: """Handles the reply to the /spot command. Checks the message the user wants to post, and goes to the final step Args: update: update event context: context passed by the handler Returns: next state of the conversation """ info = EventInfo.from_message(update, context) if not info.is_valid_message_type: # the type is NOT supported await info.bot.send_message(chat_id=info.chat_id, text=INVALID_MESSAGE_TYPE_ERROR) return ConversationState.POSTING.value if info.message.entities: types = [entity.type for entity in info.message.entities] if "url" in types or "text_link" in types: await info.bot.send_message( chat_id=info.chat_id, text="Il post contiene link, vuoi pubblicare con l'anteprima?", reply_to_message_id=info.message_id, reply_markup=get_preview_kb(), ) return ConversationState.POSTING_PREVIEW.value await info.bot.send_message( chat_id=info.chat_id, text="Sei sicuro di voler pubblicare questo post?", reply_to_message_id=info.message_id, reply_markup=get_confirm_kb(), ) return ConversationState.POSTING_CONFIRM.value
[docs] async def spot_preview_query(update: Update, context: CallbackContext) -> int: """Handles the [ accept | reject ] callback. Let the user decide if wants to post the message with or without preview. - accept: the post will be published with preview - reject: the post will be published without preview Args: update: update event context: context passed by the handler Returns: next state of the conversation """ info = EventInfo.from_callback(update, context) arg = info.query_data.split(",")[1] info.user_data["show_preview"] = arg == "accept" await info.bot.edit_message_text( chat_id=info.chat_id, message_id=info.message_id, text="Sei sicuro di voler pubblicare questo post?", reply_markup=get_confirm_kb(), ) return ConversationState.POSTING_CONFIRM.value
[docs] async def spot_confirm_query(update: Update, context: CallbackContext) -> int: """Handles the [ submit | cancel ] callback. Creates the bid or cancels its creation. - submit: saves the post as pending and sends it to the admins for them to check. - cancel: cancels the current spot conversation Args: update: update event context: context passed by the handler Returns: next state of the conversation """ info = EventInfo.from_callback(update, context) arg = info.query_data.split(",")[1] text = "Qualcosa è andato storto!" if arg == "submit": # if the the user wants to publish the post if User(info.user_id).is_pending: # there is already a spot in pending by this user text = "Hai già un post in approvazione 🧐" elif await info.send_post_to_admins(): text = ( "Il tuo post è in fase di valutazione\n" f"Una volta pubblicato, lo potrai trovare su {Config.post_get('channel_tag')}" ) else: text = "Si è verificato un problema\nAssicurati che il tipo di post sia fra quelli consentiti" elif arg == "cancel": # if the the user changed his mind text = choice(read_md("no_strings").split("\n")) await info.bot.edit_message_text(chat_id=info.chat_id, message_id=info.message_id, text=text) return ConversationState.END.value