def t_webhook_route_handler(): """ Process messages from telegram bot :return: """ try: update = loads(request.data.decode('utf-8')) logging.info(update) inline = False if 'callback_query' in update: message = update['callback_query']['message'] inline = update['callback_query']['data'] else: message = update['message'] chat_id = message['chat']['id'] if '/help' == message['text'] or '/start' == message['text']: send_to_chat( "Инструкция по работе с ботом. Выберите раздел для просмотра доступных команд.\n\n" \ "/metrika — Модуль Яндекс.Метрики. Умеет присылать статистику за день и неделю.\n" \ "/github — Модуль GitHub. Может присылать уведомления о новых коммитах, pull-реквестах и открытии Issues." , chat_id) else: for plugin in CConfig.PLUGINS: plugin.telegram_command(message, inline) except Exception as e: logging.warning("Message process error: [%s]" % e) return 'OK'
def callback(chat_hash): """ GET payload from Github webhook and send it to handler :param chat_hash unique chat id """ payload = request.json try: repository_id = int(payload['repository']['id']) repository_name = payload['repository']['name'] logging.debug('Repository id: %s, chat hash: %s' % (repository_id, chat_hash)) handler = Notifications(payload) chat_id = handler.get_chat_id_by_hash(chat_hash) if request.headers['X-GitHub-Event'] == "ping": print("add repository {%s} to connected" % repository_name) if not get_repository(repository_id): gh_repository = Github_repositories.create(chat_id=chat_id, repository_id=repository_id, repository_name=repository_name) gh_repository.save() send_to_chat("Репозиторий %s был подключен" % repository_name, chat_id) gh_repository.close() else: handler.process() handler.send_to_chat(chat_hash) except Exception as e: logging.error("Github callback exception {%s}: [%s]" % (chat_hash, e)) print(bcolors.error("Github callback exception {%s}: [%s]" % (chat_hash, e))) return "{False}" return "{True}"
def github_delete_repository(self, repository_id, chat_id): try: repository = Github_repositories.get(Github_repositories.repository_id == repository_id) repository.delete_instance() except Github_repositories.DoesNotExist: pass send_to_chat("Репозиторий отключен.", chat_id)
def send_to_chat(self, chat_hash): if self.status_publish: try: chat = Chat.get((Chat.hash == chat_hash)) send_to_chat(self.get_output(), chat.chat_id) except Chat.DoesNotExist: return False return True
def telegram_command(self, message, inline=None): chat_id = message['chat']['id'] if '/notify_help' in message['text'] or '/notify' == message['text']: send_to_chat("/notify_start - получить ссылку для передачи сообщений в данный чат.", chat_id) elif '/notify_start' in message['text']: callback_hash = get_chat_token(chat_id) logging.info("Handler.notify_start: [%s, %s]" % (chat_id, callback_hash)) c_uri = "%s/%s/%s" % (CConfig.SERVER_HOST, self.module_name, callback_hash) send_to_chat("Ссылка для отправки сообщений в данный чат: %s\n\n" \ "Сообщение отправляйте в POST параметре message." % (c_uri), chat_id)
def get(self, chat_id, cmd): metrikas = Metrika.select().where(Metrika.chat_id == chat_id) message = "%s\n\n" % self.stats(cmd) for metrika in metrikas: try: metrikaAPI = MetrikaAPI(metrika.oauth_token, metrika.counter_id, chat_id) result = metrikaAPI.get_visit_statistics(cmd) if result: users, hits = result message += "%s:\n%d уникальных посетителей\n%d просмотров\n\n" % (metrika.counter_name, users, hits) except Exception as e: logging.warning("Metrika API exception: %s" % e) send_to_chat(message, chat_id)
def start(chat_id): # TODO: change tokens multi. try: token = Metrika_tokens.select().order_by(Metrika_tokens.id.desc()).where(Metrika_tokens.chat_id == chat_id).get() buttons = Handler.get_counters(token, "start") send_object_to_chat("Теперь выберите сайт, статистику которого хотите получать.\n", json.dumps({ 'inline_keyboard': buttons }), chat_id) except Metrika_tokens.DoesNotExist: send_to_chat("Для подключения счетчика, вам нужно авторизовать бота. " \ "Для этого, пройдите по ссылке и подтвердите доступ к счетчику. \n\n" \ "https://oauth.yandex.ru/authorize?response_type=code&client_id=%s&state=%s\n" % (CConfig.MODULES['metrika']['ID'], chat_id), chat_id) return
def telegram_command(self, message, inline=None): chat_id = message['chat']['id'] if inline: if inline.startswith('/github_delete'): repository_id = inline[14:] self.github_delete_repository(repository_id, chat_id) return if message['text'].startswith('/github_help') or message['text'] == '/github' or message['text'] == '/github@codex_bot': send_to_chat(self.github_help(chat_id), chat_id) if message['text'].startswith('/github_start'): self.github_start(chat_id) if message['text'].startswith('/github_stop'): self.github_stop(chat_id)
def github_stop(self, chat_id): repositories = Github_repositories.select().where(Github_repositories.chat_id == chat_id) if not len(repositories): send_to_chat("У вас не подключено ни одного репозитория.", chat_id) else: buttons = [ { 'text': repository.repository_name, 'callback_data': "/github_delete%s" % str(repository.repository_id) } for repository in repositories ] print(buttons) send_object_to_chat("Выберите репозиторий, который хотите отключить.\n", json.dumps({ 'inline_keyboard': [ buttons ] }), chat_id)
def github_start(self, chat_id): send_to_chat("Чтобы подключить репозиторий, выполните три простых шага.\n", chat_id) send_image_to_chat("1) Откройте настройки вашего репозитория", "images/github_start_step_1.jpg", chat_id) send_image_to_chat("2) Зайдите в раздел Webhooks & services и нажмите кнопку Add Webhook", "images/github_start_step_2.jpg", chat_id) callback_hash = append_chat(chat_id) logging.info("Append new chat: [%s, %s]" % (chat_id, callback_hash)) print("-- append to chat %s" % callback_hash) print(CConfig.SERVER_HOST) host_with_https = "https://%s" % CConfig.SERVER_HOST \ if not CConfig.SERVER_HOST.startswith("https") \ else CConfig.SERVER_HOST c_uri = "%s/%s/%s" % (host_with_https, self.module_name, callback_hash) msg = "3) Вставьте в поле Payload URL следующую ссылку.\n\n%s\n\n" \ "В поле «Which events would you like to trigger this webhook?» \nвыберите \n" \ "«Let me select individual events» и отметье следующие флажки: \n\n" \ "- Issues\n- Pull request\n- Push\n\nНажмите на кнопку «Add Webhook»\n\n" % c_uri send_to_chat(msg, chat_id)
def metrika_stop(self, chat_id): try: token = Metrika_tokens.get(Metrika_tokens.chat_id == chat_id) counters = Metrika.select().where(Metrika.chat_id == chat_id) if len(counters): buttons = [] buttons_row = [] for counter in counters: buttons_row.append( {'text': counter.counter_name, 'callback_data': "/metrika_%s%s#%s" % ("stop", token.id, counter.counter_id)}) CConfig.CACHE['metrika_%s_%s' % (token.id, counter.counter_id)] = counter.counter_name if len(buttons_row) == 2: buttons.append(buttons_row[:]) buttons_row = [] if len(buttons_row): buttons.append(buttons_row[:]) send_object_to_chat("Выберите сайт, который хотите отключить.\n", json.dumps({ 'inline_keyboard': buttons }), chat_id) else: send_to_chat("Подключенных счетчиков не найдено.", chat_id) except Metrika_tokens.DoesNotExist: send_to_chat("Токен не найден.", chat_id)
def telegram_command(self, message, inline=False): chat_id = message['chat']['id'] if inline: if inline.startswith('/metrika_start'): cmd = inline[14:] token_id, counter_id = cmd.split("#") self.add(chat_id, token_id, counter_id) self.metrika_help(chat_id) if inline.startswith('/metrika_stop'): cmd = inline[13:] token_id, counter_id = cmd.split("#") self.delete(chat_id, token_id, counter_id) self.help(chat_id) return if message['text'] == '/metrika' or message['text'] == '/metrika@codex_bot': send_to_chat(self.help(chat_id), chat_id) if message['text'].startswith('/metrika_start'): Handler.start(chat_id) if message['text'].startswith('/metrika_stop'): self.metrika_stop(chat_id) if message['text'].startswith('/metrika_help'): self.metrika_help(chat_id) if message['text'].startswith('/metrika_get'): logging.info("Get metrika statistics: [%s]" % (chat_id)) self.get(chat_id) if message['text'].startswith('/metrika_counters'): params = message['text'].split(' ') if len(params) == 2 and params[0] == "/metrika_counters": metrikaAPI = MetrikaAPI(params[1], '', chat_id) send_to_chat(metrikaAPI.get_counters(), chat_id) else: send_to_chat(self.help(), chat_id) if message["text"].startswith("/today"): self.get(chat_id, "today") if message["text"].startswith("/weekly"): self.get(chat_id, "weekly") if message["text"].startswith("/monthly"): self.get(chat_id, "monthly")
def delete(self, chat_id, token_id, counter_id): try: token = Metrika_tokens.get(Metrika_tokens.id == token_id) try: counter = Metrika.select().where((Metrika.counter_id == counter_id) & (Metrika.chat_id == chat_id)).get() counter.delete_instance() counter_name = CConfig.CACHE['metrika_%s_%s' % (token_id, counter_id)] send_to_chat("Готово! Сайт <%s> отключен от модуля." % counter_name, chat_id) except Metrika.DoesNotExist: send_to_chat("Сайт не найден.", chat_id) except Metrika_tokens.DoesNotExist: send_to_chat("Ошибка токена <%s>." % token_id, chat_id)
def add(self, chat_id, token_id, counter_id): # TODO: Params as hash id in cache try: token = Metrika_tokens.get(Metrika_tokens.id == token_id) try: counter = Metrika.select().where((Metrika.counter_id == counter_id) & (Metrika.chat_id == chat_id)).get() send_to_chat("Счетчик <%s> уже прикреплен к данному чату." % counter.counter_name, chat_id) except Metrika.DoesNotExist: counter_name = CConfig.CACHE['metrika_%s_%s' % (token_id, counter_id)] metrika = Metrika.create(oauth_token=token.token, counter_id=counter_id, chat_id=chat_id, counter_name=counter_name, client_id=CConfig.MODULES['metrika']['ID']) metrika.save() send_to_chat("Готово! Сайт <%s> успешно подключен." % counter_name, chat_id) except Metrika_tokens.DoesNotExist: send_to_chat("Ошибка токена <%s>." % token_id, chat_id)
def send(self): if not self.error: send_to_chat(self.get(), self.chat_id, CConfig.MODULES['api_token'])
def metrika_help(self, chat_id): send_to_chat("/today — Получить значения счетчиков за день. \n\n" "/weekly— Показатели за неделю.\n\n" "/monthly— Показатели за месяц.\n\n" "/metrika_stop — Отключить счетчик.", chat_id)