pyspa-bot開発報告2022


(UnsplashDesola Lanre-Ologunが撮影した写真)

この記事はpyspa アドベントカレンダー 2022の23日目です。昨日は@shinyorkeでした。

過去のpyspa-bot関連記事は以下のとおりです。

shiumachi.hatenablog.com

shiumachi.hatenablog.com

pyspa-botの概要

pyspa-botは、pyspaのSlackチャンネル内で稼働しているbotです。

初期バージョンが開発されてから10年以上の歴史が経っています。

2010年ごろにDjango Appとして動作するSkype Botとして初期バージョンが稼働しました。(当時のpyspaはSkypeでチャットしていました)。これを便宜上バージョン1とします。

2013年ごろにSlackに移行したタイミングでSkype BotがSlackにも対応するようになりましたが、開発者の@moriyoshitが個人でメンテナンスしてたこともあり、落ちたら誰も起動できなくなるといった保守上の問題がありました。

そこで2016年に、Django依存をなくし、rtmbotをベースにしたチャットボットシステムに移行しました。これを便宜上バージョン2とします。

github.com

pyspa-bot ver.2 の2021年時点での技術概要

  • python-rtmbotベースのbotサーバ
  • Python 3.8 (ver.2 移行時は3.6だったが一度アップグレードを実施)
  • DBはSQLiteを使用(これはver.1時代のものをそのまま流用)
  • Google Cloudで稼働 (初期の頃は無料のマイクロインスタンスを使っていたが今はn1-standard-1を使用)
  • 手動デプロイ。サービスはsystemdで管理

2022年の主な作業

GitLabからGitHubへの移行

GitLab無料版のプライベートリポジトリのユーザー数を5人までに制限したためリポジトリGitHubに移行しました。

node-gitlab-2-githubを使ってIssueなども全てきれいに移行しました。

github.com

SQLiteからCloud SQL(PostgreSQL)への移行

昨年の記事ではCDに持っていくことを目標としていましたが、一度に全てを行うのが難しかったため、DB移行のみ実施しました。

インスタンスの移動

過去に無料インスタンスを使っていた関係で北米リージョンでインスタンスを稼働していましたが、既に有料インスタンスを利用しているため北米リージョンを選び続ける理由はありませんでした。

現在は東アジアリージョンで稼働させています。

Python 3.10 への移行

特に問題なくアップグレードを完了しました。

古いslackclientからslack-sdkへの移行

2022年9月にSlack APIのrtm.startが廃止された影響を受けて、pyspa-botが稼働しなくなりました。

pyspa-botはrtmbotに依存している関係でslackclientというライブラリにも依存していましたが、既にどちらもメンテナンスされていません。

pypi.org

rtmbotは既にフォークしてメンテを続けていますが、slackclientはライブラリをそのまま使い続けていました。

この機会に新しいslack-sdkに移行しました。

github.com

新機能開発: 新KudosBot

pyspa++とbotに入力すると、`pyspa`のスコアがインクリメントされるというKudosという機能を持つbotを刷新しました。

これにより、以下の機能が追加されました。

(1) a+++のように記号を連続させた場合、連続した記号の数-1の数だけインクリメントあるいはデクリメントする

例えばpyspa++++++++++++++++++と連続してプラスを書くと、書いた分だけインクリメントできるようになりました。


(2) コードブロック(バックスラッシュ3つで囲まれた文字列)やコード(バックスラッシュ1つで囲まれた文字列)は無視する

コードを貼り付けるときのコードブロック内のインクリメントに反応するのが煩わしかったので反応しないようにしました。


(3) C++を無視する

C++のような頻繁に使われる用語を無視するようになりました。従来版ではこのおかげでCがやたらとインクリメントされていました。

課題とTODO

CD

昨年に続きCDが課題です。

残るタスクは下記のとおりです。

  • サービスのDocker化
  • Cloud Buildでビルドするように変更
  • Cloud Runから継続的にデプロイするよう変更
rtmbot依存の脱却

現在のpyspa-botはrtmbotをフォークして独自にメンテナンスを続けている状態ですが、あまり健全な状態ではありません。bolt-python等への移行をしていく予定です。

github.com

アノテーションの導入

pyspa-botPython 2.x時代に作られたレガシーシステムであるため型アノテーションが導入されていませんでした。

例えば以下のコードを見てください。

class Node(typing.NamedTuple):
    type: str
    value: typing.Union[str, float, int, typing.Sequence["Node"], "Node", None]
    pos: typing.Optional[int]
    image: str

if node[0] == "FUNCTION":
        if node[1][0][0] == "IDENTIFIER":
            name = node[1][0][1]

2行目と3行目の第2インデックスはNodeのリスト、それ以外は全てNodeになっています。

こんなコードが至る所にあります。

mypy 0.981から再帰型を検査できるようになったので上記のNodeを検査できるようになりました。

これで型アノテーションの付与を進められるようになります。

今はほぼ毎日型アノテーションをつけるという作業を進めています。

Slack依存の脱却

現在のpyspa-botでは、slackAPIを直接叩いているところがあちこちにあったり、rtmbotのプラグインのコードにロジックがかかれていたりなどして、Slack及びSlackライブラリに強く依存してしまっている状態です。

これらを完全に分離して、任意のサービスにpyspa-botを対応できるようにする予定です。

テストの整備

2016年の移行時はノーテストだったため、そのタイミングでテストは色々書きましたけど私の技術力が低かったこともあり、今見ると品質の悪いテストがたくさん入ってしまっています。

これらのテストを整備して、意味のあるテストを追加していく予定です。

パッケージ構造の改善

rtmbotをフォークしたこともあり、トップレベルパッケージが以下のように複数存在しており、保守が煩雑になっています。

  • rtmbot
    • rtmbotからフォークしたパッケージ
  • plugins
    • rtmbot用のプラグインを管理するパッケージだが、pyspa-bot独自のロジックが多く含まれてしまっている
  • pyspabot
    • pyspabot独自のコマンドなどが管理されている

これを以下のように整理する予定です。

  • pyspabot
    • platform: 各SNS・チャットプラットフォームごとのパッケージをここで管理
      • slack
        • rtmbot: 旧rtmbot
        • plugins: 旧plugins。ただしpyspa-bot独自のロジックは含めない
    • core: 旧pyspabot

よくある質問

いつ開発してますか?

仕事の息抜きとか寝る前のちょっとしたすきま時間に開発してます。

1日10~30分程度です。

一から作り直した方がよくないですか?

まとまった時間取れないのでアプリを壊さないよう慎重に開発しています。

息抜きの割にはかなり作り方が本格的じゃないですか?

息抜きだから他にしがらみなく自由に開発できます。

どれくらいコード書いてますか?

この3ヶ月で4043行(+2478、-1565)でした。

最後に

pyspa-botの開発には多くのメンバーが関わっています。現在の主なメンバーは以下のとおりです。

特に@aodagは日々のコードレビューをこなし続けてくれていて、大変感謝しています。ありがとう!


明日のアドベントカレンダー@torufurukawaです。