Chienomi

Discord Webhook + curlでスマホに通知してみる(LINE Notifyもあるよ)

webhook

  • TOP
  • Old Archives
  • Discord Webhook + curlでスマホに通知してみる(LINE Notifyもあるよ)

IFTTTに近いかもしれないが、特定の条件で発生するアクションを作ったのだが、Linuxコンピュータで処理しただけでは外出中に気づくことができない。 そこでスマホに通知する方法が欲しくて考えた結果、もっとも適切そうなのは、DiscordのWebhookを使うというものだった。

通知までの考え方

一般には次のような流れになる

  1. 検証すべきデータを取得する
  2. データを解析する
  3. 条件を満たす場合にhookを実行する

データ取得、解析は、例えばウェブスクレイピング。次の例では特定のページが最終取得時と変更されているかをチェックする

getfunc() {
  curl 'http://journal.reasonset.net/' > ~/tmp/new.page.html
}

checkfunc() {
  if cmp ~/tmp/new.page.html ~/tmp/old.page.html
  then
    return 0
  else
    rm ~/tmp/old.page.html
    mv ~/tmp/new.page.html ~/tmp/old.page.html
    return 1
  fi
}

ここでhookさせるべきときに1を返すのは、whileで処理しやすいようにするためである。

データの解析までは通常ひとつづりで行われるため、まとめてしまって構わない。 Ruby + Nokogiri + Capybara + Poltergeistという構成でスクレイピングする場合もあるだろう。

また、twによってツイッターの投稿をチェックしたり、IMAPメールボックスをチェックしたり、あるいはfetchmailで受信したメールをフィルタするという方法もあるでしょう。

hookについては、次のようなものが考えられます。 まず、通知を表示する。

notify_hook() {
  notify-send "$1"
}

音を鳴らす。SOXを使うか、mpvを使うか、aplayを使うか…など選択肢は多いのですが、ここではSOXを使うことにしましょう。 音が鳴り終わるまで止める必要はないので、バックグラウンドで

notify_hook() {
  play "$1" &
}

ダイアログを表示する。Zenityの場合、制御端末が存在していると、制御端末ウィンドウがアクティブにならないとダイアログが表示されないため、ここではYadを使います。

notify_hook() {
  yad "$1"
}

コマンドを実行する。hookが起動された時点で実行したい内容があれば書いておきます。

notify_hook() {
  tw --yes "HOOKされたよ!"
}

スマートフォンに対する通知

Linuxコンピュータの前にいればユーティリティを自在に書くことのできる我々は全能感にすら浸ることができる。 だが、残念ながらLinuxコンピュータで優れたスクリプトを書いていたとしても、それはLinuxコンピュータに触れていなければ十分に発揮することができない。

そんな外の世界をつなぐのがスマートフォンの存在だ。 スマートフォンが注意をひきつけてくれれば何かしらの対応が可能だろう。

最も簡単な方法はメールではないだろうか。昔からよく使われていた方法だ。 現在もその方法は有効であり、例えばMailxを使ってメールを送ることもできる。 次の例ではMailxは設定済みであるか、もしくはlocalhsotに有効なMTAがあるものとする。

notify_hook() {
  echo "Hookされました" | mail -r "notification@localhost.localdomain" -s "Hooked notification" mms@example.com
}

だが、今時MMSなんか使っていないというHackerも多いのではないだろうか。 GMail宛に送るという方法もあるが、GMailで大量のメールをもらっているからあまり参考にはならないという人も多いはず。

ではインスタントメッセンジャーについて検討してみよう。

Facebook Messangerはfb-messanger-cliやMesserなどがあるが、自分自身に送るためのハードルが高すぎるため現実的ではないだろう。

Google Hangoutsはhangupsによってコマンドラインからの送信が可能だ。 ただし、Pythonスクリプトで書く必要があり、それなりに複雑だ。事前準備もある程度必要で、bot用アカウントを作成しておかなければ自分自身には送れないという意味でハードルは高い。

SkypeもSkype4pyによってコマンドラインから利用が可能だが、問題はHangouts同様である。 最近はSkypeアカウントの認証は厳しいし、サードパーティクライアントに対して非常に厳しい対応をとっていることを考えるとより難しいだろう。

以外にもLINEは現実的な処理が可能だ。 LINE Notifyのマイページから登録を行い、トークンを取得する。 そして次のようにして送信するのだ([token]と[message]は適切に置き換える)

curl -X POST -H 'Authorization: Bearer [token]' -F 'message=[message]' https://notify-api.line.me/api/notify

有力な選択肢のひとつである。

SlackはBOTを作成することができ、簡単に通知することができるが、Slackの通知は安定しないため、すぐに気づきたい場合に見逃すかもしれない。

Discordを使う

LINEで通知できるのも素晴らしいが、Discordならもっと楽しい。

Discordはマルチプラットフォームであり、PC, Android, iOSで扱うことができる。 加えて、それぞれの端末にアカウントを分けることで電話番号のない端末を探したり、一斉に通知したりすることが可能だ。

しかも、LINEでは通知はすべてがまとめられてしまうが、これなら分類することもできる。 LINEにおいても自分のみが所属するグループを作ることで共有が可能だが、Discordのほうが共有も容易だ。 URIなどを端末間で共有したい場合の利便性も高い。

まずは準備をしよう。 各端末にアカウントを用意し(PCと共有のアカウントがあっても構わない)、自分(たち)用のサーバーを用意する。 そして各端末のアカウントを招待し、通知/共有に含めたい全アカウントを登録する。

これでgeneralを介してアクセス可能になったが、全てがまとめられてしまう状況には変わりない。 そこで、内容を適切に分割するようにチャンネルを作成しよう。

チャンネルをわけることで、そのチャンネルに対する内容を通知しなくていい端末は当該チャンネルの通知を切っておく、ということも可能になるる これにより内容によって端末に通知する/しないを選択可能だ。

ではいよいよWebhookを作成する。 チャンネルの設定に移動し、"Webhooks"を選択する。ここでWebhookを作成するとWebhookの名前とアバターを設定し、通知するチャンネルを選択、そしてURLが発行されるはずだ。 このwebhook URLに対してJSONをPOSTすることでbotとして発言させることができる。

Webhookに対して送れるJSONオブジェクトは次の通りだ。

Field Type Description Required
content string 2000文字までのメッセージ 1つのcontent/file/embeds
username string Webhookのusernameを上書きする false
avatar_url string デフォルトのアバターを上書きするURL false
tts bool trueならTTSメッセージとする false
file file contents 送信するファイル one of content, file, embeds
embeds array of embed objects 埋め込まれたリッチコンテンツ one of content, file, embeds

チャンネルは設定を上書きできないが、発言者の名前やアバターは上書きすることができる。 そのため、単一のWebhookでも種類の異なる通知をすることが可能だ。 (アバター変更するなら複数のWebhookを使ったほうが効率は良いだろうが)

curlを使って次のようにJSONを送信することができる。

curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"username":"J.R.H","content":"ホックされたよ!!!"}' 'https://discordapp.com/api/webhooks/koko-ni-hook-no-uri'

JSONがダブルクォートを必要とするため、変数展開したい場合は少し大変かもしれない。

ひとこと

LINEもDiscordも、ユーザーごと/チャンネルごと個別の通知音設定がほしい