LoginSignup
0
0

More than 1 year has passed since last update.

シェルスクリプトでWEBページの更新を検知してDiscordに通知するやつ

Posted at

ソースコード

#!/bin/bash

LAST_MODIFIED="Thu, 17 Oct 2019 07:18:26 GMT"
URL="https://example.com"
DISCORD_WEBHOOK_ADDRESS=""

LM=$( \
    curl -I -s ${URL} \
    | grep --ignore-case "Last-Modified" \
    | sed -e "s/Last-Modified: //i" -e "s/\r//" \
)

if [ ! "$LAST_MODIFIED" = "$LM" ]; then
    curl -X POST -H "Content-Type: application/json" \
        -d '{"content": "Last-Modified is changed at <t:'$(date -d "$LM" +%s)'>. ('"$LM"')"}' \
        ${DISCORD_WEBHOOK_ADDRESS}
fi

実行結果

image.png

解説

変数宣言

LAST_MODIFIED="Thu, 17 Oct 2019 07:18:26 GMT"
URL="https://example.com"
DISCORD_WEBHOOK_ADDRESS=""

LAST_MODIFIED 手動で最終更新日を入れておく
URL 更新をチェックしたいサイトのアドレス
DISCORD_WEBHOOK_ADDRESS WEBページに更新があったときに通知するwebhookのアドレス

Last-Modifiedの取得

LM=$( \
	curl -I --silent ${URL} \
	| grep --ignore-case "Last-Modified" \
	| sed -e "s/Last-Modified: //i" -e "s/\r//" \
)

curl -I -s ${URL} URLのヘッダのみを取得する.サイレントモードで実行する
grep --ignore-case "Last-Modified" 大文字小文字を無視して “Last-Modified” の文字列を探す.サイトによって “Last-Modified” だったり “last-modified”だったりしたので
sed -e "s/Last-Modified: //i" -e "s/\r//" ”Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT”という文字列を受け取り日時のみを返す.ついでにCR文字を消す

if

取得したLast-Modifiedの値が手動で入力した値と同じか単純に比較しているだけ.

webhookのポスト

curl -X POST -H "Content-Type: application/json" \
    -d '{"content": "Last-Modified is changed at <t:'$(date -d "$LM" +%s)'>. ('"$LM"')"}' \
    ${DISCORD_WEBHOOK_ADDRESS}

<t:'$(date -d "$LM" +%s)'> Last-ModifiedはGMTらしいのでローカル時間に変換してあげる.

グリニッジ標準時。 HTTP における時刻は常にグリニッジ標準時で表され、ローカル時刻になることはありません。

Last-Modified - HTTP | MDN
discordでは <t:TIMESTAMP> の形式でUnix Timestampを送ると良い感じにユーザのロケールとタイムゾーンにしてくれる.
Discord Developer Portal - API Docs for Bots and Developers
date コマンドに-dオプションで変換したい時間を入れて+%sでUnix Timestamp で出力する.
"$LM" Last-Modifiedの値にスペースが入っているのでスペース込みで1つの文字列扱いにするためにダブルクォーテーションで囲んでおく.

curlの-dオプションの引数をjson形式にする関係でシングルクォーテーションで囲んでいるが,これだとコマンド置換や変数展開ができない.そこで変数展開が必要な前後で文字列を区切っている(Python だと 'str1' + 'str2' と書くような感じ.).Bashだと+が不要なのでそのままつなげればよい('str1''str2').このときに見やすくするために '$ の間にスペースを入れると当然ながら別の引数として認識されてしまう.

実行方法

crontabやsystemd timerを利用して何分かおきに走らせたりするといいのではないでしょうか.

# crontab -e
*/5 * * * * PATH_TO_SCRIPT

おわりに

いかがでしたか.RSSなどが無いサイトで更新をチェックしたいときに使えるTipsでした.
変数を配列で持てば複数サイトにも対応できそうですね.
Last-Modified をヘッダに入れてないサイトに対しては無力ですが(笑).そんな時はETagとか見たら良いんじゃないでしょうか.
しらんけど

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