Beispiel #1
0
def post_cmd(update: Update, context: CallbackContext) -> int:
    """Handles the /post command
    Checks that the user is in a private chat and it's not banned and start the post process

    Args:
        update (Update): update event
        context (CallbackContext): context passed by the handler

    Returns:
        int: value passed to the handler, if requested
    """
    info = get_message_info(update, context)
    if update.message.chat.type != "private":  # you can only post with a private message
        info['bot'].send_message(
            chat_id=info['chat_id'],
            text="Non puoi usare quest comando ora\nChatta con @tendTo_bot in privato",
        )
        return STATE['end']

    if MemeData.is_banned(user_id=info['sender_id']):  # you are banned
        info['bot'].send_message(chat_id=info['chat_id'], text="Sei stato bannato 😅")
        return STATE['end']

    # have already a post in pending
    if MemeData.is_pending(user_id=info['sender_id']):
        info['bot'].send_message(chat_id=info['chat_id'], text="Hai già un post in approvazione 🧐")
        return STATE['end']

    info['bot'].send_message(chat_id=info['chat_id'], text="Invia il post che vuoi pubblicare")
    return STATE['posting']
Beispiel #2
0
def approve_yes_callback(
        update: Update,
        context: CallbackContext) -> Tuple[str, InlineKeyboardMarkup, int]:
    """Handles the approve_yes callback.
    Approves the post, deleting it from the pending_post table, publishing it in the channel \
    and putting it in the published post table

    Args:
        update (Update): update event
        context (CallbackContext): context passed by the handler

    Returns:
        Tuple[str, InlineKeyboardMarkup, int]: text and replyMarkup that make up the reply, new conversation state
    """
    info = get_callback_info(update, context)
    n_approve = MemeData.set_admin_vote(info['sender_id'], info['message_id'],
                                        info['chat_id'], True)

    # The post passed the approval phase and is to be published
    if n_approve >= config_map['meme']['n_votes']:
        message = update.callback_query.message
        user_id = MemeData.get_user_id(g_message_id=info['message_id'],
                                       group_id=info['chat_id'])
        published_post = send_post_to(message=message,
                                      bot=info['bot'],
                                      destination="channel")

        if config_map['meme'][
                'comments']:  # if comments are enabled, save the user_id, so the user can be credited
            context.bot_data[
                f"{published_post.chat_id},{published_post.message_id}"] = user_id

        info['bot'].send_message(
            chat_id=user_id,
            text="Il tuo ultimo post è stato approvato")  # notify the user

        # Shows the list of admins who approved the pending post and removes it form the db
        show_admins_votes(chat_id=info['chat_id'],
                          message_id=info['message_id'],
                          bot=info['bot'],
                          approve=True)
        MemeData.remove_pending_meme(info['message_id'], info['chat_id'])
        return None, None, None

    if n_approve != -1:  # the vote changed
        keyboard = update.callback_query.message.reply_markup.inline_keyboard
        return None, update_approve_kb(keyboard,
                                       info['message_id'],
                                       info['chat_id'],
                                       approve=n_approve), None

    return None, None, None
Beispiel #3
0
def send_helper_message(user_id: int,
                        chat_id: int,
                        reply_message_id: int,
                        bot: Bot,
                        reply_markup: InlineKeyboardMarkup = None) -> Message:
    """Sends an helper message to show the author of the post, and to vote on the post if comments are enabled

    Args:
        user_id (int): id of the user that originated the post
        chat_id (int): id of the chat to which send the helper message
        reply_message_id (int): id of the message the helper message will reply to
        bot (Bot): bot
        reply_markup (InlineKeyboardMarkup, optional): voting Inline Keyboard. Defaults to None.

    Returns:
        Message: helper message
    """
    sign = anonym_name()
    if MemeData.is_credited(user_id=user_id):  # the user wants to be credited
        username = bot.getChat(user_id).username
        if username:
            sign = "@" + username

    return bot.send_message(chat_id=chat_id,
                            text=f"by: {sign}",
                            reply_markup=reply_markup,
                            reply_to_message_id=reply_message_id)
Beispiel #4
0
def vote_no_callback(
        update: Update,
        context: CallbackContext) -> Tuple[str, InlineKeyboardMarkup, int]:
    """Handles the vote_no callback.
    Downvotes the post

    Args:
        update (Update): update event
        context (CallbackContext): context passed by the handler

    Returns:
        Tuple[str, InlineKeyboardMarkup, int]: text and replyMarkup that make up the reply, new conversation state
    """
    info = get_callback_info(update, context)
    n_downvotes, was_added = MemeData.set_user_vote(
        user_id=info['sender_id'],
        c_message_id=info['message_id'],
        channel_id=info['chat_id'],
        vote=False)

    if n_downvotes != -1:  # the vote changed
        if was_added:
            info['bot'].answerCallbackQuery(callback_query_id=info['query_id'],
                                            text="Hai messo un 👎")
        else:
            info['bot'].answerCallbackQuery(callback_query_id=info['query_id'],
                                            text="Hai tolto il 👎")
        keyboard = update.callback_query.message.reply_markup.inline_keyboard
        return None, update_vote_kb(keyboard,
                                    info['message_id'],
                                    info['chat_id'],
                                    downvote=n_downvotes), None

    return None, None, None
Beispiel #5
0
def settings_credit_callback(
        update: Update,
        context: CallbackContext) -> Tuple[str, InlineKeyboardMarkup, int]:
    """Handles the settings_foto_cane callback.
    Adds the user_id to the table of credited users, if it wasn't already there

    Args:
        update (Update): update event
        context (CallbackContext): context passed by the handler

    Returns:
        Tuple[str, InlineKeyboardMarkup, int]: text and replyMarkup that make up the reply, new conversation state
    """
    username = update.callback_query.from_user.username
    user_id = update.callback_query.from_user.id

    # if the user was already credited
    if MemeData.become_credited(user_id=user_id):
        text = "Sei già creditato nei post\n"
    else:
        text = "La tua preferenza è stata aggiornata\n"

    if username:  # the user has a valid username
        text += f"I tuoi post avranno come credit @{username}"
    else:
        text += "**ATTENZIONE:**\nNon hai nessun username associato al tuo account telegram\n"\
            "Se non lo aggiungi, non sarai creditato"
    return text, None, None
Beispiel #6
0
def approve_no_callback(
        update: Update,
        context: CallbackContext) -> Tuple[str, InlineKeyboardMarkup, int]:
    """Handles the approve_yes callback.
    Approves the post, deleting it from the pending_post table, publishing it in the channel \
    and putting it in the published post table

    Args:
        update (Update): update event
        context (CallbackContext): context passed by the handler

    Returns:
        Tuple[str, InlineKeyboardMarkup, int]: text and replyMarkup that make up the reply, new conversation state
    """
    info = get_callback_info(update, context)
    n_reject = MemeData.set_admin_vote(info['sender_id'], info['message_id'],
                                       info['chat_id'], False)

    # The post has been refused
    if n_reject >= config_map['meme']['n_votes']:
        user_id = MemeData.get_user_id(g_message_id=info['message_id'],
                                       group_id=info['chat_id'])
        info['bot'].send_message(
            chat_id=user_id,
            text=
            "Il tuo ultimo post è stato rifiutato\nPuoi controllare le regole con /rules"
        )  # notify the user

        # Shows the list of admins who refused the pending post and removes it form the db
        show_admins_votes(chat_id=info['chat_id'],
                          message_id=info['message_id'],
                          bot=info['bot'],
                          approve=False)
        MemeData.remove_pending_meme(info['message_id'], info['chat_id'])
        return None, None, None

    if n_reject != -1:  # the vote changed
        keyboard = update.callback_query.message.reply_markup.inline_keyboard
        return None, update_approve_kb(keyboard,
                                       info['message_id'],
                                       info['chat_id'],
                                       reject=n_reject), None

    return None, None, None
Beispiel #7
0
def ban_cmd(update: Update, context: CallbackContext):
    """Handles the /ban command
    Ban a user by replying to one of his pending posts with /ban

    Args:
        update (Update): update event
        context (CallbackContext): context passed by the handler
    """
    info = get_message_info(update, context)
    if info['chat_id'] == config_map['meme']['group_id']:  # you have to be in the admin group
        g_message_id = update.message.reply_to_message.message_id
        user_id = MemeData.get_user_id(g_message_id=g_message_id, group_id=info['chat_id'])

        if user_id is None:
            info['bot'].send_message(chat_id=info['chat_id'], text="Per bannare qualcuno, rispondi al suo post con /ban")
            return

        MemeData.ban_user(user_id=user_id)
        MemeData.remove_pending_meme(g_message_id=g_message_id, group_id=info['chat_id'])
        info['bot'].delete_message(chat_id=info['chat_id'], message_id=g_message_id)
        info['bot'].send_message(chat_id=info['chat_id'], text="L'utente è stato bannato")
Beispiel #8
0
def reply_cmd(update: Update, context: CallbackContext):
    """Handles the /reply command
    Send a message to a user by replying to one of his pending posts with /reply + the message you want to send

    Args:
        update (Update): update event
        context (CallbackContext): context passed by the handler
    """
    info = get_message_info(update, context)
    if info['chat_id'] == config_map['meme']['group_id']:  # you have to be in the admin group
        g_message_id = update.message.reply_to_message.message_id
        user_id = MemeData.get_user_id(g_message_id=g_message_id, group_id=info['chat_id'])
        if user_id is None or len(info['text']) <= 7:
            info['bot'].send_message(
                chat_id=info['chat_id'],
                text=
                "Per mandare un messaggio ad un utente, rispondere al suo post con /reply seguito da ciò che gli si vuole dire"
            )
            return
        info['bot'].send_message(chat_id=user_id,
                                 text="COMUNICAZIONE DEGLI ADMIN SUL TUO ULTIMO POST:\n" + info['text'][7:].strip())
Beispiel #9
0
def sban_cmd(update: Update, context: CallbackContext):
    """Handles the /sban command
    Sban a user by using this command and listing all the user_id to sban

    Args:
        update (Update): update event
        context (CallbackContext): context passed by the handler
    """
    info = get_message_info(update, context)
    if info['chat_id'] == config_map['meme']['group_id']:  # you have to be in the admin group
        if len(context.args) == 0:  # if no args have been passed
            info['bot'].send_message(chat_id=info['chat_id'], text="[uso]: /sban <user_id1> [...user_id2]")
            return
        for user_id in context.args:
            # the sban was unsuccesful (maybe the user id was not found)
            if not MemeData.sban_user(user_id=user_id):
                break
        else:
            info['bot'].send_message(chat_id=info['chat_id'], text="Sban effettuato")
            return
        info['bot'].send_message(chat_id=info['chat_id'], text="Uno o più sban sono falliti")
Beispiel #10
0
def settings_anonimo_callback(
        update: Update,
        context: CallbackContext) -> Tuple[str, InlineKeyboardMarkup, int]:
    """Handles the settings_sei_ghei callback.
    Removes the user_id from the table of credited users, if present

    Args:
        update (Update): update event
        context (CallbackContext): context passed by the handler

    Returns:
        Tuple[str, InlineKeyboardMarkup, int]: text and replyMarkup that make up the reply, new conversation state
    """
    user_id = update.callback_query.from_user.id
    # if the user was already anonym
    if MemeData.become_anonym(user_id=user_id):
        text = "Sei già anonimo"
    else:
        text = "La tua preferenza è stata aggiornata\n"\
            "Ora i tuoi post saranno anonimi"

    return text, None, None
Beispiel #11
0
def show_admins_votes(chat_id: int, message_id: int, bot: Bot, approve: bool):
    """After a post is been approved or rejected, shows the admins that aproved or rejected it

    Args:
        chat_id (int): id of the admin group
        message_id (int): id of the post in question in the group
        bot (Bot): bot
        approve (bool): whether the vote is approve or reject
    """
    admins = MemeData.get_admin_list_votes(g_message_id=message_id,
                                           group_id=chat_id,
                                           approve=approve)
    text = "Approvato da:\n" if approve else "Rifiutato da:\n"
    for admin in admins:
        username = bot.get_chat(admin).username
        text += f"@{username}\n" if username else f"{bot.get_chat(admin).first_name}\n"

    bot.edit_message_reply_markup(chat_id=chat_id,
                                  message_id=message_id,
                                  reply_markup=None)
    bot.send_message(chat_id=chat_id,
                     text=text,
                     reply_to_message_id=message_id)
Beispiel #12
0
def send_post_to(message: Message,
                 bot: Bot,
                 destination: str,
                 user_id: int = None) -> Message:
    """Sends the post to the specified destination:

    admin -> to the admin group, so it can be approved

    channel -> to the channel, so it can be ejoyed by the users (and voted, if comments are disabled)

    channel_group -> to the group associated to the channel, so that users can vote the post (if comments are enabled)

    Args:
        message (Message): message that contains the post to send
        bot (Bot): bot
        destination (str): destination of the message (admin | channel | channel_group)
        user_id (int, optional): id of the user that originated the post. Defaults to None.
    Returns:
        Message: message used to send a post to a specific destination
    """
    text = message.text
    photo = message.photo
    voice = message.voice
    audio = message.audio
    video = message.video
    animation = message.animation
    sticker = message.sticker
    caption = message.caption

    reply_markup = None
    post_message = None

    if destination == "admin":  # send the post to the admin group so it can be approved
        chat_id = config_map['meme']['group_id']
        reply_markup = get_approve_kb()
    elif destination == "channel":  # send the post to the channel...
        chat_id = config_map['meme']['channel_id']
        if not config_map['meme'][
                'comments']:  # ... append the voting Inline Keyboard, if comments are not to be supported
            reply_markup = get_vote_kb()
    elif destination == "channel_group":  # sends a support message with the voting Inline Keyboard in the comment session
        post_message = send_helper_message(
            user_id=user_id,
            chat_id=config_map['meme']['channel_group_id'],
            reply_message_id=message.message_id,
            bot=bot,
            reply_markup=get_vote_kb())
    else:
        print("[error] send_message_to: unvalid destination")
        return None

    if post_message is None:
        if text:
            post_message = bot.sendMessage(chat_id=chat_id,
                                           text=text,
                                           reply_markup=reply_markup)
        elif photo:
            post_message = bot.sendPhoto(chat_id=chat_id,
                                         photo=photo[-1],
                                         caption=caption,
                                         reply_markup=reply_markup)
        elif voice:
            post_message = bot.sendVoice(chat_id=chat_id,
                                         voice=voice,
                                         reply_markup=reply_markup)
        elif audio:
            post_message = bot.sendAudio(chat_id=chat_id,
                                         audio=audio,
                                         reply_markup=reply_markup)
        elif video:
            post_message = bot.sendVideo(chat_id=chat_id,
                                         video=video,
                                         caption=caption,
                                         reply_markup=reply_markup)
        elif animation:
            post_message = bot.sendAnimation(chat_id=chat_id,
                                             animation=animation,
                                             reply_markup=reply_markup)
        elif sticker:
            post_message = bot.sendSticker(chat_id=chat_id,
                                           sticker=sticker,
                                           reply_markup=reply_markup)

    if destination == "admin":  # insert the post among the pending ones
        MemeData.insert_pending_post(user_message=message,
                                     admin_message=post_message)
    elif destination == "channel":  # insert the post among the published ones and show the credtit...
        if not config_map['meme'][
                'comments']:  # ... but only if the user can vote directly on the post
            MemeData.insert_published_post(post_message)
            send_helper_message(user_id=user_id,
                                chat_id=config_map['meme']['channel_id'],
                                reply_message_id=post_message.message_id,
                                bot=bot)
    elif destination == "channel_group":  # insert the first comment among the published posts, so that votes can be tracked
        MemeData.insert_published_post(post_message)

    return post_message