class UpdaterTest(BaseTest, unittest.TestCase): """ This object represents Tests for Updater, Dispatcher, WebhookServer and WebhookHandler """ def setUp(self): self.updater = None self.received_message = None self.message_count = 0 self.lock = Lock() def _setup_updater(self, *args, **kwargs): bot = MockBot(*args, **kwargs) self.updater = Updater(workers=2, bot=bot) def tearDown(self): if self.updater is not None: self.updater.stop() def reset(self): self.message_count = 0 self.received_message = None def telegramHandlerTest(self, bot, update): self.received_message = update.message.text self.message_count += 1 def telegramInlineHandlerTest(self, bot, update): self.received_message = (update.inline_query, update.chosen_inline_result) self.message_count += 1 @run_async def asyncHandlerTest(self, bot, update, **kwargs): sleep(1) with self.lock: self.received_message = update.message.text self.message_count += 1 def stringHandlerTest(self, bot, update): self.received_message = update self.message_count += 1 def regexGroupHandlerTest(self, bot, update, groups=None, groupdict=None): self.received_message = (groups, groupdict) self.message_count += 1 def additionalArgsTest(self, bot, update, update_queue, args): self.received_message = update self.message_count += 1 if args[0] == 'resend': update_queue.put('/test5 noresend') elif args[0] == 'noresend': pass def contextTest(self, bot, update, context): self.received_message = update self.message_count += 1 self.context = context @run_async def asyncAdditionalHandlerTest(self, bot, update, update_queue=None, **kwargs): sleep(1) with self.lock: if update_queue is not None: self.received_message = update.message.text self.message_count += 1 def errorRaisingHandlerTest(self, bot, update): raise TelegramError(update) def errorHandlerTest(self, bot, update, error): self.received_message = error.message self.message_count += 1 def test_addRemoveTelegramMessageHandler(self): self._setup_updater('Test') d = self.updater.dispatcher d.addTelegramMessageHandler( self.telegramHandlerTest) self.updater.start_polling(0.01) sleep(.1) self.assertEqual(self.received_message, 'Test') # Remove handler d.removeTelegramMessageHandler(self.telegramHandlerTest) self.reset() self.updater.bot.send_messages = 1 sleep(.1) self.assertTrue(None is self.received_message) def test_addTelegramMessageHandlerMultipleMessages(self): self._setup_updater('Multiple', 100) self.updater.dispatcher.addTelegramMessageHandler( self.telegramHandlerTest) self.updater.start_polling(0.0) sleep(2) self.assertEqual(self.received_message, 'Multiple') self.assertEqual(self.message_count, 100) def test_addRemoveTelegramRegexHandler(self): self._setup_updater('Test2') d = self.updater.dispatcher regobj = re.compile('Te.*') self.updater.dispatcher.addTelegramRegexHandler(regobj, self.telegramHandlerTest) self.updater.start_polling(0.01) sleep(.1) self.assertEqual(self.received_message, 'Test2') # Remove handler d.removeTelegramRegexHandler(regobj, self.telegramHandlerTest) self.reset() self.updater.bot.send_messages = 1 sleep(.1) self.assertTrue(None is self.received_message) def test_addRemoveTelegramCommandHandler(self): self._setup_updater('/test') d = self.updater.dispatcher self.updater.dispatcher.addTelegramCommandHandler( 'test', self.telegramHandlerTest) self.updater.start_polling(0.01) sleep(.1) self.assertEqual(self.received_message, '/test') # Remove handler d.removeTelegramCommandHandler('test', self.telegramHandlerTest) self.reset() self.updater.bot.send_messages = 1 sleep(.1) self.assertTrue(None is self.received_message) def test_addRemoveUnknownTelegramCommandHandler(self): self._setup_updater('/test2') d = self.updater.dispatcher self.updater.dispatcher.addUnknownTelegramCommandHandler( self.telegramHandlerTest) self.updater.start_polling(0.01) sleep(.1) self.assertEqual(self.received_message, '/test2') # Remove handler d.removeUnknownTelegramCommandHandler(self.telegramHandlerTest) self.reset() self.updater.bot.send_messages = 1 sleep(.1) self.assertTrue(None is self.received_message) def test_addRemoveStringRegexHandler(self): self._setup_updater('', messages=0) d = self.updater.dispatcher d.addStringRegexHandler('Te.*', self.stringHandlerTest) queue = self.updater.start_polling(0.01) queue.put('Test3') sleep(.1) self.assertEqual(self.received_message, 'Test3') # Remove handler d.removeStringRegexHandler('Te.*', self.stringHandlerTest) self.reset() queue.put('Test3') sleep(.1) self.assertTrue(None is self.received_message) def test_addRemoveStringCommandHandler(self): self._setup_updater('', messages=0) d = self.updater.dispatcher d.addStringCommandHandler( 'test3', self.stringHandlerTest) queue = self.updater.start_polling(0.01) queue.put('/test3') sleep(.1) self.assertEqual(self.received_message, '/test3') # Remove handler d.removeStringCommandHandler('test3', self.stringHandlerTest) self.reset() queue.put('/test3') sleep(.1) self.assertTrue(None is self.received_message) def test_addRemoveUnknownStringCommandHandler(self): self._setup_updater('/test') d = self.updater.dispatcher d.addUnknownStringCommandHandler( self.stringHandlerTest) queue = self.updater.start_polling(0.01) queue.put('/test4') sleep(.1) self.assertEqual(self.received_message, '/test4') # Remove handler d.removeUnknownStringCommandHandler(self.stringHandlerTest) self.reset() self.updater.bot.send_messages = 1 sleep(.1) self.assertTrue(None is self.received_message) def test_addRemoveErrorHandler(self): self._setup_updater('', messages=0) d = self.updater.dispatcher d.addErrorHandler(self.errorHandlerTest) queue = self.updater.start_polling(0.01) error = TelegramError("Unauthorized.") queue.put(error) sleep(.1) self.assertEqual(self.received_message, "Unauthorized.") # Remove handler d.removeErrorHandler(self.errorHandlerTest) self.reset() queue.put(error) sleep(.1) self.assertTrue(None is self.received_message) def test_errorInHandler(self): self._setup_updater('', messages=0) d = self.updater.dispatcher d.addStringRegexHandler('.*', self.errorRaisingHandlerTest) self.updater.dispatcher.addErrorHandler(self.errorHandlerTest) queue = self.updater.start_polling(0.01) queue.put('Test Error 1') sleep(.1) self.assertEqual(self.received_message, 'Test Error 1') def test_cleanBeforeStart(self): self._setup_updater('') d = self.updater.dispatcher d.addTelegramMessageHandler(self.telegramHandlerTest) self.updater.start_polling(0.01, clean=True) sleep(.1) self.assertEqual(self.message_count, 0) self.assertIsNone(self.received_message) def test_errorOnGetUpdates(self): self._setup_updater('', raise_error=True) d = self.updater.dispatcher d.addErrorHandler(self.errorHandlerTest) self.updater.start_polling(0.01) sleep(.1) self.assertEqual(self.received_message, "Test Error 2") def test_addRemoveTypeHandler(self): self._setup_updater('', messages=0) d = self.updater.dispatcher d.addTypeHandler(dict, self.stringHandlerTest) queue = self.updater.start_polling(0.01) payload = {"Test": 42} queue.put(payload) sleep(.1) self.assertEqual(self.received_message, payload) # Remove handler d.removeTypeHandler(dict, self.stringHandlerTest) self.reset() queue.put(payload) sleep(.1) self.assertTrue(None is self.received_message) def test_addRemoveInlineHandlerQuery(self): print('Testing add/removeInlineHandler') self._setup_updater('', messages=0) d = self.updater.dispatcher d.addTelegramInlineHandler(self.telegramInlineHandlerTest) queue = self.updater.start_polling(0.01) update = Update(update_id=0, inline_query="testquery") update2 = Update(update_id=0, chosen_inline_result="testresult") queue.put(update) sleep(.1) self.assertEqual(self.received_message[0], "testquery") queue.put(update2) sleep(.1) self.assertEqual(self.received_message[1], "testresult") # Remove handler d.removeTelegramInlineHandler(self.telegramInlineHandlerTest) self.reset() queue.put(update) sleep(.1) self.assertTrue(None is self.received_message) def test_runAsync(self): self._setup_updater('Test5', messages=2) d = self.updater.dispatcher d.addTelegramMessageHandler( self.asyncHandlerTest) self.updater.start_polling(0.01) sleep(1.2) self.assertEqual(self.received_message, 'Test5') self.assertEqual(self.message_count, 2) def test_additionalArgs(self): self._setup_updater('', messages=0) self.updater.dispatcher.addStringCommandHandler( 'test5', self.additionalArgsTest) queue = self.updater.start_polling(0.01) queue.put('/test5 resend') sleep(.1) self.assertEqual(self.received_message, '/test5 noresend') self.assertEqual(self.message_count, 2) def test_context(self): context = "context_data" self._setup_updater('', messages=0) self.updater.dispatcher.addStringCommandHandler( 'test_context', self.contextTest) queue = self.updater.start_polling(0.01) queue.put('/test_context', context=context) sleep(.5) self.assertEqual(self.received_message, '/test_context') self.assertEqual(self.message_count, 1) self.assertEqual(self.context, context) def test_regexGroupHandler(self): self._setup_updater('', messages=0) d = self.updater.dispatcher d.addStringRegexHandler('^(This).*?(?P<testgroup>regex group).*', self.regexGroupHandlerTest) queue = self.updater.start_polling(0.01) queue.put('This is a test message for regex group matching.') sleep(.1) self.assertEqual(self.received_message, (('This', 'regex group'), {'testgroup': 'regex group'})) def test_runAsyncWithAdditionalArgs(self): self._setup_updater('Test6', messages=2) d = self.updater.dispatcher d.addTelegramMessageHandler( self.asyncAdditionalHandlerTest) self.updater.start_polling(0.01) sleep(1.2) self.assertEqual(self.received_message, 'Test6') self.assertEqual(self.message_count, 2) def test_webhook(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, 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 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_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_bootstrap_retries_success(self): retries = 3 self._setup_updater('', messages=0, bootstrap_retries=retries) self.updater._set_webhook('path', retries) self.assertEqual(self.updater.bot.bootstrap_attempts, retries) def test_bootstrap_retries_unauth(self): retries = 3 self._setup_updater('', messages=0, bootstrap_retries=retries, bootstrap_err=Unauthorized()) self.assertRaises(Unauthorized, self.updater._set_webhook, 'path', retries) self.assertEqual(self.updater.bot.bootstrap_attempts, 1) def test_bootstrap_retries_invalid_token(self): retries = 3 self._setup_updater('', messages=0, bootstrap_retries=retries, bootstrap_err=InvalidToken()) self.assertRaises(InvalidToken, self.updater._set_webhook, 'path', retries) self.assertEqual(self.updater.bot.bootstrap_attempts, 1) def test_bootstrap_retries_fail(self): retries = 1 self._setup_updater('', messages=0, bootstrap_retries=retries) self.assertRaisesRegexp(TelegramError, 'test', self.updater._set_webhook, 'path', retries - 1) self.assertEqual(self.updater.bot.bootstrap_attempts, 1) def test_webhook_invalid_posts(self): self._setup_updater('', messages=0) ip = '127.0.0.1' port = randrange(1024, 49152) # select random port for travis thr = Thread(target=self.updater._start_webhook, args=(ip, port, '', None, None, 0, None)) thr.start() sleep(0.5) try: with self.assertRaises(HTTPError) as ctx: self._send_webhook_msg(ip, port, '<root><bla>data</bla></root>', content_type='application/xml') self.assertEqual(ctx.exception.code, 403) with self.assertRaises(HTTPError) as ctx: self._send_webhook_msg(ip, port, 'dummy-payload', content_len=-2) self.assertEqual(ctx.exception.code, 403) # TODO: prevent urllib or the underlying from adding content-length # with self.assertRaises(HTTPError) as ctx: # self._send_webhook_msg(ip, port, 'dummy-payload', # content_len=None) # self.assertEqual(ctx.exception.code, 411) with self.assertRaises(HTTPError) as ctx: self._send_webhook_msg(ip, port, 'dummy-payload', content_len='not-a-number') self.assertEqual(ctx.exception.code, 403) finally: self.updater._stop_httpd() thr.join() def _send_webhook_msg(self, ip, port, payload_str, url_path='', content_len=-1, content_type='application/json', get_method=None): headers = { 'content-type': content_type, } if not payload_str: content_len = None payload = None else: payload = bytes(payload_str, encoding='utf-8') if content_len == -1: content_len = len(payload) if content_len is not None: headers['content-length'] = str(content_len) url = 'http://{ip}:{port}/{path}'.format(ip=ip, port=port, path=url_path) req = Request(url, data=payload, headers=headers) if get_method is not None: req.get_method = get_method return urlopen(req) def signalsender(self): sleep(0.5) os.kill(os.getpid(), signal.SIGTERM) def test_idle(self): self._setup_updater('Test6', messages=0) self.updater.start_polling(poll_interval=0.01) Thread(target=self.signalsender).start() self.updater.idle() # If we get this far, idle() ran through sleep(1) self.assertFalse(self.updater.running) def test_createBot(self): updater = Updater('123:abcd') self.assertIsNotNone(updater.bot) def test_mutualExclusiveTokenBot(self): bot = Bot('123:zyxw') self.assertRaises(ValueError, Updater, token='123:abcd', bot=bot) def test_noTokenOrBot(self): self.assertRaises(ValueError, Updater)
class UpdaterTest(BaseTest, unittest.TestCase): """ This object represents Tests for Updater, Dispatcher, WebhookServer and WebhookHandler """ def setUp(self): self.updater = None self.received_message = None self.message_count = 0 self.lock = Lock() def _setup_updater(self, *args, **kwargs): bot = MockBot(*args, **kwargs) self.updater = Updater(workers=2, bot=bot) def tearDown(self): if self.updater is not None: self.updater.stop() def reset(self): self.message_count = 0 self.received_message = None def telegramHandlerTest(self, bot, update): self.received_message = update.message.text self.message_count += 1 def telegramInlineHandlerTest(self, bot, update): self.received_message = (update.inline_query, update.chosen_inline_result) self.message_count += 1 @run_async def asyncHandlerTest(self, bot, update, **kwargs): sleep(1) with self.lock: self.received_message = update.message.text self.message_count += 1 def stringHandlerTest(self, bot, update): self.received_message = update self.message_count += 1 def regexGroupHandlerTest(self, bot, update, groups=None, groupdict=None): self.received_message = (groups, groupdict) self.message_count += 1 def additionalArgsTest(self, bot, update, update_queue, args): self.received_message = update self.message_count += 1 if args[0] == 'resend': update_queue.put('/test5 noresend') elif args[0] == 'noresend': pass def contextTest(self, bot, update, context): self.received_message = update self.message_count += 1 self.context = context @run_async def asyncAdditionalHandlerTest(self, bot, update, update_queue=None, **kwargs): sleep(1) with self.lock: if update_queue is not None: self.received_message = update.message.text self.message_count += 1 def errorRaisingHandlerTest(self, bot, update): raise TelegramError(update) def errorHandlerTest(self, bot, update, error): self.received_message = error.message self.message_count += 1 def test_addRemoveTelegramMessageHandler(self): self._setup_updater('Test') d = self.updater.dispatcher d.addTelegramMessageHandler(self.telegramHandlerTest) self.updater.start_polling(0.01) sleep(.1) self.assertEqual(self.received_message, 'Test') # Remove handler d.removeTelegramMessageHandler(self.telegramHandlerTest) self.reset() self.updater.bot.send_messages = 1 sleep(.1) self.assertTrue(None is self.received_message) def test_addTelegramMessageHandlerMultipleMessages(self): self._setup_updater('Multiple', 100) self.updater.dispatcher.addTelegramMessageHandler( self.telegramHandlerTest) self.updater.start_polling(0.0) sleep(2) self.assertEqual(self.received_message, 'Multiple') self.assertEqual(self.message_count, 100) def test_addRemoveTelegramRegexHandler(self): self._setup_updater('Test2') d = self.updater.dispatcher regobj = re.compile('Te.*') self.updater.dispatcher.addTelegramRegexHandler( regobj, self.telegramHandlerTest) self.updater.start_polling(0.01) sleep(.1) self.assertEqual(self.received_message, 'Test2') # Remove handler d.removeTelegramRegexHandler(regobj, self.telegramHandlerTest) self.reset() self.updater.bot.send_messages = 1 sleep(.1) self.assertTrue(None is self.received_message) def test_addRemoveTelegramCommandHandler(self): self._setup_updater('/test') d = self.updater.dispatcher self.updater.dispatcher.addTelegramCommandHandler( 'test', self.telegramHandlerTest) self.updater.start_polling(0.01) sleep(.1) self.assertEqual(self.received_message, '/test') # Remove handler d.removeTelegramCommandHandler('test', self.telegramHandlerTest) self.reset() self.updater.bot.send_messages = 1 sleep(.1) self.assertTrue(None is self.received_message) def test_addRemoveUnknownTelegramCommandHandler(self): self._setup_updater('/test2') d = self.updater.dispatcher self.updater.dispatcher.addUnknownTelegramCommandHandler( self.telegramHandlerTest) self.updater.start_polling(0.01) sleep(.1) self.assertEqual(self.received_message, '/test2') # Remove handler d.removeUnknownTelegramCommandHandler(self.telegramHandlerTest) self.reset() self.updater.bot.send_messages = 1 sleep(.1) self.assertTrue(None is self.received_message) def test_addRemoveStringRegexHandler(self): self._setup_updater('', messages=0) d = self.updater.dispatcher d.addStringRegexHandler('Te.*', self.stringHandlerTest) queue = self.updater.start_polling(0.01) queue.put('Test3') sleep(.1) self.assertEqual(self.received_message, 'Test3') # Remove handler d.removeStringRegexHandler('Te.*', self.stringHandlerTest) self.reset() queue.put('Test3') sleep(.1) self.assertTrue(None is self.received_message) def test_addRemoveStringCommandHandler(self): self._setup_updater('', messages=0) d = self.updater.dispatcher d.addStringCommandHandler('test3', self.stringHandlerTest) queue = self.updater.start_polling(0.01) queue.put('/test3') sleep(.1) self.assertEqual(self.received_message, '/test3') # Remove handler d.removeStringCommandHandler('test3', self.stringHandlerTest) self.reset() queue.put('/test3') sleep(.1) self.assertTrue(None is self.received_message) def test_addRemoveUnknownStringCommandHandler(self): self._setup_updater('/test') d = self.updater.dispatcher d.addUnknownStringCommandHandler(self.stringHandlerTest) queue = self.updater.start_polling(0.01) queue.put('/test4') sleep(.1) self.assertEqual(self.received_message, '/test4') # Remove handler d.removeUnknownStringCommandHandler(self.stringHandlerTest) self.reset() self.updater.bot.send_messages = 1 sleep(.1) self.assertTrue(None is self.received_message) def test_addRemoveErrorHandler(self): self._setup_updater('', messages=0) d = self.updater.dispatcher d.addErrorHandler(self.errorHandlerTest) queue = self.updater.start_polling(0.01) error = TelegramError("Unauthorized.") queue.put(error) sleep(.1) self.assertEqual(self.received_message, "Unauthorized.") # Remove handler d.removeErrorHandler(self.errorHandlerTest) self.reset() queue.put(error) sleep(.1) self.assertTrue(None is self.received_message) def test_errorInHandler(self): self._setup_updater('', messages=0) d = self.updater.dispatcher d.addStringRegexHandler('.*', self.errorRaisingHandlerTest) self.updater.dispatcher.addErrorHandler(self.errorHandlerTest) queue = self.updater.start_polling(0.01) queue.put('Test Error 1') sleep(.1) self.assertEqual(self.received_message, 'Test Error 1') def test_cleanBeforeStart(self): self._setup_updater('') d = self.updater.dispatcher d.addTelegramMessageHandler(self.telegramHandlerTest) self.updater.start_polling(0.01, clean=True) sleep(.1) self.assertEqual(self.message_count, 0) self.assertIsNone(self.received_message) def test_errorOnGetUpdates(self): self._setup_updater('', raise_error=True) d = self.updater.dispatcher d.addErrorHandler(self.errorHandlerTest) self.updater.start_polling(0.01) sleep(.1) self.assertEqual(self.received_message, "Test Error 2") def test_addRemoveTypeHandler(self): self._setup_updater('', messages=0) d = self.updater.dispatcher d.addTypeHandler(dict, self.stringHandlerTest) queue = self.updater.start_polling(0.01) payload = {"Test": 42} queue.put(payload) sleep(.1) self.assertEqual(self.received_message, payload) # Remove handler d.removeTypeHandler(dict, self.stringHandlerTest) self.reset() queue.put(payload) sleep(.1) self.assertTrue(None is self.received_message) def test_addRemoveInlineHandlerQuery(self): print('Testing add/removeInlineHandler') self._setup_updater('', messages=0) d = self.updater.dispatcher d.addTelegramInlineHandler(self.telegramInlineHandlerTest) queue = self.updater.start_polling(0.01) update = Update(update_id=0, inline_query="testquery") update2 = Update(update_id=0, chosen_inline_result="testresult") queue.put(update) sleep(.1) self.assertEqual(self.received_message[0], "testquery") queue.put(update2) sleep(.1) self.assertEqual(self.received_message[1], "testresult") # Remove handler d.removeTelegramInlineHandler(self.telegramInlineHandlerTest) self.reset() queue.put(update) sleep(.1) self.assertTrue(None is self.received_message) def test_runAsync(self): self._setup_updater('Test5', messages=2) d = self.updater.dispatcher d.addTelegramMessageHandler(self.asyncHandlerTest) self.updater.start_polling(0.01) sleep(1.2) self.assertEqual(self.received_message, 'Test5') self.assertEqual(self.message_count, 2) def test_additionalArgs(self): self._setup_updater('', messages=0) self.updater.dispatcher.addStringCommandHandler( 'test5', self.additionalArgsTest) queue = self.updater.start_polling(0.01) queue.put('/test5 resend') sleep(.1) self.assertEqual(self.received_message, '/test5 noresend') self.assertEqual(self.message_count, 2) def test_context(self): context = "context_data" self._setup_updater('', messages=0) self.updater.dispatcher.addStringCommandHandler( 'test_context', self.contextTest) queue = self.updater.start_polling(0.01) queue.put('/test_context', context=context) sleep(.5) self.assertEqual(self.received_message, '/test_context') self.assertEqual(self.message_count, 1) self.assertEqual(self.context, context) def test_regexGroupHandler(self): self._setup_updater('', messages=0) d = self.updater.dispatcher d.addStringRegexHandler('^(This).*?(?P<testgroup>regex group).*', self.regexGroupHandlerTest) queue = self.updater.start_polling(0.01) queue.put('This is a test message for regex group matching.') sleep(.1) self.assertEqual(self.received_message, (('This', 'regex group'), { 'testgroup': 'regex group' })) def test_runAsyncWithAdditionalArgs(self): self._setup_updater('Test6', messages=2) d = self.updater.dispatcher d.addTelegramMessageHandler(self.asyncAdditionalHandlerTest) self.updater.start_polling(0.01) sleep(1.2) self.assertEqual(self.received_message, 'Test6') self.assertEqual(self.message_count, 2) def test_webhook(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, 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 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_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_bootstrap_retries_success(self): retries = 3 self._setup_updater('', messages=0, bootstrap_retries=retries) self.updater._set_webhook('path', retries) self.assertEqual(self.updater.bot.bootstrap_attempts, retries) def test_bootstrap_retries_unauth(self): retries = 3 self._setup_updater('', messages=0, bootstrap_retries=retries, bootstrap_err=Unauthorized()) self.assertRaises(Unauthorized, self.updater._set_webhook, 'path', retries) self.assertEqual(self.updater.bot.bootstrap_attempts, 1) def test_bootstrap_retries_invalid_token(self): retries = 3 self._setup_updater('', messages=0, bootstrap_retries=retries, bootstrap_err=InvalidToken()) self.assertRaises(InvalidToken, self.updater._set_webhook, 'path', retries) self.assertEqual(self.updater.bot.bootstrap_attempts, 1) def test_bootstrap_retries_fail(self): retries = 1 self._setup_updater('', messages=0, bootstrap_retries=retries) self.assertRaisesRegexp(TelegramError, 'test', self.updater._set_webhook, 'path', retries - 1) self.assertEqual(self.updater.bot.bootstrap_attempts, 1) def test_webhook_invalid_posts(self): self._setup_updater('', messages=0) ip = '127.0.0.1' port = randrange(1024, 49152) # select random port for travis thr = Thread(target=self.updater._start_webhook, args=(ip, port, '', None, None, 0, None)) thr.start() sleep(0.5) try: with self.assertRaises(HTTPError) as ctx: self._send_webhook_msg(ip, port, '<root><bla>data</bla></root>', content_type='application/xml') self.assertEqual(ctx.exception.code, 403) with self.assertRaises(HTTPError) as ctx: self._send_webhook_msg(ip, port, 'dummy-payload', content_len=-2) self.assertEqual(ctx.exception.code, 403) # TODO: prevent urllib or the underlying from adding content-length # with self.assertRaises(HTTPError) as ctx: # self._send_webhook_msg(ip, port, 'dummy-payload', # content_len=None) # self.assertEqual(ctx.exception.code, 411) with self.assertRaises(HTTPError) as ctx: self._send_webhook_msg(ip, port, 'dummy-payload', content_len='not-a-number') self.assertEqual(ctx.exception.code, 403) finally: self.updater._stop_httpd() thr.join() def _send_webhook_msg(self, ip, port, payload_str, url_path='', content_len=-1, content_type='application/json', get_method=None): headers = { 'content-type': content_type, } if not payload_str: content_len = None payload = None else: payload = bytes(payload_str, encoding='utf-8') if content_len == -1: content_len = len(payload) if content_len is not None: headers['content-length'] = str(content_len) url = 'http://{ip}:{port}/{path}'.format(ip=ip, port=port, path=url_path) req = Request(url, data=payload, headers=headers) if get_method is not None: req.get_method = get_method return urlopen(req) def signalsender(self): sleep(0.5) os.kill(os.getpid(), signal.SIGTERM) def test_idle(self): self._setup_updater('Test6', messages=0) self.updater.start_polling(poll_interval=0.01) Thread(target=self.signalsender).start() self.updater.idle() # If we get this far, idle() ran through sleep(1) self.assertFalse(self.updater.running) def test_createBot(self): updater = Updater('123:abcd') self.assertIsNotNone(updater.bot) def test_mutualExclusiveTokenBot(self): bot = Bot('123:zyxw') self.assertRaises(ValueError, Updater, token='123:abcd', bot=bot) def test_noTokenOrBot(self): self.assertRaises(ValueError, Updater)
class TelegramManager(Component): INTERCOM_MESSAGE_EVENT_CHAT_START = 'telegram-event-chat-start' INTERCOM_MESSAGE_EVENT_CHAT_MESSAGE = 'telegram-event-chat-message' INTERCOM_MESSAGE_DO_VIDEO_MESSAGE = 'telegram-do-video-message' INTERCOM_MESSAGE_DO_PHOTO_MESSAGE = 'telegram-do-photo-message' INTERCOM_MESSAGE_DO_DOCUMENT_MESSAGE = 'telegram-do-document-message' INTERCOM_MESSAGE_DO_CHAT_MESSAGE = 'telegram-do-chat-message' INTERCOM_MESSAGE_DO_SEND_CAM_SNAPSHOT = 'telegram-do-send-cam-snapshot' INTERCOM_MESSAGE_DO_SEND_CAM_VIDEO = 'telegram-do-send-cam-video' _allowed_users = [] _token = None _current_token = None _updater = None _bot = None _runtime_file_mutex = Lock() _chat_ids = {} def _get_settings_file(cls): return App.get_settings_path() + '/telegram.yml' def _get_runtime_file(cls): return App.get_settings_path() + '/telegram_runtime.yml' def _load_runtime(self): self._chat_ids = {} runtime_file = self._get_runtime_file() try: runtime = yaml.load(open(runtime_file, 'r')) Log.info("Loading runtime from " + runtime_file) except: Log.error("Loading runtime failed from " + runtime_file) return self._chat_ids = runtime['chat_ids'] def _save_runtime(self): runtime_file = self._get_runtime_file() runtime = {'chat_ids': self._chat_ids} self._runtime_file_mutex.acquire() yaml.dump(runtime, open(runtime_file, 'w'), default_flow_style=False) self._runtime_file_mutex.release() def _add_chat_id(self, user, chat_id): must_save = (user not in self._chat_ids or self._chat_ids[user] != chat_id) self._chat_ids[user] = chat_id if must_save: self._save_runtime() def get_variables(self): if self.get_bot() is not None: return { 'telegram_bot_name': self.get_bot().username, 'telegram_bot_first_name': self.get_bot().first_name, 'telegram_bot_last_name': self.get_bot().last_name, } else: return {} def load_settings(self): self._allowed_users = [] settings_file = self._get_settings_file() try: settings = yaml.load(open(settings_file, 'r')) Log.info("Loading settings from " + settings_file) except: Log.error("Loading settings failed from " + settings_file) return self._token = settings['token'] self._allowed_users = settings['users'] def get_is_allowed_message(self, update: Update): """ Return true if user is allowed to send messages :param update: :return: """ return update.message.from_user.username in self._allowed_users def get_bot(self) -> Bot: return self._bot def get_chat_id(self, username): if username not in self._chat_ids: return None return self._chat_ids[username] def send_message(self, text, recipients=None): if recipients is None: recipients = self._allowed_users for recipient in recipients: chat_id = self.get_chat_id(recipient) if chat_id is not None: self.get_bot().sendMessage(chat_id, text) else: Log.error('Unknown chat ID for user ' + recipient + ', please send a message to this bot') def send_picture(self, file_name, caption=None, recipients=None): if file_name is None: return try: if recipients is None: recipients = self._allowed_users for recipient in recipients: chat_id = self.get_chat_id(recipient) if chat_id is not None: self.get_bot().sendPhoto(chat_id=chat_id, photo=open(file_name, 'rb'), caption=caption) else: Log.error('Unknown chat ID for user ' + recipient + ', please send a message to this bot') except telegram.error.BadRequest: pass except FileNotFoundError: Log.error('File ' + file_name + ' not found') def send_video(self, file, caption=None, recipients=None): if file is None: return try: if recipients is None: recipients = self._allowed_users for recipient in recipients: chat_id = self.get_chat_id(recipient) if chat_id is not None: self.get_bot().sendDocument( chat_id=chat_id, document=open(file, 'rb'), filename=os.path.basename(file), caption=caption) else: Log.error('Unknown chat ID for user ' + recipient + ', please send a message to this bot') except telegram.error.BadRequest: pass except FileNotFoundError: Log.error('File ' + file + ' not found') send_document = send_video def _on_intercom_message_send_chat(self, message: Message) -> Reply: payload = message.message_payload recipients = None if 'to' in payload: recipients = re.split(r'\s*,\s*', payload['to']) self.send_message(text=payload['text'], recipients=recipients) return Reply(Reply.INTERCOM_STATUS_SUCCESS) def _send_cam_snapshot(self, cam: Cam, recipients): cam_snapshot = self.send_intercom_message( CamManager.INTERCOM_MESSAGE_DO_SNAPSHOT, {'cam': cam}) if cam_snapshot != Reply.INTERCOM_STATUS_SUCCESS: return caption = CamRepo.get_by_code(cam).name reply_payload = cam_snapshot.get_payload() for from_component, component_payload in reply_payload.items(): if component_payload['status'] == Reply.INTERCOM_STATUS_SUCCESS and \ from_component == CamManager.get_instance().get_code(): file_name = component_payload['payload']['filename'] # Async upload threading.Thread(target=self.send_picture, kwargs={ 'file_name': file_name, 'caption': caption, 'recipients': recipients, }).start() def _send_cam_video(self, cam: Cam, recipients, duration): res = self.send_intercom_message( CamManager.INTERCOM_MESSAGE_DO_VIDEO_START, {'cam': cam}) if res != Reply.INTERCOM_STATUS_SUCCESS: return time.sleep(duration) res = self.send_intercom_message( CamManager.INTERCOM_MESSAGE_DO_VIDEO_STOP, {'cam': cam}) if res != Reply.INTERCOM_STATUS_SUCCESS: return caption = CamRepo.get_by_code(cam).name reply_payload = res.get_payload() for from_component, component_payload in reply_payload.items(): if component_payload['status'] == Reply.INTERCOM_STATUS_SUCCESS and \ from_component == CamManager.get_instance().get_code(): file_name = component_payload['payload']['filename'] # Async upload threading.Thread(target=self.send_video, kwargs={ 'file_name': file_name, 'caption': caption, 'recipients': recipients, }).start() def _on_cam_action(self, message: Message) -> Reply: payload = message.message_payload cams = payload['cam'].split(',') for cam in cams: recipients = None if 'to' in payload: recipients = re.split(r'\s*,\s*', payload['to']) if message == self.INTERCOM_MESSAGE_DO_SEND_CAM_SNAPSHOT: self._send_cam_snapshot(cam=cam, recipients=recipients) elif message == self.INTERCOM_MESSAGE_DO_SEND_CAM_VIDEO: duration = 10 if 'duration' in message.message_payload: duration = message.message_payload['duration'] self._send_cam_video(cam=cam, recipients=recipients, duration=duration) return Reply(Reply.INTERCOM_STATUS_SUCCESS) def _on_intercom_message_cam_action(self, message: Message) -> Reply: payload = message.message_payload cams = payload['cam'].split(',') for cam in cams: recipients = None if 'to' in payload: recipients = re.split(r'\s*,\s*', payload['to']) # Async images send threading.Thread(target=self._on_cam_action, kwargs={ 'cam': cam, 'recipients': recipients }).start() return Reply(Reply.INTERCOM_STATUS_SUCCESS) def _on_intercom_message_complex_message(self, message: Message) -> Reply: payload = message.message_payload filename = message.message_payload['filename'] if not os.path.isfile(filename) or not App.can_access_file(filename): return Reply(Reply.INTERCOM_STATUS_NON_BLOCKING_FAILURE) caption = os.path.basename() if 'caption' in message.message_payload: caption = message.message_payload[filename] recipients = None if 'to' in payload: recipients = re.split(r'\s*,\s*', payload['to']) if message == self.INTERCOM_MESSAGE_DO_PHOTO_MESSAGE: self.send_picture(file_name=filename, caption=caption, recipients=recipients) elif message == self.INTERCOM_MESSAGE_DO_VIDEO_MESSAGE: self.send_video(file=filename, caption=caption, recipients=recipients) elif message == self.INTERCOM_MESSAGE_DO_DOCUMENT_MESSAGE: self.send_video(file=filename, caption=caption, recipients=recipients) return Reply(Reply.INTERCOM_STATUS_SUCCESS) def _on_intercom_message(self, message: Message) -> Reply: if message == self.INTERCOM_MESSAGE_DO_CHAT_MESSAGE: return self._on_intercom_message_send_chat(message) if message in [ self.INTERCOM_MESSAGE_DO_SEND_CAM_SNAPSHOT, self.INTERCOM_MESSAGE_DO_SEND_CAM_VIDEO ]: return self._on_cam_action(message) if message in [ self.INTERCOM_MESSAGE_DO_PHOTO_MESSAGE, self.INTERCOM_MESSAGE_DO_VIDEO_MESSAGE, self.INTERCOM_MESSAGE_DO_DOCUMENT_MESSAGE ]: return self._on_intercom_message_complex_message(message) return Component._on_intercom_message(self, message) def _get_update_info_for_payload(self, update: Update): return { 'from': update.message.from_user.username, 'from_first_name': update.message.from_user.first_name, 'from_last_name': update.message.from_user.last_name, 'text': update.message.text, } def _on_command_start(self, bot: Bot, update: Update): self._add_chat_id(update.message.from_user.username, update.message.chat_id) if self.get_is_allowed_message(update): self.send_intercom_message( self.INTERCOM_MESSAGE_EVENT_CHAT_START, self._get_update_info_for_payload(update)) def _on_message(self, bot: Bot, update: Update): self._add_chat_id(update.message.from_user.username, update.message.chat_id) if self.get_is_allowed_message(update): self.send_intercom_message( self.INTERCOM_MESSAGE_EVENT_CHAT_MESSAGE, self._get_update_info_for_payload(update)) def _start_bot(self): self._updater = Updater(token=self._token) self._bot = self._updater.bot self._updater.dispatcher.add_handler( CommandHandler('start', self._on_command_start)) self._updater.dispatcher.add_handler( MessageHandler([Filters.text], self._on_message)) self._updater.start_polling() def _stop_bot(self): if self._updater is not None: self._updater.stop() del self._updater def _reload(self): self.load_settings() if self._current_token != self._token: self._current_token = self._token self._stop_bot() self._load_runtime() self._start_bot() return True def start(self): Component.start(self) self.reload()
class TelegramMessageHandler(object): def __init__(self): self.updater = Updater( '475775136:AAFkVNGakPSCINOHKdE6jv7MKRPZXN5WoQ4') #Token def start(self, bot, update): update.message.reply_text('Olá {}! Seja muito bem-vindo'.format( update.message.from_user.first_name)) time.sleep(3) update.message.reply_text('Muito prazer, eu sou o Jay') time.sleep(3) update.message.reply_text( 'e estou aqui para te ajudar a conhecer São José dos Campos. \nVamos lá!? \õ/' ) def hello(self, bot, update): update.message.reply_text('Oi {}! É bom ter você por aqui :D'.format( update.message.from_user.first_name)) time.sleep(2) self.reply_text('Olha... eu garanto que você não vai se arrepender!') def support(self, bot, update): update.message.reply_text( 'vejo que você precisa de ajuda uma ajuda {}'.format( update.message.from_user.first_name)) time.sleep(2) update.message.reply_text('me diz o que precisa..') def mess_receive_user(self, bot, update): nbCustom = NaiveBayesCustom() nbCustom.classifyTextFromIM( update.message.text) # self.get_last_mess() place = nbCustom.getClassification() probMax = nbCustom.getProbMaxClassification() #print('\nProbabilidade Máxima: ', probMax) #print('\nClasse: ', place) if (probMax < 0.5000): update.message.reply_text( 'não consigo te orientar porque não entendi o que vc quis dizer' ) elif (probMax >= 0.5000 and probMax < 0.7500): update.message.reply_text('olha {}, não é certeza mas.. '.format( update.message.from_user.first_name)) time.sleep(2) update.message.reply_text('talvez vc vai gostar de ir no ' + place) elif (probMax <= 0.7500 and probMax < 0.8500): update.message.reply_text( place + ' seria um bom lugar pra vc ir {}'.format( update.message.from_user.first_name)) else: update.message.reply_text( place + ' é o lugar pra vc ir com toda certeza!'.format( update.message.from_user.first_name)) ''' def get_last_mess(self): messages = self.updater.bot.getUpdates() print(len(messages)) if (len(messages) == 0): return '' else: print("mensagens: ", messages) print("Ultima msg: ", messages[len(messages)-1]['message']['text']) return messages[len(messages)-1]['message']['text'] ''' def run_dispatcher(self): self.updater.dispatcher.add_handler(CommandHandler( 'start', self.start)) self.updater.dispatcher.add_handler(CommandHandler( 'hello', self.hello)) self.updater.dispatcher.add_handler( CommandHandler('support', self.support)) receive_msg_handler = MessageHandler([Filters.text], self.mess_receive_user) self.updater.dispatcher.add_handler(receive_msg_handler) def start_bot(self): self.run_dispatcher() self.updater.start_polling() print("\n-------------------------------------------------") print("|\tTelegram Bot Inicialized with Success \t|") print("-------------------------------------------------\n") self.updater.idle() def stop_bot(self): self.updater.stop()