def test_webhook(self): print('Testing Webhook') self._setup_updater('', messages=0) d = self.updater.dispatcher d.addTelegramMessageHandler( self.telegramHandlerTest) # Select random port for travis port = randrange(1024, 49152) self.updater.start_webhook('127.0.0.1', port, url_path='TOKEN', cert='./tests/test_updater.py', key='./tests/test_updater.py') sleep(0.5) # SSL-Wrapping will fail, so we start the server without SSL Thread(target=self.updater.httpd.serve_forever).start() # Now, we send an update to the server via urlopen message = Message(1, User(1, "Tester"), datetime.now(), Chat(1, "group", title="Test Group")) message.text = "Webhook Test" update = Update(1) update.message = message try: payload = bytes(update.to_json(), encoding='utf-8') except TypeError: payload = bytes(update.to_json()) header = { 'content-type': 'application/json', 'content-length': str(len(payload)) } r = Request('http://127.0.0.1:%d/TOKEN' % port, data=payload, headers=header) urlopen(r) sleep(1) self.assertEqual(self.received_message, 'Webhook Test') print("Test other webhook server functionalities...") request = Request('http://localhost:%d/webookhandler.py' % port) response = urlopen(request) self.assertEqual(b'', response.read()) self.assertEqual(200, response.code) request.get_method = lambda: 'HEAD' response = urlopen(request) self.assertEqual(b'', response.read()) self.assertEqual(200, response.code) # Test multiple shutdown() calls self.updater.httpd.shutdown() self.updater.httpd.shutdown() self.assertTrue(True)
def test_webhook_no_ssl(self): print("Testing Webhook without SSL") bot = MockBot("", messages=0) self.updater.bot = bot d = self.updater.dispatcher d.addTelegramMessageHandler(self.telegramHandlerTest) # Select random port for travis port = randrange(1024, 49152) self.updater.start_webhook("127.0.0.1", port) sleep(0.5) # Now, we send an update to the server via urlopen message = Message(1, User(1, "Tester 2"), datetime.now(), GroupChat(1, "Test Group 2")) message.text = "Webhook Test 2" update = Update(1) update.message = message try: payload = bytes(update.to_json(), encoding="utf-8") except TypeError: payload = bytes(update.to_json()) header = {"content-type": "application/json", "content-length": str(len(payload))} r = Request("http://127.0.0.1:%d/" % port, data=payload, headers=header) urlopen(r) sleep(1) self.assertEqual(self.received_message, "Webhook Test 2")
def test_authorized_only_exception(default_conf, mocker): mocker.patch.dict('freqtrade.rpc.telegram._CONF', default_conf) update = Update(randint(1, 100)) update.message = Message(randint(1, 100), 0, datetime.utcnow(), Chat(0, 0)) @authorized_only def dummy_handler(*args, **kwargs) -> None: raise Exception('test') dummy_handler(MagicMock(), update)
def mock_update(self, text): message = Message(0, User(0, 'Testuser'), None, Chat(0, Chat.GROUP), bot=self) message.text = text update = Update(0) if self.edited: update.edited_message = message else: update.message = message return update
def mockUpdate(self, text): message = Message(0, None, None, None) message.text = text update = Update(0) if self.edited: update.edited_message = message else: update.message = message return update
def test_webhook(self): print("Testing Webhook") bot = MockBot("", messages=0) self.updater.bot = bot d = self.updater.dispatcher d.addTelegramMessageHandler(self.telegramHandlerTest) # Select random port for travis port = randrange(1024, 49152) self.updater.start_webhook( "127.0.0.1", port, url_path="TOKEN", cert="./tests/test_updater.py", key="./tests/test_updater.py" ) sleep(0.5) # SSL-Wrapping will fail, so we start the server without SSL Thread(target=self.updater.httpd.serve_forever).start() # Now, we send an update to the server via urlopen message = Message(1, User(1, "Tester"), datetime.now(), GroupChat(1, "Test Group")) message.text = "Webhook Test" update = Update(1) update.message = message try: payload = bytes(update.to_json(), encoding="utf-8") except TypeError: payload = bytes(update.to_json()) header = {"content-type": "application/json", "content-length": str(len(payload))} r = Request("http://127.0.0.1:%d/TOKEN" % port, data=payload, headers=header) urlopen(r) sleep(1) self.assertEqual(self.received_message, "Webhook Test") print("Test other webhook server functionalities...") request = Request("http://localhost:%d/webookhandler.py" % port) response = urlopen(request) self.assertEqual(b"", response.read()) self.assertEqual(200, response.code) request.get_method = lambda: "HEAD" response = urlopen(request) self.assertEqual(b"", response.read()) self.assertEqual(200, response.code) # Test multiple shutdown() calls self.updater.httpd.shutdown() self.updater.httpd.shutdown() self.assertTrue(True)
def test_webhook(self): self._setup_updater('', messages=0) d = self.updater.dispatcher handler = MessageHandler([], self.telegramHandlerTest) d.addHandler(handler) ip = '127.0.0.1' port = randrange(1024, 49152) # Select random port for travis self.updater.start_webhook(ip, port, url_path='TOKEN', cert='./tests/test_updater.py', key='./tests/test_updater.py', webhook_url=None) sleep(0.5) # SSL-Wrapping will fail, so we start the server without SSL Thread(target=self.updater.httpd.serve_forever).start() # Now, we send an update to the server via urlopen message = Message(1, User(1, "Tester"), datetime.now(), Chat(1, "group", title="Test Group")) message.text = "Webhook Test" update = Update(1) update.message = message self._send_webhook_msg(ip, port, update.to_json(), 'TOKEN') sleep(1) self.assertEqual(self.received_message, 'Webhook Test') print("Test other webhook server functionalities...") response = self._send_webhook_msg(ip, port, None, 'webookhandler.py') self.assertEqual(b'', response.read()) self.assertEqual(200, response.code) response = self._send_webhook_msg( ip, port, None, 'webookhandler.py', get_method=lambda: 'HEAD') self.assertEqual(b'', response.read()) self.assertEqual(200, response.code) # Test multiple shutdown() calls self.updater.httpd.shutdown() self.updater.httpd.shutdown() self.assertTrue(True)
def test_authorized_only_unauthorized(default_conf, mocker): mocker.patch.dict('freqtrade.rpc.telegram._CONF', default_conf) chat = Chat(0xdeadbeef, 0) update = Update(randint(1, 100)) update.message = Message(randint(1, 100), 0, datetime.utcnow(), chat) state = {'called': False} @authorized_only def dummy_handler(*args, **kwargs) -> None: state['called'] = True dummy_handler(MagicMock(), update) assert state['called'] is False
def test_webhook_no_ssl(self, monkeypatch, updater): q = Queue() monkeypatch.setattr('telegram.Bot.set_webhook', lambda *args, **kwargs: True) monkeypatch.setattr('telegram.Bot.delete_webhook', lambda *args, **kwargs: True) monkeypatch.setattr('telegram.ext.Dispatcher.process_update', lambda _, u: q.put(u)) ip = '127.0.0.1' port = randrange(1024, 49152) # Select random port for travis updater.start_webhook(ip, port, webhook_url=None) sleep(.2) # Now, we send an update to the server via urlopen update = Update(1, message=Message(1, User(1, '', False), None, Chat(1, ''), text='Webhook 2')) self._send_webhook_msg(ip, port, update.to_json()) sleep(.2) assert q.get(False) == update
def getUpdates(self, offset=None, limit=100, timeout=0): """Use this method to receive incoming updates using long polling. Args: offset: Identifier of the first update to be returned. Must be greater by one than the highest among the identifiers of previously received updates. By default, updates starting with the earliest unconfirmed update are returned. An update is considered confirmed as soon as getUpdates is called with an offset higher than its update_id. limit: Limits the number of updates to be retrieved. Values between 1—100 are accepted. Defaults to 100. timeout: Timeout in seconds for long polling. Defaults to 0, i.e. usual short polling. Returns: A list of telegram.Update objects are returned. """ url = "%s/getUpdates" % (self.base_url) data = {} if offset: data["offset"] = offset if limit: data["limit"] = limit if timeout: data["timeout"] = timeout json_data = self._requestUrl(url, "POST", data=data) data = self._parseAndCheckTelegram(json_data) return [Update.de_json(x) for x in data]
def post(self, request, token): dispatcher = self.get_dispatcher(token) if not dispatcher: return Http404() json_string = request.body.decode('utf-8') update = Update.de_json(json.loads(json_string)) dispatcher.process_update(update) return HttpResponse()
def __init__(self): update = Update.de_json(request.get_json(force=True)) if getattr(update, 'message', None): for t, c in self.types.items(): if getattr(update.message, t): m = c() m.update = update m.parse() m.run() m.respond()
def getUpdates(self, offset=None, limit=100, timeout=0, network_delay=.2): """Use this method to receive incoming updates using long polling. Args: offset: Identifier of the first update to be returned. Must be greater by one than the highest among the identifiers of previously received updates. By default, updates starting with the earliest unconfirmed update are returned. An update is considered confirmed as soon as getUpdates is called with an offset higher than its update_id. limit: Limits the number of updates to be retrieved. Values between 1-100 are accepted. Defaults to 100. timeout: Timeout in seconds for long polling. Defaults to 0, i.e. usual short polling. network_delay: Additional timeout in seconds to allow the response from Telegram to take some time when using long polling. Defaults to 2, which should be enough for most connections. Increase it if it takes very long for data to be transmitted from and to the Telegram servers. Returns: list[:class:`telegram.Update`]: A list of :class:`telegram.Update` objects are returned. Raises: :class:`telegram.TelegramError` """ url = '{0}/getUpdates'.format(self.base_url) data = {'timeout': timeout} if offset: data['offset'] = offset if limit: data['limit'] = limit urlopen_timeout = timeout + network_delay result = request.post(url, data, timeout=urlopen_timeout) if result: self.logger.debug( 'Getting updates: %s', [u['update_id'] for u in result]) else: self.logger.debug('No new updates found.') return [Update.de_json(x) for x in result]
def test_webhook(self, monkeypatch, updater): q = Queue() monkeypatch.setattr('telegram.Bot.set_webhook', lambda *args, **kwargs: True) monkeypatch.setattr('telegram.Bot.delete_webhook', lambda *args, **kwargs: True) monkeypatch.setattr('telegram.ext.Dispatcher.process_update', lambda _, u: q.put(u)) ip = '127.0.0.1' port = randrange(1024, 49152) # Select random port for travis updater.start_webhook( ip, port, url_path='TOKEN', cert='./tests/test_updater.py', key='./tests/test_updater.py', ) sleep(.2) # SSL-Wrapping will fail, so we start the server without SSL thr = Thread(target=updater.httpd.serve_forever) thr.start() try: # Now, we send an update to the server via urlopen update = Update(1, message=Message(1, User(1, '', False), None, Chat(1, ''), text='Webhook')) self._send_webhook_msg(ip, port, update.to_json(), 'TOKEN') sleep(.2) assert q.get(False) == update response = self._send_webhook_msg(ip, port, None, 'webookhandler.py') assert b'' == response.read() assert 200 == response.code response = self._send_webhook_msg(ip, port, None, 'webookhandler.py', get_method=lambda: 'HEAD') assert b'' == response.read() assert 200 == response.code # Test multiple shutdown() calls updater.httpd.shutdown() finally: updater.httpd.shutdown() thr.join()
def webhook(): if request.method == "POST": # retrieve the message in JSON and then transform it to Telegram object update = Update.de_json(request.get_json(force=True)) logger.info("Update received! "+ update.message.text) dp.process_update(update) update_queue.put(update) return "OK" else: return redirect("https://telegram.me/links_forward_bot", code=302)
def start(bot: telegram.Bot, update: telegram.Update): if update.message.chat_id > 0: keyboard = telegram.ReplyKeyboardMarkup(DEFAULT_KEYBOARD, one_time_keyboard=False) bot.sendMessage(update.message.chat_id, start_message, reply_markup=keyboard) else: bot.sendMessage(update.message.chat_id, start_message) x = authenticate() x(lambda bot2, update2: print('authenticated:\n' + str(update.to_dict( ))))(bot, update) Updates.get_updates().botan.track(update.message, 'start')
def test_webhook_no_ssl(self): self._setup_updater('', messages=0) d = self.updater.dispatcher d.addTelegramMessageHandler( self.telegramHandlerTest) ip = '127.0.0.1' port = randrange(1024, 49152) # Select random port for travis self.updater.start_webhook(ip, port) sleep(0.5) # Now, we send an update to the server via urlopen message = Message(1, User(1, "Tester 2"), datetime.now(), Chat(1, 'group', title="Test Group 2")) message.text = "Webhook Test 2" update = Update(1) update.message = message self._send_webhook_msg(ip, port, update.to_json()) sleep(1) self.assertEqual(self.received_message, 'Webhook Test 2')
def test_webhook_no_ssl(self): print('Testing Webhook without SSL') self._setup_updater('', messages=0) d = self.updater.dispatcher d.addTelegramMessageHandler( self.telegramHandlerTest) # Select random port for travis port = randrange(1024, 49152) self.updater.start_webhook('127.0.0.1', port) sleep(0.5) # Now, we send an update to the server via urlopen message = Message(1, User(1, "Tester 2"), datetime.now(), Chat(1, 'group', title="Test Group 2")) message.text = "Webhook Test 2" update = Update(1) update.message = message try: payload = bytes(update.to_json(), encoding='utf-8') except TypeError: payload = bytes(update.to_json()) header = { 'content-type': 'application/json', 'content-length': str(len(payload)) } r = Request('http://127.0.0.1:%d/' % port, data=payload, headers=header) urlopen(r) sleep(1) self.assertEqual(self.received_message, 'Webhook Test 2')
def test_effective_message_type(self): test_message = Message(message_id=1, from_user=None, date=None, chat=None) test_message.text = 'Test' assert helpers.effective_message_type(test_message) == 'text' test_message.text = None test_message.sticker = Sticker('sticker_id', 50, 50) assert helpers.effective_message_type(test_message) == 'sticker' test_message.sticker = None test_message.new_chat_members = [User(55, 'new_user', False)] assert helpers.effective_message_type(test_message) == 'new_chat_members' test_update = Update(1) test_message.text = 'Test' test_update.message = test_message assert helpers.effective_message_type(test_update) == 'text' empty_update = Update(2) assert helpers.effective_message_type(empty_update) is None
def send_message(self, text, from_user_id=0, skip_answer=True): update = { 'update_id': 0, 'message': { 'message_id': 0, 'text': text, 'from': { 'id': from_user_id, 'first_name': 'Jack' }, 'date': int(time.time()) } } self.updater.dispatcher.processUpdate(Update.de_json(update)) if skip_answer and len(self.bot.messages) > 0: self.bot.pop_message()
def application(environ, start_response): print "app" # the environment variable CONTENT_LENGTH may be empty or missing try: request_body_size = int(environ.get('CONTENT_LENGTH', 0)) except (ValueError): request_body_size = 0 # When the method is POST the variable will be sent # in the HTTP request body which is passed by the WSGI server # in the file like wsgi.input environment variable. buf = environ['wsgi.input'].read(request_body_size) global job_queue updater = Updater("207443777:AAGuMP5nIJMqbFKILRmVuuAz8in7PfiWdjA") job_queue = updater.job_queue # Get the dispatcher to register handlers dp = updater.dispatcher # on different commands - answer in Telegram dp.addHandler(CommandHandler("start", start)) dp.addHandler(CommandHandler("help", start)) dp.addHandler(CommandHandler("set", set)) dp.addHandler(InlineQueryHandler(inlinequery)) # log all errors dp.addErrorHandler(error) updater.bot.setWebhook("https://afternoon-shelf-83103.herokuapp.com") # Start the Bot #updater.start_polling() json_string = bytes_to_native_str(buf) update = Update.de_json(json.loads(json_string)) dp.processUpdate(update) start_response('200 OK', [('Content-Type', 'text/plain')]) return [''] # Block until the you presses Ctrl-C or the process receives SIGINT, # SIGTERM or SIGABRT. This should be used most of the time, since # start_polling() is non-blocking and will stop the bot gracefully. import time
def getUpdates(self, offset=None, limit=100, timeout=0): """Use this method to receive incoming updates using long polling. Args: offset: Identifier of the first update to be returned. Must be greater by one than the highest among the identifiers of previously received updates. By default, updates starting with the earliest unconfirmed update are returned. An update is considered confirmed as soon as getUpdates is called with an offset higher than its update_id. limit: Limits the number of updates to be retrieved. Values between 1-100 are accepted. Defaults to 100. timeout: Timeout in seconds for long polling. Defaults to 0, i.e. usual short polling. Returns: A list of telegram.Update objects are returned. """ url = '%s/getUpdates' % self.base_url data = {} if offset: data['offset'] = offset if limit: data['limit'] = limit if timeout: data['timeout'] = timeout result = request.post(url, data) if result: self.logger.info( 'Getting updates: %s', [u['update_id'] for u in result]) else: self.logger.info('No new updates found.') return [Update.de_json(x) for x in result]
def post(self, request, token): serializer = UpdateSerializer(data=request.data) if serializer.is_valid(): serializer.save() try: bot = Bot.objects.get(token=token) bot.handle(Update.de_json(request.data)) except Bot.DoesNotExist: logger.warning("Token %s not associated to a bot" % token) return Response(serializer.errors, status=status.HTTP_404_NOT_FOUND) except: exc_info = sys.exc_info() traceback.print_exception(*exc_info) logger.error("Error processing %s for token %s" % (request.data, token)) return Response(serializer.errors, status=status.HTTP_500_INTERNAL_SERVER_ERROR) else: return Response(serializer.data, status=status.HTTP_200_OK) logger.error("Validation error: %s from message %s" % (serializer.errors, request.data)) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def message(): if request.method == 'POST': if not out_channel.get_me()['username'] == self.verify: logger.debug("Invalid access token, check it " "matches Telegram") return "failed" update = Update.de_json(request.get_json(force=True), out_channel) if self._is_button(update): message = update.callback_query.message text = update.callback_query.data else: message = update.message if self._is_user_message(message): text = message.text.replace('/bot', '') elif self._is_location(message): text = ('{{"lng":{0}, "lat":{1}}}' ''.format(message.location.longitude, message.location.latitude)) else: return "success" sender_id = message.chat.id try: if text == '_restart' or text == '/restart': on_new_message(UserMessage(text, out_channel, sender_id)) on_new_message(UserMessage('/start', out_channel, sender_id)) else: on_new_message(UserMessage(text, out_channel, sender_id)) except Exception as e: logger.error("Exception when trying to handle " "message.{0}".format(e)) logger.error(e, exc_info=True) if self.debug_mode: raise pass return "success"
def do_POST(self): self.logger.debug("Webhook triggered") try: self._validate_post() clen = self._get_content_len() except _InvalidPost as e: self.send_error(e.http_code) self.end_headers() else: buf = self.rfile.read(clen) json_string = bytes_to_native_str(buf) self.send_response(200) self.end_headers() self.logger.debug("Webhook received data: " + json_string) update = Update.de_json(json.loads(json_string)) self.logger.info("Received Update with ID %d on Webhook" % update.update_id) self.server.update_queue.put(update)
def do_POST(self): self.logger.debug("Webhook triggered") if self.path == self.server.webhook_path and \ 'content-type' in self.headers and \ 'content-length' in self.headers and \ self.headers['content-type'] == 'application/json': json_string = \ n(self.rfile.read(int(self.headers['content-length']))) self.send_response(200) self.end_headers() self.logger.debug("Webhook received data: " + json_string) update = Update.de_json(json.loads(json_string)) self.logger.info("Received Update with ID %d on Webhook" % update.update_id) self.server.update_queue.put(update) else: self.send_error(403) self.end_headers()
def false_update(request): return Update(update_id=2, **request.param)
def lambda_handler(event, context): dp.process_update(Update.de_json(json.loads(event["body"]), bot)) return {"statusCode": 200}
def webhook(): update = Update.de_json(request.get_json(force=True), bot) update_queue.put(update) return 'ok'
def respond(): # retrieve the message in JSON and then transform it to Telegram object update = Update.de_json(request.get_json(force=True), bot) update_queue.put(update) return 'ok'
def tg_supply(data): update = Update.de_json(data, None) if not update.effective_user: return chat_id = update.effective_chat.id user_id = update.effective_user.id tg_user = update.effective_user data = update.callback_query and update.callback_query.data # type: Optional[str] try: state = get_supply_state(tg_user_id=user_id, tg_user=tg_user, tg_chat_id=chat_id) db_user = state.db_user if data and data.startswith('c|'): parts = data.split('|') reply = handle_supply_command(db_user, parts[1], parts[2:]) if reply.next_state is None: reply.next_state = SupplyState.NO_STATE else: if update.message and update.message.text == '/start': state = set_supply_state(db_user, None) reply = state.handle( update_to_text(update), data, update_to_coordinates(update), ) if reply is not None and reply.next_state is not None: next_state = set_supply_state(db_user, reply.next_state) else: next_state = state if isinstance(state, DefaultState): return build_tg_response(chat_id=chat_id, reply=next_state.get_intro()) queue_messages(tg_chat_id=chat_id, original_message=update.callback_query and update.callback_query.message, replies=[reply, next_state.get_intro()], workflow=Workflow.SUPPLY) if update.callback_query: return { 'method': 'answerCallbackQuery', 'callback_query_id': update.callback_query.id, } except Exception: logger.exception('Something went wrong for a supply user.') return build_tg_response( chat_id=chat_id, reply=Reply(text=_( 'Something went wrong. Try something different, please.'), buttons=[[{ 'data': f'c|{SupplyCommand.BACK_TO_POSTING}', 'text': _('Start from the beginning'), }]]))
def callback_query(bot): return Update(0, callback_query=CallbackQuery(2, User(1, "", False), None, data="test data"))
def test_persisting_no_user_no_chat(self, cdp): class OwnPersistence(BasePersistence): def __init__(self): super(OwnPersistence, self).__init__() self.store_user_data = True self.store_chat_data = True self.store_bot_data = True self.test_flag_bot_data = False self.test_flag_chat_data = False self.test_flag_user_data = False def update_bot_data(self, data): self.test_flag_bot_data = True def update_chat_data(self, chat_id, data): self.test_flag_chat_data = True def update_user_data(self, user_id, data): self.test_flag_user_data = True def update_conversation(self, name, key, new_state): pass def get_conversations(self, name): pass def get_user_data(self): pass def get_bot_data(self): pass def get_chat_data(self): pass def callback(update, context): pass handler = MessageHandler(Filters.all, callback) cdp.add_handler(handler) cdp.persistence = OwnPersistence() update = Update(1, message=Message(1, User(1, '', False), None, None, text='Text')) cdp.process_update(update) assert cdp.persistence.test_flag_bot_data assert cdp.persistence.test_flag_user_data assert not cdp.persistence.test_flag_chat_data cdp.persistence.test_flag_bot_data = False cdp.persistence.test_flag_user_data = False cdp.persistence.test_flag_chat_data = False update = Update(1, message=Message(1, None, None, Chat(1, ''), text='Text')) cdp.process_update(update) assert cdp.persistence.test_flag_bot_data assert not cdp.persistence.test_flag_user_data assert cdp.persistence.test_flag_chat_data
def wrapper(update: Update, context: CallbackContext): # The user has been banned and already got a message regarding this issue if context.user_data.get("banned-message-sent"): return user = None session = get_session() try: if hasattr(update, "message") and update.message: message = update.message elif hasattr(update, "edited_message") and update.edited_message: message = update.edited_message user, _ = get_user(session, message.from_user) # Send a message explaining the user, why they cannot use the bot. # Also set a flag, which prevents sending this messages multiple times and thereby prevents DOS attacks. if user.banned: if not context.user_data.get("banned-message-sent"): context.user_data["banned-message-sent"] = True message.chat.send_message( "You have been permanently banned from using this bot, either due to spamming or inappropriate behavior." "Please refrain from asking questions in the support group or on Github. There's nothing we can do about this." ) return # Show an error message, if the users uses the bot in a public chat, # when he shouldn't. Also check if we're even allowed to send a message. if private and message.chat.type != "private": chat = context.bot.getChat(message.chat.id) if chat.permissions.can_send_messages: message.chat.send_message( "Please do this in a direct conversation with me.") return response = func(context.bot, update, session, user) session.commit() # Respond to user if response is not None: message.chat.send_message(response) except RollbackException as e: session.rollback() message.chat.send_message( e.message, parse_mode="markdown", disable_web_page_preview=True, ) except Exception as e: if not ignore_exception(e): if config["logging"]["debug"]: traceback.print_exc() sentry.capture_exception( tags={ "handler": "message", }, extra={ "update": update.to_dict(), "function": func.__name__ }, ) locale = "English" if user is not None: locale = user.locale try: message.chat.send_message( i18n.t("misc.error", locale=locale), parse_mode="markdown", disable_web_page_preview=True, ) except Exception as e: # It sometimes happens, that an error occurs during sending the # error message. Only capture important exceptions if not ignore_exception(e): sentry.capture_exception( tags={ "handler": "message", }, extra={ "update": update.to_dict(), "function": func.__name__, }, ) raise e finally: # The session might not be there yet # We're checking for bans inside this try/catch, which has to # happen before session initialization due to performance reasons if "session" in locals(): session.close()
def test_error_handler(self): class CallbackContext(object): error = "error msg" self.assertIsNone(error_callback(Update("0"), CallbackContext()))
def webhook_updater(request): update = Update.de_json(json.loads(request.body), BOT) DISPATCHER.process_update(update) return HttpResponse("Ok")
def error_handler(update: Update, context: CallbackContext): logger.error('Update "{}" caused error "{}"'.format( json.dumps(update.to_dict(), indent=4), context.error))
def update(): _update = Update(0) _update.message = Message(0, 0, datetime.utcnow(), Chat(0, 0)) return _update
def parse_update(self, data: bytes) -> Any: update_dict = json.loads(data) return Update.de_json(update_dict, self._updater.bot)
def test_channel_message_without_chat(self, bot): handler = ConversationHandler(entry_points=[CommandHandler('start', self.start_end)], states={}, fallbacks=[]) message = Message(0, None, None, Chat(0, Chat.CHANNEL, 'Misses Test'), bot=bot) update = Update(0, message=message) assert not handler.check_update(update)
def telegramWebHook(): update = Update.de_json(request.get_json(force=True)) text = None if getattr(update.message, 'document'): gallery = Gallery().search(tgid = update.message.chat.id) if gallery: newfile = bot.getFile(update.message.document.file_id) file_name = update.message.document.file_id newfile.download(file_name) writed = False if os.path.exists(file_name): writed = write_file(file_name, read_file(file_name, storage = 'local', append_path = False), acl = 'public-read', mime_type = update.message.document.mime_type) thumbnail(file_name) os.remove(file_name) write_file('%s.json' % file_name, update.to_json()) if writed: file_id = File(gallery_eid = gallery.eid, file_id = update.message.document.file_id) file_id.save() sendLink = getattr(gallery, 'sendLink', None) if sendLink == 'True': text = 'File URL: %s' % url_for('image', file_id = file_id.eid, _external = True, disable_web_page_preview = True) else: text = 'Failed to download file' else: text = 'Gallery does not exist, please create first' pass if getattr(update.message, 'text'): args = update.message.text.split(' ', 2) if args[0] == '/register': text = 'Username:'******'Complete register: https://telegram.me/ACSGalleryBot?start=%s' % update.message.from_user.id else: text = 'User added to gallery' # set gallery permission at this point because i have chat id elif args[0] == '/start': if len(args) > 1 and int(args[1]) == int(update.message.chat.id): text = 'Username:'******'force_reply' : True }) else: text = update.to_json() elif getattr(update.message, 'reply_to_message'): if update.message.reply_to_message.text == 'Username:'******'Password:'******'force_reply' : True }) return 'ok' elif update.message.reply_to_message.text == 'Password:'******'User succesfuly registered' elif args[0] == '/create': if hasattr(update.message.chat, 'title'): gallery = Gallery().search(tgid = update.message.chat.id) if not gallery: gallery = Gallery(tgid = update.message.chat.id, title = update.message.chat.title).save() text = 'Gallery URL: %s' % url_for('gallery', id = gallery.eid, _external = True, _scheme = 'https') else: text = 'Bot only works in groups' elif args[0] == '/remove': gallery = Gallery().search(tgid = update.message.chat.id) if gallery: gallery.delete() text = 'Gallery deleted' else: text = 'Gallery is not registered' # TODO: Confirm elif args[0] == '/config': args.pop(0) gallery = Gallery.search(tgid = update.message.chat.id) if gallery: if len(args) == 0: text = g.config(update.message.chat.id) elif len(args) == 1: text = 'get one' text = g.config(update.message.chat.id, args[0]) else: text = g.config(update.message.chat.id, args[0], args[1]) else: text = 'Gallery is not registered' #else: # text = update.to_json() if text: bot.sendMessage(update.message.chat.id, text, disable_web_page_preview=True) return ""
def test_error_while_saving_chat_data(self, dp, bot): increment = [] class OwnPersistence(BasePersistence): def __init__(self): super().__init__() self.store_user_data = True self.store_chat_data = True self.store_bot_data = True def get_bot_data(self): return dict() def update_bot_data(self, data): raise Exception def get_chat_data(self): return defaultdict(dict) def update_chat_data(self, chat_id, data): raise Exception def get_user_data(self): return defaultdict(dict) def update_user_data(self, user_id, data): raise Exception def get_conversations(self, name): pass def update_conversation(self, name, key, new_state): pass def start1(b, u): pass def error(b, u, e): increment.append("error") # If updating a user_data or chat_data from a persistence object throws an error, # the error handler should catch it update = Update(1, message=Message(1, User(1, "Test", False), None, Chat(1, "lala"), text='/start', entities=[ MessageEntity( type=MessageEntity.BOT_COMMAND, offset=0, length=len('/start')) ], bot=bot)) my_persistence = OwnPersistence() dp = Dispatcher(bot, None, persistence=my_persistence) dp.add_handler(CommandHandler('start', start1)) dp.add_error_handler(error) dp.process_update(update) assert increment == ["error", "error", "error"]
def test_context(self, cdp, message): handler = RegexHandler(r'(t)est(.*)', self.callback_context) cdp.add_handler(handler) cdp.process_update(Update(0, message=message)) assert self.test_flag
def privateUpdate(): return Update(1, TestStartPrivate.private_message)
def update_from_file(self, bot, name): update = Update.de_json(self.file(name), bot) return update
def test_error_while_persisting(self, cdp, monkeypatch): class OwnPersistence(BasePersistence): def __init__(self): super(OwnPersistence, self).__init__() self.store_user_data = True self.store_chat_data = True self.store_bot_data = True def update(self, data): raise Exception('PersistenceError') def update_bot_data(self, data): self.update(data) def update_chat_data(self, chat_id, data): self.update(data) def update_user_data(self, user_id, data): self.update(data) def get_chat_data(self): pass def get_bot_data(self): pass def get_user_data(self): pass def get_conversations(self, name): pass def update_conversation(self, name, key, new_state): pass def callback(update, context): pass test_flag = False def error(update, context): nonlocal test_flag test_flag = str(context.error) == 'PersistenceError' raise Exception('ErrorHandlingError') def logger(message): assert 'uncaught error was raised while handling' in message update = Update(1, message=Message(1, User(1, '', False), None, Chat(1, ''), text='Text')) handler = MessageHandler(Filters.all, callback) cdp.add_handler(handler) cdp.add_error_handler(error) monkeypatch.setattr(cdp.logger, 'exception', logger) cdp.persistence = OwnPersistence() cdp.process_update(update) assert test_flag
class TestDispatcher(object): message_update = Update(1, message=Message(1, User(1, '', False), None, Chat(1, ''), text='Text')) received = None count = 0 @pytest.fixture(autouse=True, name='reset') def reset_fixture(self): self.reset() def reset(self): self.received = None self.count = 0 def error_handler(self, bot, update, error): self.received = error.message def error_handler_raise_error(self, bot, update, error): raise Exception('Failing bigly') def callback_increase_count(self, bot, update): self.count += 1 def callback_set_count(self, count): def callback(bot, update): self.count = count return callback def callback_raise_error(self, bot, update): raise TelegramError(update.message.text) def callback_if_not_update_queue(self, bot, update, update_queue=None): if update_queue is not None: self.received = update.message def callback_context(self, update, context): if (isinstance(context, CallbackContext) and isinstance(context.bot, Bot) and isinstance(context.update_queue, Queue) and isinstance(context.job_queue, JobQueue) and isinstance(context.error, TelegramError)): self.received = context.error.message def test_one_context_per_update(self, cdp): def one(update, context): if update.message.text == 'test': context.my_flag = True def two(update, context): if update.message.text == 'test': if not hasattr(context, 'my_flag'): pytest.fail() else: if hasattr(context, 'my_flag'): pytest.fail() cdp.add_handler(MessageHandler(Filters.regex('test'), one), group=1) cdp.add_handler(MessageHandler(None, two), group=2) u = Update(1, Message(1, None, None, None, text='test')) cdp.process_update(u) u.message.text = 'something' cdp.process_update(u) def test_error_handler(self, dp): dp.add_error_handler(self.error_handler) error = TelegramError('Unauthorized.') dp.update_queue.put(error) sleep(.1) assert self.received == 'Unauthorized.' # Remove handler dp.remove_error_handler(self.error_handler) self.reset() dp.update_queue.put(error) sleep(.1) assert self.received is None def test_construction_with_bad_persistence(self, caplog, bot): class my_per: def __init__(self): self.store_user_data = False self.store_chat_data = False with pytest.raises( TypeError, match= 'persistence should be based on telegram.ext.BasePersistence'): Dispatcher(bot, None, persistence=my_per()) def test_error_handler_that_raises_errors(self, dp): """ Make sure that errors raised in error handlers don't break the main loop of the dispatcher """ handler_raise_error = MessageHandler(Filters.all, self.callback_raise_error) handler_increase_count = MessageHandler(Filters.all, self.callback_increase_count) error = TelegramError('Unauthorized.') dp.add_error_handler(self.error_handler_raise_error) # From errors caused by handlers dp.add_handler(handler_raise_error) dp.update_queue.put(self.message_update) sleep(.1) # From errors in the update_queue dp.remove_handler(handler_raise_error) dp.add_handler(handler_increase_count) dp.update_queue.put(error) dp.update_queue.put(self.message_update) sleep(.1) assert self.count == 1 def test_run_async_multiple(self, bot, dp, dp2): def get_dispatcher_name(q): q.put(current_thread().name) q1 = Queue() q2 = Queue() dp.run_async(get_dispatcher_name, q1) dp2.run_async(get_dispatcher_name, q2) sleep(.1) name1 = q1.get() name2 = q2.get() assert name1 != name2 def test_multiple_run_async_decorator(self, dp, dp2): # Make sure we got two dispatchers and that they are not the same assert isinstance(dp, Dispatcher) assert isinstance(dp2, Dispatcher) assert dp is not dp2 @run_async def must_raise_runtime_error(): pass with pytest.raises(RuntimeError): must_raise_runtime_error() def test_run_async_with_args(self, dp): dp.add_handler( MessageHandler(Filters.all, run_async(self.callback_if_not_update_queue), pass_update_queue=True)) dp.update_queue.put(self.message_update) sleep(.1) assert self.received == self.message_update.message def test_error_in_handler(self, dp): dp.add_handler(MessageHandler(Filters.all, self.callback_raise_error)) dp.add_error_handler(self.error_handler) dp.update_queue.put(self.message_update) sleep(.1) assert self.received == self.message_update.message.text def test_add_remove_handler(self, dp): handler = MessageHandler(Filters.all, self.callback_increase_count) dp.add_handler(handler) dp.update_queue.put(self.message_update) sleep(.1) assert self.count == 1 dp.remove_handler(handler) dp.update_queue.put(self.message_update) assert self.count == 1 def test_add_remove_handler_non_default_group(self, dp): handler = MessageHandler(Filters.all, self.callback_increase_count) dp.add_handler(handler, group=2) with pytest.raises(KeyError): dp.remove_handler(handler) dp.remove_handler(handler, group=2) def test_error_start_twice(self, dp): assert dp.running dp.start() def test_handler_order_in_group(self, dp): dp.add_handler( MessageHandler(Filters.photo, self.callback_set_count(1))) dp.add_handler(MessageHandler(Filters.all, self.callback_set_count(2))) dp.add_handler(MessageHandler(Filters.text, self.callback_set_count(3))) dp.update_queue.put(self.message_update) sleep(.1) assert self.count == 2 def test_groups(self, dp): dp.add_handler( MessageHandler(Filters.all, self.callback_increase_count)) dp.add_handler(MessageHandler(Filters.all, self.callback_increase_count), group=2) dp.add_handler(MessageHandler(Filters.all, self.callback_increase_count), group=-1) dp.update_queue.put(self.message_update) sleep(.1) assert self.count == 3 def test_add_handler_errors(self, dp): handler = 'not a handler' with pytest.raises(TypeError, match='handler is not an instance of'): dp.add_handler(handler) handler = MessageHandler(Filters.photo, self.callback_set_count(1)) with pytest.raises(TypeError, match='group is not int'): dp.add_handler(handler, 'one') def test_flow_stop(self, dp, bot): passed = [] def start1(b, u): passed.append('start1') raise DispatcherHandlerStop def start2(b, u): passed.append('start2') def start3(b, u): passed.append('start3') def error(b, u, e): passed.append('error') passed.append(e) update = Update(1, message=Message(1, None, None, None, text='/start', entities=[ MessageEntity( type=MessageEntity.BOT_COMMAND, offset=0, length=len('/start')) ], bot=bot)) # If Stop raised handlers in other groups should not be called. passed = [] dp.add_handler(CommandHandler('start', start1), 1) dp.add_handler(CommandHandler('start', start3), 1) dp.add_handler(CommandHandler('start', start2), 2) dp.process_update(update) assert passed == ['start1'] def test_exception_in_handler(self, dp, bot): passed = [] def start1(b, u): passed.append('start1') raise Exception('General exception') def start2(b, u): passed.append('start2') def start3(b, u): passed.append('start3') def error(b, u, e): passed.append('error') passed.append(e) update = Update(1, message=Message(1, None, None, None, text='/start', entities=[ MessageEntity( type=MessageEntity.BOT_COMMAND, offset=0, length=len('/start')) ], bot=bot)) # If an unhandled exception was caught, no further handlers from the same group should be # called. passed = [] dp.add_handler(CommandHandler('start', start1), 1) dp.add_handler(CommandHandler('start', start2), 1) dp.add_handler(CommandHandler('start', start3), 2) dp.add_error_handler(error) dp.process_update(update) assert passed == ['start1', 'start3'] def test_telegram_error_in_handler(self, dp, bot): passed = [] err = TelegramError('Telegram error') def start1(b, u): passed.append('start1') raise err def start2(b, u): passed.append('start2') def start3(b, u): passed.append('start3') def error(b, u, e): passed.append('error') passed.append(e) update = Update(1, message=Message(1, None, None, None, text='/start', entities=[ MessageEntity( type=MessageEntity.BOT_COMMAND, offset=0, length=len('/start')) ], bot=bot)) # If a TelegramException was caught, an error handler should be called and no further # handlers from the same group should be called. dp.add_handler(CommandHandler('start', start1), 1) dp.add_handler(CommandHandler('start', start2), 1) dp.add_handler(CommandHandler('start', start3), 2) dp.add_error_handler(error) dp.process_update(update) assert passed == ['start1', 'error', err, 'start3'] assert passed[2] is err def test_flow_stop_in_error_handler(self, dp, bot): passed = [] err = TelegramError('Telegram error') def start1(b, u): passed.append('start1') raise err def start2(b, u): passed.append('start2') def start3(b, u): passed.append('start3') def error(b, u, e): passed.append('error') passed.append(e) raise DispatcherHandlerStop update = Update(1, message=Message(1, None, None, None, text='/start', entities=[ MessageEntity( type=MessageEntity.BOT_COMMAND, offset=0, length=len('/start')) ], bot=bot)) # If a TelegramException was caught, an error handler should be called and no further # handlers from the same group should be called. dp.add_handler(CommandHandler('start', start1), 1) dp.add_handler(CommandHandler('start', start2), 1) dp.add_handler(CommandHandler('start', start3), 2) dp.add_error_handler(error) dp.process_update(update) assert passed == ['start1', 'error', err] assert passed[2] is err def test_error_handler_context(self, cdp): cdp.add_error_handler(self.callback_context) error = TelegramError('Unauthorized.') cdp.update_queue.put(error) sleep(.1) assert self.received == 'Unauthorized.' @pytest.mark.skipif(sys.version_info < (3, 0), reason='pytest fails this for no reason') def test_non_context_deprecation(self, dp): with pytest.warns(TelegramDeprecationWarning): Dispatcher(dp.bot, dp.update_queue, job_queue=dp.job_queue, workers=0, use_context=False)
def tg_demand(data): update = Update.de_json(data, None) user_id = update.effective_user.id chat_id = update.effective_chat.id tg_user = update.effective_user text = update.message and update.message.text try: user = get_or_create_user( user_id=user_id, chat_id=chat_id, provider=Provider.TG, workflow=Workflow.DEMAND, info={ UserInfoField.NAME.value: tg_user.first_name, UserInfoField.USERNAME.value: tg_user.username, UserInfoField.LANGUAGE.value: tg_user.language_code, }, ) if update.callback_query is not None: reply = handle_demand_data(user=user, data=update.callback_query.data) else: if text == '/start': set_demand_state(user, None) state = get_demand_state(user) reply = state.handle( update_to_text(update), data=None, coordinates=update_to_coordinates(update), ) replies = [reply] if reply is not None: if reply.next_state is not None: next_state = set_demand_state(user=user, state=reply.next_state) replies.append(next_state.get_intro()) queue_messages(tg_chat_id=chat_id, original_message=update.callback_query and update.callback_query.message, replies=replies, workflow=Workflow.DEMAND) if update.callback_query: return { 'method': 'answerCallbackQuery', 'callback_query_id': update.callback_query.id, } except Exception: logger.exception('Something went wrong for a demand user.') return build_tg_response( chat_id=chat_id, reply=Reply(text=_( 'Something went wrong. Try something different, please.')))
def pass_update(): new_update = Update.de_json(request.get_json(force=True), bot) update_queue.put(new_update) return "ok"
def pre_checkout_query(): return Update( 1, pre_checkout_query=PreCheckoutQuery("id", User(1, "test user", False), "EUR", 223, "invoice_payload"), )
def chat_join_request_update(bot, chat_join_request): return Update(0, chat_join_request=chat_join_request)
def index() -> Response: dispatcher.process_update(Update.de_json(request.get_json(force=True), bot)) return "", http.HTTPStatus.NO_CONTENT
def __init__(self, request, bot): self.request_body = request.body.decode('utf8') update = json.loads(self.request_body) self.update = Update.de_json(update, bot=bot)
def chosen_inline_result(): return Update(1, chosen_inline_result=ChosenInlineResult( 'result_id', User(1, 'test_user', False), 'query'))
def callback_query(bot): return Update(0, callback_query=CallbackQuery(2, User(1, '', False), None, data='test data'))
def test_nested_conversation_handler(self, dp, bot, user1, user2): self.nested_states[self.DRINKING] = [ ConversationHandler(entry_points=self.drinking_entry_points, states=self.drinking_states, fallbacks=self.drinking_fallbacks, map_to_parent=self.drinking_map_to_parent) ] handler = ConversationHandler(entry_points=self.entry_points, states=self.nested_states, fallbacks=self.fallbacks) dp.add_handler(handler) # User one, starts the state machine. message = Message(0, user1, None, self.group, text='/start', bot=bot, entities=[ MessageEntity(type=MessageEntity.BOT_COMMAND, offset=0, length=len('/start')) ]) dp.process_update(Update(update_id=0, message=message)) assert self.current_state[user1.id] == self.THIRSTY # The user is thirsty and wants to brew coffee. message.text = '/brew' message.entities[0].length = len('/brew') dp.process_update(Update(update_id=0, message=message)) assert self.current_state[user1.id] == self.BREWING # Lets pour some coffee. message.text = '/pourCoffee' message.entities[0].length = len('/pourCoffee') dp.process_update(Update(update_id=0, message=message)) assert self.current_state[user1.id] == self.DRINKING # The user is holding the cup message.text = '/hold' message.entities[0].length = len('/hold') dp.process_update(Update(update_id=0, message=message)) assert self.current_state[user1.id] == self.HOLDING # The user is sipping coffee message.text = '/sip' message.entities[0].length = len('/sip') dp.process_update(Update(update_id=0, message=message)) assert self.current_state[user1.id] == self.SIPPING # The user is swallowing message.text = '/swallow' message.entities[0].length = len('/swallow') dp.process_update(Update(update_id=0, message=message)) assert self.current_state[user1.id] == self.SWALLOWING # The user is holding the cup again message.text = '/hold' message.entities[0].length = len('/hold') dp.process_update(Update(update_id=0, message=message)) assert self.current_state[user1.id] == self.HOLDING # The user wants to replenish the coffee supply message.text = '/replenish' message.entities[0].length = len('/replenish') dp.process_update(Update(update_id=0, message=message)) assert self.current_state[user1.id] == self.REPLENISHING assert handler.conversations[(0, user1.id)] == self.BREWING # The user wants to drink their coffee again message.text = '/pourCoffee' message.entities[0].length = len('/pourCoffee') dp.process_update(Update(update_id=0, message=message)) assert self.current_state[user1.id] == self.DRINKING # The user is now ready to start coding message.text = '/startCoding' message.entities[0].length = len('/startCoding') dp.process_update(Update(update_id=0, message=message)) assert self.current_state[user1.id] == self.CODING # The user decides it's time to drink again message.text = '/drinkMore' message.entities[0].length = len('/drinkMore') dp.process_update(Update(update_id=0, message=message)) assert self.current_state[user1.id] == self.DRINKING # The user is holding their cup message.text = '/hold' message.entities[0].length = len('/hold') dp.process_update(Update(update_id=0, message=message)) assert self.current_state[user1.id] == self.HOLDING # The user wants to end with the drinking and go back to coding message.text = '/end' message.entities[0].length = len('/end') dp.process_update(Update(update_id=0, message=message)) assert self.current_state[user1.id] == self.END assert handler.conversations[(0, user1.id)] == self.CODING # The user wants to drink once more message.text = '/drinkMore' message.entities[0].length = len('/drinkMore') dp.process_update(Update(update_id=0, message=message)) assert self.current_state[user1.id] == self.DRINKING # The user wants to stop altogether message.text = '/stop' message.entities[0].length = len('/stop') dp.process_update(Update(update_id=0, message=message)) assert self.current_state[user1.id] == self.STOPPING assert handler.conversations.get((0, user1.id)) is None
def mockUpdate(text): message = Message(0, None, None, None) message.text = text update = Update(0) update.message = message return update
def show_poll(poll: Poll, answers: [Answer], update: telegram.ext.Dispatcher, bot: telegram.Update): question = poll.question text, reply_markup = generate_poll_message(poll, answers) bot.sendMessage(chat_id=update.message.chat_id, text=text, reply_markup=reply_markup)
def telegram_hook(token): if token != WEBHOOK_TOKEN: abort(401, 'Unauthorized') update = Update.de_json(request.json, bot) if update.callback_query: return process_callback(update.callback_query) elif update.message: return process_message(update.message)