#前書き
PythonのslackbotライブラリでSlackボットとIFTTTを連携したい!!
と思ったがslackbotライブラリでうまく動かなかったのでメモ書き。
「google home mini → ifttt→ slack → 家のslackbot」連携イメージ
#結論:修正方法
まずはオリジナルソース「https://github.com/lins05/slackbot」
pipでインストールします。
そこんとこは以下の方が詳しいのおまかせ。
PythonのslackbotライブラリでSlackボットを作る
んで、インストールソースの以下を直接変更
###修正前
~抜粋~
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))
~抜粋終わり~
###修正後
~抜粋~
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経由で同じメッセージを
送ってもうまく動かないって現象になるようです。
#理想
簡単に実装するために上記で作ってしまいましたが、理想的には以下の処理を
直すほうがよさそうです。めんどくさくてやりませんでしたが。
~抜粋~
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ボットを作る