LoginSignup
6

More than 5 years have passed since last update.

PythonのslackbotライブラリでSlackボットとIFTTTを連携

Last updated at Posted at 2018-01-21

前書き

PythonのslackbotライブラリでSlackボットとIFTTTを連携したい!!
と思ったがslackbotライブラリでうまく動かなかったのでメモ書き。

「google home mini → ifttt→ slack → 家のslackbot」連携イメージ

結論:修正方法

まずはオリジナルソース「https://github.com/lins05/slackbot」
pipでインストールします。

そこんとこは以下の方が詳しいのおまかせ。
PythonのslackbotライブラリでSlackボットを作る

んで、インストールソースの以下を直接変更

修正前

dispatcher.py
抜粋
    def _on_new_message(self, msg):
        # ignore edits
        subtype = msg.get('subtype', '')
        if subtype == u'message_changed':
            return

        botname = self._get_bot_name()
        try:
            msguser = self._client.users.get(msg['user'])
            username = msguser['name']
        except (KeyError, TypeError):
            if 'username' in msg:
                username = msg['username']
            else:
                return

        if username == botname or username == u'slackbot':
            return

        msg_respond_to = self.filter_text(msg)
        if msg_respond_to:
            self._pool.add_task(('respond_to', msg_respond_to))
        else:
            self._pool.add_task(('listen_to', msg))
抜粋終わり

修正後

dispatcher.py
抜粋
    def _on_new_message(self, msg):
        # ignore edits
        subtype = msg.get('subtype', '')
        if subtype == u'message_changed':
            return

        botname = self._get_bot_name()
        try:
            msguser = self._client.users.get(msg['user'])
            username = msguser['name']
        except (KeyError, TypeError):
            if 'username' in msg:
                username = msg['username']
            else:
                return

        if username == botname or username == u'slackbot':
            return

        msg_respond_to = self.filter_text(msg)
        if msg_respond_to:
            if msg_respond_to.get('text', None) == None: # ←追加行
                msg_respond_to['text'] = msg_respond_to.get('attachments')[0].get('pretext') # ←追加行
            self._pool.add_task(('respond_to', msg_respond_to))
        else:
            self._pool.add_task(('listen_to', msg))
抜粋終わり

理屈

slackbotライブラリーが期待するレスポンス(json形式)と、実際にIFTTT経由でくる
メッセージの形式が違うのが原因のようです。

JSON形式できたメッセージ形式中から、textノードを取り出して処理しようとしますが、
ITTF経由で来たメッセージにはtextノードが存在せず、attachmentsノード中の、
pretextノードってのがメッセージになるようです。

だから、通常のメッセージ入力では動くのに、ITTF経由で同じメッセージを
送ってもうまく動かないって現象になるようです。

理想

簡単に実装するために上記で作ってしまいましたが、理想的には以下の処理を
直すほうがよさそうです。めんどくさくてやりませんでしたが。

dispatcher.py
抜粋
    def _dispatch_msg_handler(self, category, msg):
        responded = False
        for func, args in self._plugins.get_plugins(category, msg.get('text', None)):
            if func:
                responded = True
                try:
                    func(Message(self._client, msg), *args)
                except:
                    logger.exception(
                        'failed to handle message %s with plugin "%s"',
                        msg['text'], func.__name__)
                    reply = u'[{}] I had a problem handling "{}"\n'.format(
                        func.__name__, msg['text'])
                    tb = u'```\n{}\n```'.format(traceback.format_exc())
                    if self._errors_to:
                        self._client.rtm_send_message(msg['channel'], reply)
                        self._client.rtm_send_message(self._errors_to,
                                                      '{}\n{}'.format(reply,
                                                                      tb))
                    else:
                        self._client.rtm_send_message(msg['channel'],
                                                      '{}\n{}'.format(reply,
                                                                      tb))
抜粋終わり

「for func, args in self._plugins.get_plugins(category, msg.get('text', None)):」を、
msgから柔軟にメッセージ文字列取り出すほうが良い気がします。

参考にさせていただいたページ

PythonのslackbotライブラリでSlackボットを作る

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6