LoginSignup
1
1

More than 5 years have passed since last update.

Errbotのpluginを作ってみる

Posted at

Hubotのhubot-scriptに当たる仕組みを、Errbotではpluginといいます。

こちらにはサードパーティのPluginが並んでいますが、
せっかくなので作ってみようと思います。

pluginの基本部分

pluginは2個のファイルが必要です。

  • plugファイル
  • pythonモジュール

plugファイルはpluginのメタデータファイルです。
Pythonのバージョン指定、helpコマンド実行時の説明文などが記述されています。

pythonモジュールはpluginの実体です。
ロジックをこちらに書きます。

返事をするだけのplugin

hello_plugin.png

hello.plug
[Core]
Name = Hello
Module = hello

[Python]
Version = 2+

[Documentation]
Description = Hello plugin
hello.py
# -*- coding:utf8 -*-
from __future__ import division, print_function, absolute_import
from errbot import BotPlugin, botcmd


class Hello(BotPlugin):
    @botcmd
    def hello(self, msg, args):
        return 'Hello world!'

中身をもうちょっと詳しく

pluginの実体クラスはBotPluginを継承します。初期化時にもろもろの処理をしてくれるのですが、今回は省略します。
botcmdデコレータでデコレーションしたメソッドの名前がそのままコマンドになります。

  • ここでは!helloがそのままコマンドになります。

botコマンドになるメソッドには2個の引数が必要です。

  • msg
    • コマンドの全文
  • args
    • コマンドに引数がつけられるので、その引数部分
    • 特にlistなどにパースされてはいない

botcmdにデコレートしたメソッドが文字列を返すと、それをそのまましゃべってくれます。
楽でいいですね。

天気を教えてくれるplugin

bl549uY4BE.gif

weather.py
# -*- coding:utf8 -*-
from __future__ import division, print_function, absolute_import
from errbot import BotPlugin, botcmd
import requests
from xml.etree import ElementTree


class Weather(BotPlugin):
    WEATHER_HACK_AREA_URL = \
        'http://weather.livedoor.com/forecast/rss/primary_area.xml'
    WEATHER_HACK_API_URL = \
        'http://weather.livedoor.com/forecast/webservice/json/v1?'

    @botcmd
    def weather(self, msg, args):
        # 引数に指定された都市を探す
        city_id = self.find_city_id(args)
        if city_id is None:
            return u'{} は確認不可能な地域です'.format(args)
        resp = requests.get(
            self.WEATHER_HACK_API_URL,
            {'city': city_id}
        )
        wt_json = resp.json()
        return u'{}: {}は{}'.format(
            wt_json['title'],
            wt_json['forecasts'][0]['dateLabel'],
            wt_json['forecasts'][0]['telop']
        )

    def find_city_id(self, city_name):
        """LivedoorのAPIで天気を返す都市を探す
        """
        resp = requests.get(self.WEATHER_HACK_AREA_URL)
        tree = ElementTree.fromstring(resp.content)
        cities = {
            elm.attrib['title']: elm.attrib['id']
            for elm in tree.findall('.//city')
        }
        return cities.get(city_name, None)

この時点では雑にargsをそのまま都市名とみなして天気を返すようにしてますが、
「複数都市をスペース区切りで投げてきたら分割してそれぞれの都市の天気をまとめて返す」
といったことも可能です。
ArgumentParserを利用すれば引数の取り扱いは柔軟にできるので、いろいろな可能性がありそうですね。

1
1
0

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
1
1