Блог Синявского
  • Разделы
  • Метки
  • Все статьи

Телеграм оповещения в приватных каналах

1

Telegram бот в приватном канале

Пишем систему оповещения через приватный канал в Telegram. В предыдущей статье я писал как можно совместить несовместимое, то есть асинхронное приложение с синхронной работой. В задаче оповещений тоже есть несколько тонкостей. Например задача по поимке chat id приватного канала. Обратимся к хорошо известному tornado, так как приложение будет работать по http. То есть мы будем наше сообщение отправлять в виде аргумента http запроса к телеграм боту. tornado будет слушать 80 порт и обрабатывать запросы, и передавать сообещения в наш приватный канал. Неплохо когда части программы существуют отдельно и развязны между собой посредством какого-то транспорта.

Создаем виртуальное окружение и добавляем следующие необходимые модули:

$ virtuaenv -p python2.7 env
$ source env/bin/activate

(env)$ pip install pyTelegramBotAPI tornado

Тонкости телеграм

При создании канала обязательно запоминаем имя канала @ChannelName После создания канала и добавления в него бота, мы не можем по имени канала отправить сообщения, нам нужен идентификатор chat_id. Его можно получить используя следующий алгоритм.

  1. Необходимо создать публичный канал
  2. Необходимо написать echo бота, который принимает сообщения и выводит их в консоль
  3. В наш канал надо добавить администратором нашего бота через по поиск по @имя_бота
  4. Пишем в канеле тестовое сообщение нашему боту
  5. Смотрим в консоли chat_id и запоминаем его - это идентификатор канала
  6. Переводим наш канал в приватный

Получим chat id для канала

$ nano telegram.py
# coding: utf8
from telebot import TeleBot

TOKEN = '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11'

if __name__ == "__main__":

    bot = TeleBot(TOKEN)

    result = bot.send_message(
        chat_id='@ChannelName',
        text='test_message_text',
        reply_markup=''
    )
    print result.chat.id
    bot.polling()

После запуска бота мы получим chat_id

(env) $ python telegram.py

-1001100397557

Напишем бота рассылок

Переводим канал в приватный, если это необходимо и теперь можно написать бота который будет оповещать. Так как по имени в приватный канал не получится отправлять сообщение.

$ nano telegram.py
# coding: utf8
from telebot import TeleBot
import tornado
from tornado.httpserver import HTTPServer
from tornado.ioloop import PeriodicCallback, IOLoop
from tornado.web import RequestHandler

CHAT_ID = -1001100397557
TOKEN = '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11'
SECRET = 'FBNbCyjVRU'

class SendMessageHandler(RequestHandler):
    def initialize(self, bot):
        self.bot = bot

    def get(self):
        message = self.get_argument('message')
        secret = self.get_argument('secret')

        if message and secret and secret == SECRET:
            self.bot.send_message(
                chat_id=CHAT_ID,
                text=message,
                reply_markup=''
            )

class BotPeriodicCallback(PeriodicCallback):
    def __init__(self, bot, callback_time, io_loop=None):
        if callback_time <= 0:
            raise ValueError("Periodic callback must have a positive callback_time")
        self.callback_time = callback_time
        self.io_loop = io_loop or IOLoop.current()
        self._running = False
        self._timeout = None
        self.bot = bot

    def bot_callback(self, timeout=20):
        if self.bot.skip_pending:
            self.bot.skip_pending = False
        updates = self.bot.get_updates(offset=(self.bot.last_update_id + 1), timeout=timeout)
        self.bot.process_new_updates(updates)

    def _run(self):
        if not self._running:
            return
        try:
            return self.bot_callback()
        except Exception:
            self.io_loop.handle_callback_exception(self.bot_callback)
        finally:
            self._schedule_next()

def main():
    bot = TeleBot(TOKEN)

    @bot.message_handler(commands=['start', 'help'])
    def send_welcome(message):
        bot.reply_to(message, u"Добро пожаловать! Вас приветствует робот рассылок!")

    @bot.message_handler(func=lambda message: True)
    def echo_all(message):
        bot.reply_to(message, 'По вопросам связанным с Telegram обращайтесь по телефону +7 950 027 66 17')

    ioloop = tornado.ioloop.IOLoop.instance()

    BotPeriodicCallback(bot, 1000, ioloop).start()

    host = '0.0.0.0'
    http_port = 8087

    http_server = HTTPServer(
        tornado.web.Application([
            (r'/send_message/(.*)/', SendMessageHandler, {'bot': bot}),
        ], debug=True)
    )
    http_server.listen(http_port, host)
    print("HTTP listening on %s:%d..." % (host, http_port))
    ioloop.start()

if __name__ == "__main__":
    main()

Таким образом мы можем отправить сообщение в наш канал сделав простой GET запрос.

http://<host>:8087/send_message/?secret=<secret>&message=<message>

Все готово!



  • ← сюда
  • туда →

comments powered by Disqus

Опубликовано

24.03.2017

Обновление

05.05.2022

Категории

python

Тэги

  • example 16
  • python 30
  • telegram 3
  • tornado 3

Всегда на связи

  • Блог Синявского - Ничего не переносить на завтра, это тоже проблема с прокастинацией?
  • © Алексей Синявский, по лицензии CC BY-SA если не указано иное.
  • С использованием Pelican. Тема: Elegant от Talha Mansoor