Slackで$…$や$$…$$を数式にするSlash Command

どうもぴざきゃっとです。

今回は,以下の記事で紹介したクラスSlackの機能の1つである数式入力の話をします。

pizzacat83.hatenablog.com

botソースコードはこちら

github.com

概要

/formulaに続いて$…$や$$…$$で数式を囲んだメッセージを入力すると、その部分が数式画像で置き換えられたメッセージが届きます。

f:id:pizzacat83:20190306162603p:plain:w500

以前は$$で囲まずに数式だけを書く、という仕様だったので、一応それにも対応しています。

f:id:pizzacat83:20190306162148p:plain:w300

数式をSlackで書けるようにするbotは既に存在していて,実際参考にしているんですが,このように$...$や$$...$$を含む文章に対応しているものはないんじゃないですかね。

実装

入力テキスト→数式画像入りメッセージ

このbotはGASで動かす関係でGAS特有の関数があったりしてNode.js等に転用しにくいものが多いですが、この部分に関してはNode.jsでも動くと思います。ただしTypeScriptなので適宜コンパイルしてください。

流れとしては、

  1. 正規表現でメッセージを数式部分を取得
  2. 各数式とそれに先行するテキストをattachment化

という感じです。

正規表現/([^]*?)((\$\$?)[^]+?\3)/gで,これを用いるとabc$def$ghi$$jkl$$mnoからabc$def$ghi$$jkl$$を抽出できます。

各マッチに対して,数式画像のattachmentを生成します。プレーンテキストから数式画像を生成するのにGoogle Charts APIを使います。リンク先見るとわかるんですがこのAPIはdeprecatedで,いつ使えなくなるかわからないんですが,代案が見つからなかったので当面はこれを使います。クエリパラメータにencodeURIComponentした文字列を書いてあげるとそれが画像へのURLになります。

このURLをattachmentのimage_urlに指定するだけで,Slackに画像付きメッセージを投稿することができます。なので,URLから画像をfetchするような処理は不要です。

また,attachmentのpretextには数式の前の文字列(abc$def$abcの部分)を指定します。

全てのマッチを処理した後はabc$def$ghi$$jkl$$mnomnoが残るので,mnoをpretextとしimage_urlを持たないattachmentを最後に追加します。なお最後のattachmentはスマホから見るとtextやimage_urlがないことによる謎の点f:id:pizzacat83:20190306152507p:plainが出るので,colorを#ffffffにすると見栄えが良いです。

数式画像入りメッセージ→レスポンスJSON

この部分はGAS特有です。

リクエストはPOSTでやってくるので,応答するためのdoPost(e)という関数を作ります。やってくるリクエストは/formulaだけではなく、他のSlash CommandsやEvent APIなども来るので,こんな感じで処理しています。

どのコマンドのリクエストなのかがcommandというパラメータに入っているので,コマンドの文字列に対応する関数をslackCommandsというオブジェクトに格納しておき,slackCommands['command']みたいな感じで呼び出すようにしています。関数の実行結果を受け取ったら,JSON文字列に変換してレスポンスを返します。

ちなみにGASWebEventSlackCommandParamsというinterfaceを用意しているので,コードを書くときに補完が効いて快適です。

使い心地

理系クラスなので当然数式を書きたいわけですが,TeXに慣れていなくてよくミスった数式が表示されてしまい,なんども投稿し直すことが多いです。プレビュー機能があると良さそうですね。ephemeralレスポンスとボタンで作れそうです。