def test_client_subscribe(self, mock_post): mock_post.return_value.status_code = 200 mock_post.return_value.json.return_value = {'success': True} messenger = MessengerClient(access_token='1234') messenger.subscribe_app() mock_post.assert_called_with( 'https://graph.facebook.com/v2.6/me/subscribed_apps', params={'access_token': '1234'})
def test_client_subscribe(self, mock_post): mock_post.return_value.status_code = 200 mock_post.return_value.json.return_value = { 'success': True } messenger = MessengerClient(access_token='1234') messenger.subscribe_app() mock_post.assert_called_with( 'https://graph.facebook.com/v2.6/me/subscribed_apps', params={'access_token': '1234'} )
class MessengerBot(IntegrationBot): """ Facebook Messenger integration. Permabots only uses Page Access Token but webhook is not set. It mus be set manually in Facebook dev platform using UUID generated as id of the messenger bot after creation in Permabots. This bot is used to Verify Token and generate url https://domain/processing/messengerbot/permabots_messenger_bot_id/ Read Messenger documentation `<https://developers.facebook.com/docs/messenger-platform/quickstart>` _. """ token = models.CharField(_('Messenger Token'), max_length=512, db_index=True) class Meta: verbose_name = _('Messenger Bot') verbose_name_plural = _('Messenger Bots') def __init__(self, *args, **kwargs): super(MessengerBot, self).__init__(*args, **kwargs) self._bot = None self.webhook = False if self.token: self.init_bot() def __str__(self): return "%s" % self.token def __repr__(self): return "(%s, %s)" % (self.id, self.token) def init_bot(self): self._bot = MessengerClient(self.token) def set_webhook(self, url): # Url is set in facebook dashboard. Just subscribe self._bot.subscribe_app() @property def hook_url(self): return 'permabots:messengerbot' @property def hook_id(self): return str(self.id) @property def null_url(self): # not used return "https://example.com" @property def identity(self): return 'messenger' def message_text(self, message): return message.data def get_chat_state(self, message): try: return MessengerChatState.objects.select_related('state').get( chat=message.sender, state__bot=self.bot) except MessengerChatState.DoesNotExist: return None def build_keyboard(self, keyboard): def traverse(o, tree_types=(list, tuple)): if isinstance(o, tree_types): for value in o: for subvalue in traverse(value, tree_types): yield subvalue else: yield o built_keyboard = None if keyboard: # same payload as title built_keyboard = [ PostbackButton(element[0:20], element) for element in traverse(ast.literal_eval(keyboard)) ] return built_keyboard def create_chat_state(self, message, target_state, context): MessengerChatState.objects.create(chat=message.sender, state=target_state, ctx=context) def get_chat_id(self, message): return message.sender def send_message(self, chat_id, text, keyboard, reply_message=None, user=None): texts = text.strip().split('\\n') msgs = [] for txt in texts: for chunk in textwrap.wrap(txt, 320): msgs.append(messages.Message(text=chunk)) if keyboard: if len(msgs[-1].text) <= 45: title = msgs.pop().text else: new_texts = textwrap.wrap(msgs[-1].text, 45) msgs[-1].text = " ".join(new_texts[:-1]) title = new_texts[-1] elements = [] for chunk_buttons, last in self.batch(keyboard[0:30], 3): elements.append(Element(title=title, buttons=chunk_buttons)) generic_template = GenericTemplate(elements) attachment = TemplateAttachment(generic_template) msgs.append(messages.Message(attachment=attachment)) for msg in msgs: try: logger.debug("Message to send:(%s)" % msg.to_dict()) recipient = messages.Recipient(recipient_id=chat_id) self._bot.send(messages.MessageRequest(recipient, msg)) logger.debug("Message sent OK:(%s)" % msg.to_dict()) except: exctype, value = sys.exc_info()[:2] logger.error("Error trying to send message:(%s): %s:%s" % (msg.to_dict(), exctype, value))
class MessengerBot(IntegrationBot): """ Facebook Messenger integration. Permabots only uses Page Access Token but webhook is not set. It mus be set manually in Facebook dev platform using UUID generated as id of the messenger bot after creation in Permabots. This bot is used to Verify Token and generate url https://domain/processing/messengerbot/permabots_messenger_bot_id/ Read Messenger documentation `<https://developers.facebook.com/docs/messenger-platform/quickstart>` _. """ token = models.CharField(_('Messenger Token'), max_length=512, db_index=True) class Meta: verbose_name = _('Messenger Bot') verbose_name_plural = _('Messenger Bots') def __init__(self, *args, **kwargs): super(MessengerBot, self).__init__(*args, **kwargs) self._bot = None self.webhook = False if self.token: self.init_bot() def __str__(self): return "%s" % self.token def __repr__(self): return "(%s, %s)" % (self.id, self.token) def init_bot(self): self._bot = MessengerClient(self.token) def set_webhook(self, url): # Url is set in facebook dashboard. Just subscribe self._bot.subscribe_app() @property def hook_url(self): return 'permabots:messengerbot' @property def hook_id(self): return str(self.id) @property def null_url(self): # not used return "https://example.com" @property def identity(self): return 'messenger' def message_text(self, message): return message.data def get_chat_state(self, message): try: return MessengerChatState.objects.select_related('state').get(chat=message.sender, state__bot=self.bot) except MessengerChatState.DoesNotExist: return None def build_keyboard(self, keyboard): def traverse(o, tree_types=(list, tuple)): if isinstance(o, tree_types): for value in o: for subvalue in traverse(value, tree_types): yield subvalue else: yield o built_keyboard = None if keyboard: # same payload as title built_keyboard = [PostbackButton(element[0:20], element) for element in traverse(ast.literal_eval(keyboard))] return built_keyboard def create_chat_state(self, message, target_state, context): MessengerChatState.objects.create(chat=message.sender, state=target_state, ctx=context) def get_chat_id(self, message): return message.sender def send_message(self, chat_id, text, keyboard, reply_message=None, user=None): texts = text.strip().split('\\n') msgs = [] for txt in texts: for chunk in textwrap.wrap(txt, 320): msgs.append(messages.Message(text=chunk)) if keyboard: if len(msgs[-1].text) <= 45: title = msgs.pop().text else: new_texts = textwrap.wrap(msgs[-1].text, 45) msgs[-1].text = " ".join(new_texts[:-1]) title = new_texts[-1] elements = [] for chunk_buttons, last in self.batch(keyboard[0:30], 3): elements.append(Element(title=title, buttons=chunk_buttons)) generic_template = GenericTemplate(elements) attachment = TemplateAttachment(generic_template) msgs.append(messages.Message(attachment=attachment)) for msg in msgs: try: logger.debug("Message to send:(%s)" % msg.to_dict()) recipient = messages.Recipient(recipient_id=chat_id) self._bot.send(messages.MessageRequest(recipient, msg)) logger.debug("Message sent OK:(%s)" % msg.to_dict()) except: exctype, value = sys.exc_info()[:2] logger.error("Error trying to send message:(%s): %s:%s" % (msg.to_dict(), exctype, value))