Esempio n. 1
0
def answer_photo_message(message: Message) -> None:
    """
    Handles situations when user sends a photo as a photo not as a file,
    namely answers to him that he need to send his photo as a file

    :param message: Message objects from Telebot that contains all the data
    about user's message
    :return: none
    """
    user = users.find_one(message)
    bot.send_message(user.chat_id, messages[user.language]['as_file'])
    log.info('%s sent photo as a photo.', user)
Esempio n. 2
0
def create_main_keyboard(message: Message) -> None:
    """
    Creates and renders the main keyboard

    :param message: message from a user
    :return: None
    """

    user = users.find_one(message)
    current_user_lang = user.language
    markup = types.ReplyKeyboardMarkup(one_time_keyboard=True,
                                       resize_keyboard=True)
    markup.row('Русский/English')
    markup.row(messages[current_user_lang]['top_cams'])
    markup.row(messages[current_user_lang]['top_lens'])
    markup.row(messages[current_user_lang]['top_countries'])
    bot.send_message(user.chat_id, messages[current_user_lang]['menu_header'],
                     reply_markup=markup)
Esempio n. 3
0
    def find_one(self, message: Message) -> User:
        """
        Look up a user by a message which we get together with request
        from Telegram

        :param message: object from Telegram that contains info about user's
        message and about himself
        :return: user object that represents a Telegram user in this bot
        """

        # look up user in the cache of the bot
        user = self.users.get(message.chat.id, None)

        if user:
            return user

        # otherwise look up the user in the database
        log.debug("Looking up the user in the database as it doesn't "
                  "appear in cache")
        query = (f'SELECT first_name, nickname, last_name, language '
                 f'FROM users '
                 f'WHERE chat_id=%s')

        parameters = message.chat.id,
        try:
            cursor = db.execute_query(query, parameters)
        except DatabaseConnectionError:

            # Even if the database in unreachable add user to dictionary
            # with users otherwise the bot will crash requesting this
            # user's info
            log.error('Cannot lookup the user with chat_id %d in database',
                      message.chat.id)
            msg = message.from_user
            user = self.add_new_one(message.chat.id,
                                    msg.first_name,
                                    msg.last_name,
                                    msg.username,
                                    language='en-US',
                                    add_to_db=False)
            return user

        if not cursor.rowcount:
            # This user uses our photoGPSbot for the first time as we
            # can't find him in the database
            log.info('Adding totally new user to the system...')
            msg = message.from_user
            user = self.add_new_one(message.chat.id,
                                    msg.first_name,
                                    msg.last_name,
                                    msg.username,
                                    language='en-US')
            bot.send_message(config.MY_TELEGRAM,
                             text=f'You have a new user! {user}')
            log.info('You have a new user! Welcome %s', user)

        # finally if the user wasn't found in the cache of the bot, but was
        # found in the database
        else:
            log.debug('User %d has been found in the database',
                      message.chat.id)

            user_data = cursor.fetchall()[0]
            user = self.add_new_one(message.chat.id,
                                    *user_data,
                                    add_to_db=False)

        return user
Esempio n. 4
0
def get_most_popular_items(item_type: str, message: Message) -> str:
    """
    Get the most common cameras/lenses/countries from database and
    make list of them

    :param item_type: string with column name to choose between cameras,
    lenses and countries
    :param message: telebot object with info about user and his message
    :return: string which is either list of most common
    cameras/lenses/countries or message which states that list is
    empty
    """

    user = users.find_one(message)

    def tuple_to_ordered_str_list(list_of_gadgets: Tuple[Tuple[str]]) -> str:
        """
        Converts Python list to ordered list as a string

        Example:
        1. Canon 80D
        2. iPhone 4S

        :param list_of_gadgets: tuple of tuples with string where every string
        is a name of a camera or lens or a country
        :return: ordered list as a string
        """

        string_roaster = ''
        index = 1
        for item in list_of_gadgets:
            if not item[0]:
                continue
            string_roaster += '{}. {}\n'.format(index, item[0])
            index += 1
        return string_roaster

    log.debug('Evaluating most popular things...')

    # This query returns item types in order where the first one item
    # has the highest number of occurrences
    # in a given column

    query = (f'SELECT {item_type} FROM photo_queries_table2 '
             f'GROUP BY {item_type} '
             f'ORDER BY count({item_type}) '
             'DESC')

    try:
        cursor = db.execute_query(query)
    except DatabaseConnectionError:
        log.error("Can't evaluate a list of the most popular items")
        return messages[user.language]['doesnt work']

    # Almost impossible case but still
    if not cursor.rowcount:
        log.warning('There is nothing in the main database table')
        bot.send_message(chat_id=config.MY_TELEGRAM,
                         text='There is nothing in the main database table')
        return messages[user.language]['no_top']

    popular_items = cursor.fetchall()
    log.info('Finish evaluating the most popular items')
    return tuple_to_ordered_str_list(popular_items[:30])
Esempio n. 5
0
def admin_menu(call: CallbackQuery) -> None:
    """
    Respond to commands from the admin menu

    :param call: object that contains info about user's reaction to an
    interactive keyboard

    :return: None
    """

    # Remove progress bar from pressed button
    bot.answer_callback_query(callback_query_id=call.id, show_alert=False)

    if call.data == 'off':
        if db.disconnect():
            bot.turn_off()
        else:
            log.error('Cannot stop bot.')
            bot.send_message(chat_id=config.MY_TELEGRAM,
                             text='Cannot stop bot.')
    elif call.data == 'last active':
        bot.send_message(config.MY_TELEGRAM,
                         text=get_admin_stat('last active users'))
    elif call.data == 'total number photos sent':
        bot.send_message(config.MY_TELEGRAM,
                         text=get_admin_stat('total number photos sent'))
    elif call.data == 'photos today':
        bot.send_message(config.MY_TELEGRAM,
                         text=get_admin_stat('photos today'))
    elif call.data == 'number of users':
        bot.send_message(config.MY_TELEGRAM,
                         text=get_admin_stat('number of users'))
    elif call.data == 'number of gadgets':
        bot.send_message(config.MY_TELEGRAM,
                         text=get_admin_stat('number of gadgets'))
    elif call.data == 'uptime':
        bot.send_message(config.MY_TELEGRAM,
                         text=get_admin_stat('uptime'))
Esempio n. 6
0
def handle_menu_response(message: Message) -> None:
    """
    Function that handles user's respond to the main keyboard

    :param message: user's message
    :return: None
    """

    # keyboard_hider = telebot.types.ReplyKeyboardRemove()
    current_user_lang = users.find_one(message).language
    user = users.find_one(message)

    if message.text == 'Русский/English':

        new_lang = users.find_one(message).switch_language()
        if current_user_lang != new_lang:
            bot.send_message(user.chat_id, messages[new_lang]
                             ['switch_lang_success'])
            create_main_keyboard(message)
        else:
            bot.send_message(user.chat_id, messages[new_lang]
                             ['switch_lang_failure'])
            create_main_keyboard(message)

    elif message.text == messages[current_user_lang]['top_cams']:
        log.info('User %s asked for top cams', user)
        bot.send_message(user.chat_id,
                         text=get_most_popular_items(item_type='camera_name',
                                                     message=message))
        log.info('List of most popular cameras '
                 'has been returned to %s', user)

        # in order not to check whether user has changed his nickname or
        # whatever every time his sends any request the bot will just check
        # it every time a user wants to get a statistic about the most
        # popular cameras
        users.compare_and_update(user, message)

    elif message.text == messages[current_user_lang]['top_lens']:
        log.info('User %s asked for top lens', user)
        bot.send_message(user.chat_id,
                         text=get_most_popular_items(item_type='lens_name',
                                                     message=message))
        log.info('List of most popular lens has been returned to %s', user)

    elif message.text == messages[current_user_lang]['top_countries']:
        log.info('User %s asked for top countries', user)
        lang_table_name = ('country_ru'
                           if current_user_lang == 'ru-RU' else 'country_en')
        bot.send_message(user.chat_id,
                         text=get_most_popular_items(item_type=lang_table_name,
                                                     message=message))
        log.info('List of most popular countries has '
                 'been returned to %s', user)

    elif (message.text.lower() == 'admin' and
          user.chat_id == int(config.MY_TELEGRAM)):
        # Creates inline keyboard with options for admin Function that handle
        # user interaction with the keyboard called admin_menu

        keyboard = types.InlineKeyboardMarkup()  # Make keyboard object
        button = types.InlineKeyboardButton  # just an alias to save space

        keyboard.add(button(text='Turn bot off', callback_data='off'))
        keyboard.add(button(text='Last active users',
                            callback_data='last active'))
        keyboard.add(button(text='Total number of photos were sent',
                            callback_data='total number photos sent'))
        keyboard.add(button(text='Number of photos today',
                            callback_data='photos today'))
        keyboard.add(button(text='Number of users',
                            callback_data='number of users'))
        keyboard.add(button(text='Number of gadgets',
                            callback_data='number of gadgets'))
        keyboard.add(button(text='Uptime', callback_data='uptime'))
        bot.send_message(config.MY_TELEGRAM,
                         'Admin commands', reply_markup=keyboard)

    else:
        log.info('%s sent text message.', user)

        # Answer to user that bot can't make a conversation with him
        bot.send_message(user.chat_id,
                         messages[current_user_lang]['dont_speak'])