def create_update(self, serializer, bot): try: user = caching.get_or_set(TelegramUser, serializer.data['message']['from']['id']) except TelegramUser.DoesNotExist: user, _ = TelegramUser.objects.get_or_create( **serializer.data['message']['from']) try: chat = caching.get_or_set(TelegramChat, serializer.data['message']['chat']['id']) except TelegramChat.DoesNotExist: chat, _ = TelegramChat.objects.get_or_create( **serializer.data['message']['chat']) if 'text' not in serializer.data['message']: raise OnlyTextMessages message, _ = TelegramMessage.objects.get_or_create( message_id=serializer.data['message']['message_id'], from_user=user, date=datetime.fromtimestamp(serializer.data['message']['date']), chat=chat, text=serializer.data['message']['text']) update, _ = TelegramUpdate.objects.get_or_create( bot=bot, update_id=serializer.data['update_id'], message=message) caching.set(update) return update
def handle_messenger_message(message_id, bot_id): try: message = caching.get_or_set(MessengerMessage, message_id) messenger_bot = caching.get_or_set(MessengerBot, bot_id) except MessengerMessage.DoesNotExist: logger.error("Message %s does not exists" % message_id) except MessengerBot.DoesNotExist: logger.error("Bot %s does not exists or disabled" % bot_id) except: logger.error("Error handling update %s from bot %s" % (message_id, bot_id)) else: try: messenger_bot.bot.handle_message(message, messenger_bot) except: exc_info = sys.exc_info() traceback.print_exception(*exc_info) logger.error("Error processing %s for bot %s" % (message, messenger_bot)) else: # Each update is only used once caching.delete(MessengerMessage, message)
def handle_update(update_id, bot_id): try: update = caching.get_or_set(TelegramUpdate, update_id) telegram_bot = caching.get_or_set(TelegramBot, bot_id) except TelegramUpdate.DoesNotExist: logger.error("Update %s does not exists" % update_id) except TelegramBot.DoesNotExist: logger.error("Bot %s does not exists or disabled" % bot_id) except: logger.error("Error handling update %s from bot %s" % (update_id, bot_id)) else: try: telegram_bot.bot.handle_message(update, telegram_bot) except: exc_info = sys.exc_info() traceback.print_exception(*exc_info) logger.error("Error processing %s for bot %s" % (update, telegram_bot)) else: # Each update is only used once caching.delete(TelegramUpdate, update)
def get(self, request, hook_id): """ Verify token when configuring webhook from facebook dev. MessengerBot.id is used for verification """ try: bot = caching.get_or_set(MessengerBot, hook_id) except MessengerBot.DoesNotExist: logger.warning("Hook id %s not associated to a bot" % hook_id) return Response(status=status.HTTP_404_NOT_FOUND) if request.query_params.get('hub.verify_token') == str(bot.id): return Response(int(request.query_params.get('hub.challenge'))) return Response('Error, wrong validation token')
def post(self, request, hook_id): """ Process Kik webhook: 1. Get an enabled Kik bot 2. Verify Kik signature 3. Serialize each message 4. For each message create :class:`KikMessage <permabots.models.kik_api.KikMessage>` and :class:`KikUser <permabots.models.kik_api.KikUser>` 5. Delay each message processing to a task 6. Response provider """ try: bot = caching.get_or_set(KikBot, hook_id) except KikBot.DoesNotExist: logger.warning("Hook id %s not associated to a bot" % hook_id) return Response(status=status.HTTP_404_NOT_FOUND) signature = request.META.get('HTTP_X_KIK_SIGNATURE') if signature: signature.encode('utf-8') if not bot._bot.verify_signature(signature, request.stream.body): logger.debug("Kik Bot data %s not verified %s" % (request.data, signature)) return Response(status=403) logger.debug("Kik Bot data %s verified" % (request.data)) for kik_message in request.data['messages']: serializer = KikMessageSerializer(data=kik_message) logger.debug("Kik message %s serialized" % (kik_message)) if serializer.is_valid(): try: if not self.accepted_types(serializer): raise OnlyTextMessages message = self.create_message(serializer, bot) if bot.enabled: logger.debug("Kik Bot %s attending request %s" % (bot, kik_message)) handle_message.delay(message.id, bot.id) else: logger.error("Message %s ignored by disabled bot %s" % (message, bot)) except OnlyTextMessages: logger.warning("Not text message %s for bot %s" % (kik_message, hook_id)) return Response(status=status.HTTP_200_OK) except: exc_info = sys.exc_info() traceback.print_exception(*exc_info) logger.error("Error processing %s for bot %s" % (kik_message, hook_id)) return Response(serializer.errors, status=status.HTTP_500_INTERNAL_SERVER_ERROR) else: logger.error("Validation error: %s from kik message %s" % (serializer.errors, kik_message)) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(serializer.data, status=status.HTTP_200_OK)
def post(self, request, hook_id): """ Process Telegram webhook. 1. Serialize Telegram message 2. Get an enabled Telegram bot 3. Create :class:`Update <permabots.models.telegram_api.Update>` 5. Delay processing to a task 6. Response provider """ serializer = UpdateSerializer(data=request.data) if serializer.is_valid(): try: bot = caching.get_or_set(TelegramBot, hook_id) except TelegramBot.DoesNotExist: logger.warning("Hook id %s not associated to an bot" % hook_id) return Response(serializer.errors, status=status.HTTP_404_NOT_FOUND) try: update = self.create_update(serializer, bot) if bot.enabled: logger.debug("Telegram Bot %s attending request %s" % (bot.token, request.data)) handle_update.delay(update.id, bot.id) else: logger.error("Update %s ignored by disabled bot %s" % (update, bot.token)) except OnlyTextMessages: logger.warning("Not text message %s for bot %s" % (request.data, hook_id)) return Response(status=status.HTTP_200_OK) except: exc_info = sys.exc_info() traceback.print_exception(*exc_info) logger.error("Error processing %s for bot %s" % (request.data, hook_id)) 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 post(self, request, hook_id): """ Process Messenger webhook. 1. Get an enabled Messenger bot 3. For each message serialize 4. For each message create :class:`MessengerMessage <permabots.models.messenger_api.MessengerMessage>` 5. Delay processing of each message to a task 6. Response provider """ try: bot = caching.get_or_set(MessengerBot, hook_id) except MessengerBot.DoesNotExist: logger.warning("Hook id %s not associated to a bot" % hook_id) return Response(status=status.HTTP_404_NOT_FOUND) logger.debug("Messenger Bot %s attending request %s" % (bot, request.data)) webhook = Webhook.from_json(request.data) for webhook_entry in webhook.entries: for webhook_message in webhook_entry.messaging: try: if webhook_message.is_delivery: raise OnlyTextMessages message = self.create_message(webhook_message, bot) if bot.enabled: logger.debug("Messenger Bot %s attending request %s" % (bot, message)) handle_messenger_message.delay(message.id, bot.id) else: logger.error("Message %s ignored by disabled bot %s" % (message, bot)) except OnlyTextMessages: logger.warning("Not text message %s for bot %s" % (message, hook_id)) except: exc_info = sys.exc_info() traceback.print_exception(*exc_info) logger.error("Error processing %s for bot %s" % (webhook_message, hook_id)) return Response( status=status.HTTP_500_INTERNAL_SERVER_ERROR) return Response(status=status.HTTP_200_OK)
def create_message(self, serializer, bot): sender = self.create_user(serializer.data['from']) try: chat = caching.get_or_set(KikChat, serializer.data['chatId']) except KikChat.DoesNotExist: chat, _ = KikChat.objects.get_or_create(id=serializer.data['chatId']) if 'participants' in serializer.data: for participant in serializer.data['participants']: chat.participants.add(self.create_user(participant)) if serializer.data['type'] == 'start-chatting': body = "/start" elif serializer.data['type'] == 'scan-data': body = "/start" else: body = serializer.data['body'] message, _ = KikMessage.objects.get_or_create(message_id=serializer.data['id'], from_user=sender, timestamp=datetime.fromtimestamp(serializer.data['timestamp']), chat=chat, body=body) caching.set(message) return message
def create_user(self, username): try: user = caching.get_or_set(KikUser, username) except KikUser.DoesNotExist: user, _ = KikUser.objects.get_or_create(username=username) return user
def create_update(self, serializer, bot): if 'message' in serializer.data: try: user = caching.get_or_set( TelegramUser, serializer.data['message']['from']['id']) except TelegramUser.DoesNotExist: user, _ = TelegramUser.objects.get_or_create( **serializer.data['message']['from']) try: chat = caching.get_or_set( TelegramChat, serializer.data['message']['chat']['id']) except TelegramChat.DoesNotExist: chat, _ = TelegramChat.objects.get_or_create( **serializer.data['message']['chat']) if 'text' not in serializer.data['message']: raise OnlyTextMessages message, _ = TelegramMessage.objects.get_or_create( message_id=serializer.data['message']['message_id'], from_user=user, date=datetime.fromtimestamp( serializer.data['message']['date']), chat=chat, text=serializer.data['message']['text']) update, _ = TelegramUpdate.objects.get_or_create( bot=bot, update_id=serializer.data['update_id'], message=message) elif 'callback_query' in serializer.data: # Message may be not present if it is very old if 'message' in serializer.data['callback_query']: try: user = caching.get_or_set( TelegramUser, serializer.data['callback_query'] ['message']['from']['id']) except TelegramUser.DoesNotExist: user, _ = TelegramUser.objects.get_or_create( **serializer.data['callback_query']['message']['from']) try: chat = caching.get_or_set( TelegramChat, serializer.data['callback_query'] ['message']['chat']['id']) except TelegramChat.DoesNotExist: chat, _ = TelegramChat.objects.get_or_create( **serializer.data['callback_query']['message']['chat']) message, _ = TelegramMessage.objects.get_or_create( message_id=serializer.data['callback_query']['message'] ['message_id'], from_user=user, date=datetime.fromtimestamp( serializer.data['callback_query']['message']['date']), chat=chat, text=serializer.data['callback_query']['message']['text']) else: message = None try: user = caching.get_or_set( TelegramUser, serializer.data['callback_query']['from']['id']) except TelegramUser.DoesNotExist: user, _ = TelegramUser.objects.get_or_create( **serializer.data['callback_query']['from']) callback_query, _ = TelegramCallbackQuery.objects.get_or_create( callback_id=serializer.data['callback_query']['id'], from_user=user, message=message, data=serializer.data['callback_query']['data']) update, _ = TelegramUpdate.objects.get_or_create( bot=bot, update_id=serializer.data['update_id'], callback_query=callback_query) else: logger.error("Not valid message %s" % serializer.data) raise OnlyTextMessages caching.set(update) return update