История одного соседа

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Приветствую всяк смотрящий на моем первом посте на Хабре. Очень долго я шел к тому, чтоб решиться написать свой неинтересный рассказ и разместить его тут. И да, это очередной пост о том, как кто-то написал скучного бота. Но я получил опыт, который возможно пригодится мне когда-то. Поэтому хотелось бы закрепить. Я расскажу об этапах создания некоторого функционала, идей и с чем я столкнулся и что я узнал не из интернета, а на своём опыте. Возможно кому-то будет полезно.

Однажды, зайдя в чат дома между катками доты, я увидел бота который дает возможность кикать пользователей путем голосования в чате. Нехитрое изобретение, я решил повторить и тогда я впервые познакомился с Telegram Bot API. В частности с библиотекой telebot. И тут первое что хотел бы отметить. На момент написания того самого первого бота, в данной библиотеке использовалась функция polling(), для поддержки бота в сети при простое. Однако она была не идеальной и через буквально 10 минут простоя бот всё же полностью терял соединение и не принимал запросы. На тот момент решением стало вот такая вещь:

def updateConnect():
    while True:
        api = requests.post(f"https://api.telegram.org/bot/{token}/getUpdates".format(token))
        time.sleep(10)

Бесконечный цикл запущенный в tread для постоянного подталкивания бота к подключению при простое каждые 10 с. Сейчас polling() заменили на infinity_polling() и возможно в этом нужны уже нет. Боты без веб хуков стали работать максимально стабильно.

Далее админы этих чатов предложили добавить функцию бана человека по всем чатам дома автоматически одной кнопкой. для этого бот конечно же должен находиться во всех чатах домов и быть администратором каждого чата. 15 минут и бот живет во всех чатах. Теперь власть над домом в моих руках ХАХАХАХА. И открыто поле для экспериментов. К слову, получилось даже больше чем хотелось. Функция была полезна тем, что если есть люди, которые по каким-то причинам попали в чат не своего дома и пытаются например использовать скрытую рекламу или слишком токсичные, можно разом посмотреть где этот человек еще сидит и прямо не лазя по чатам удалить всё нажав на соответствующие кнопки:

Вот пример.
Вот пример.

Код функции таков:

def armagedon(self, user=None):
        if user == None:
            user = self.userid
        keyword_ban = types.InlineKeyboardMarkup()
        Botton_all_chats = types.InlineKeyboardButton(text = "Удалить из всех чатов", callback_data='{"key": "ban_all", "chat": "all"}')
        keyword_ban.add(Botton_all_chats)
        for id in self.list_chats.keys():
            try:
                status_chat_user = bot.get_chat_member(id, user)
                if "left, kicked".count(status_chat_user.status) != 0:
                    continue
                title = self.list_chats[id]["title"]
                Botton = types.InlineKeyboardButton(text = title, callback_data='{"key": "ban_all", "chat":' + str(id) + '}')
                keyword_ban.add(Botton)
            except Exception:
                logging.error("Пользователь не смог вызвать команду армагедон.")
        bot.send_message(self.chat_id, "Выберите в каком чате вы хотите заблокировать пользователя [" + str(self.username) + "](tg://user?id\=" + str(self.userid) + "):", reply_markup=keyword_ban, parse_mode="MarkdownV2")

Вообще в целом тут хотелось бы остановиться на моменте передачи ботом callback_data через inline кнопки. а всё дело в том что у него есть ограничения по размену данной строки и к сожалению туда получится передать ни объект, ни словарь. И даже у самих строк передаваемых размер не должен превышать определенных значений. Поэтому было решено написать универсальный инструмент. для этого я по умолчанию использую в callback_data формат json, первым тегом у меня всегда идет KEY, что собственно передает название кнопки функции обработчику, а уже за ними вся остальная информация. Однако её должно быть максимально мало. поэтому зачастую приходится использовать ООП. Ставить функцию как метод класса, объявлять в нем объект какие-то параметры которые и присваивать нужные значения уже из этого объекта в функции обработчик, возможно, и обошлись бы и без создания класса, если бы callback_data вмещал в себя больше информации. Но есть как есть. Как выглядит мой типичный callback_data я показал в предыдущем листинге, а сейчас сам обработчик кнопок:

@bot.callback_query_handler(func=lambda call: True)
def callback_woker(call):
    call_data_json = call.data
    call_data = json.loads(call_data_json)
    if call_data['key'] == "kik":
        pass

Далее для развития новостного канала ЖК я добавил возможность писать боту в личку, а он в свою очередь отправляет в специально созданный заранее чат это сообщение. Админы нажатием кнопок могут исполнить с ним следующие действия:

Пример предложенной публикации
Пример предложенной публикации

В целом было просто написать это. Я думаю все понимают. просто скопировать всё. Однако тут я столкнулся с ограничениями, судя по всему, самого API. Дело в том что оказалось нужно предусмотреть все handler-ы для каждого типа сообщений. фото, видео и текст, но и это еще не всё. То что мы привыкли скидывать как собранное воедино и фото и видео контент в одном сообщении в телеграмме бот также может отправить как тип

sendMediaGroup

А всё дело в том что бот не может отправить такое сообщение с текстом. Он отправит файлы вместе

sendMediaGroup
sendMediaGroup

Без возможности сделать подпись как на следующем фото:

как хотелось бы
как хотелось бы

Поэтому предложить можно только одно фото или видео с текстом. от типов sendMediaGroup я отказался вообще.

Далее, будучи живя в новом ЖК, да на столько новым что тут не было первый ГОД маршруток до метро, а до метро на машине 15 минут чтоб вы понимали, люди кооперировались на такси или личных авто и так родился чат Попутчиков. Люди писали часто уточняли что как где встретиться и сколько мест есть, сколько стоит и так далее. в общем в чате на 1000 человек разобрать кто с кем едет тяжело и я предложил решение.

Поездка
Поездка

Нажав кнопку в чате, ищу попутчиков в такси, вызывается предложение, сначала мы выбираем:

  • количество свободных мест в авто;

  • откуда будет поездка (от какого корпуса или от какого метро);

  • выбирается час поездки;

  • выбирается минуты поездки(интервал в 15 минут для уменьшения кнопок на экране).

И по итогу мы получаем этакий бла бла кар, готовое решение в закрепленных сообщениях к которому можно присоединиться только стольким количествам человек которые могут влезть в авто. А также с помощью подключения к этой функции API Яндекс такси люди видят сколько примерно стоит такси. к сожалению не на момент вызова планируемого такси, а на момент создания поездки. Яндекс еще не умеет в предсказания... Нам помогут только кофейная гуща и карты таро.

Также бот фильтрует мат в сообщениях, проверяя их простой проверкой соответствия. Тут тоже есть о чем сказать. перед проверкой текста лучше всего, наверное, проводить лемматизацию текста. Очень советую изучить ребятам, которые еще не знакомы с этим понятием данный пункт и решение от Яндекса, библиотеку pymystem3. Но я подумал что это слишком нагрузит сервер. и не стал. просто проверяю корень слов на соответствие. Сервер чувствует себя нормально. Даже не пробовал лемматизировать все сообщения. Возможно в будущем попробую.

Есть еще небольшие функции, например рассылка по всем чатам сообщения одной командой, захват сообщения для предложения в новости прямо из чата, автоматическое поднятие объявления в чате продаж из рук в руки в ЖК (у всех же есть такой. там еще торгуют детской одеждой мамаши) и прочие мелкие нужности, которые делают жизнь нашего ЖК чуток лучше.

Стоимость сервера отбивает небольшая реклама, которая может быть прикреплена в каждое сообщение от бота. 2 строки ниже текста. и не мешает никому, и охват не маленький.

На этом рассказ оканчиваю. Не знаю интересно было или не очень, но вот решил поделиться что давно лежало в голове. Были конечно и не удавшиеся идеи. Самая яркая из них - т.к. в домах умные домофоны от Ростелеком, один из них выходит прям на очередь на маршрутку. было бы круто либо получать доступ к трансляции и показывать её прямо по прямой ссылке, либо, вероятно с помощью библиотеки cv2 попробовать сделать информацию о том насколько загружена остановка. Однако РТ не дает возможности вынуть поток видео куда либо с их сайта. либо я пока не решил эту задачу.

Git

mosx1/bot_chats (github.com)

Хейтеры, люблю вас.

Источник: https://habr.com/ru/post/713968/


Интересные статьи

Интересные статьи

Слитые хешированные пароли Slack, утечки данных в Twitter, сообщения о взломе менеджера паролей LastPass. И это только малая часть того, чем пестрели новостные ленты в 2022 году.В компании LastPass, п...
Вторая часть статьи, посвящённой созданию первого процессора с миллионом транзисторов. Ссылка на первую часть.
Привет, Хабр! Меня зовут Константин Шимановский. Почти 20 лет своей жизни я работаю с российской BI-платформой «Форсайт. Аналитическая платформа», и сейчас возглавляю Департамент управления проду...
В научной фантастике, особенно в классических произведениях американских писателей середины прошлого века, очень часто встречаются роботы. Чаще всего они помогают человеку, иногда живут...
Машинное обучение плотно укоренилось в различных сферах деятельности людей: от распознавания речи до медицинской диагностики. Популярность этого подхода столь велика, что его пытаются использов...