(UnsplashのDesola Lanre-Ologunが撮影した写真)
この記事はpyspa アドベントカレンダー 2022の23日目です。昨日は@shinyorkeでした。
過去のpyspa-bot関連記事は以下のとおりです。
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とします。
pyspa-bot ver.2 の2021年時点での技術概要
2022年の主な作業
GitLabからGitHubへの移行
GitLabが無料版のプライベートリポジトリのユーザー数を5人までに制限したため、リポジトリをGitHubに移行しました。
node-gitlab-2-githubを使ってIssueなども全てきれいに移行しました。
SQLiteからCloud SQL(PostgreSQL)への移行
昨年の記事ではCDに持っていくことを目標としていましたが、一度に全てを行うのが難しかったため、DB移行のみ実施しました。
インスタンスの移動
過去に無料インスタンスを使っていた関係で北米リージョンでインスタンスを稼働していましたが、既に有料インスタンスを利用しているため北米リージョンを選び続ける理由はありませんでした。
現在は東アジアリージョンで稼働させています。
Python 3.10 への移行
特に問題なくアップグレードを完了しました。
古いslackclientからslack-sdkへの移行
2022年9月にSlack APIのrtm.startが廃止された影響を受けて、pyspa-botが稼働しなくなりました。
pyspa-botはrtmbotに依存している関係でslackclientというライブラリにも依存していましたが、既にどちらもメンテナンスされていません。
rtmbotは既にフォークしてメンテを続けていますが、slackclientはライブラリをそのまま使い続けていました。
この機会に新しいslack-sdkに移行しました。
新機能開発: 新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等への移行をしていく予定です。
型アノテーションの導入
pyspa-botはPython 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
- pyspabot
- pyspabot独自のコマンドなどが管理されている
これを以下のように整理する予定です。
よくある質問
いつ開発してますか?
仕事の息抜きとか寝る前のちょっとしたすきま時間に開発してます。
1日10~30分程度です。
一から作り直した方がよくないですか?
まとまった時間取れないのでアプリを壊さないよう慎重に開発しています。
息抜きの割にはかなり作り方が本格的じゃないですか?
息抜きだから他にしがらみなく自由に開発できます。
どれくらいコード書いてますか?
この3ヶ月で4043行(+2478、-1565)でした。
最後に
pyspa-botの開発には多くのメンバーが関わっています。現在の主なメンバーは以下のとおりです。
特に@aodagは日々のコードレビューをこなし続けてくれていて、大変感謝しています。ありがとう!
明日のアドベントカレンダーは@torufurukawaです。