0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Qiitaのアドカレ管理を楽にするDiscord Botを作ってみたけど上手く運用できなかった話

Last updated at Posted at 2025-12-25

こんにちは、のびすけです。

管理しているアドベントカレンダーの動きを知りたい

カレンダーを投稿してくれた人がいたらとても嬉しいので、コミュニティのDiscordなどに流したいですよね。

CleanShot 2025-12-03 at 20.03.02.png

ただここは忘れがちだったり自分で情報を見にいくのも大変です。

また、アドベントカレンダー管理者は自分が管理しているヒヤヒヤしてると思います。

ちょうどIoTLTのカレンダーでも5日目が抜けてしまっていて(誰か登録してくれていたけど気づいたらキャンセルになっていた)セルフチェックで気付けました。

CleanShot 2025-12-03 at 19.51.49.png

キャンセル自体はよくあるので問題ないのですが早く気づけると嬉しい

そんなことを11月ほどに思って作って試してみた話です。12/25の後日談も。

Difyのスケジュールトリガーで動きの差分を検知

最近使えるようになった定期実行トリガーで QiitaのサイトからHTMLを取得して差分を検知しつつDiscordに通知する仕組み を作ってみました。

※過度なことはしてないですが、スクレイピングなのでQiitaから怒られたらやめます。

大まかな流れです。

1. アドベントカレンダーの情報を取得(A)
2. カレンダーの情報を保存しておく
3. 保存してあった前回実行時のカレンダー情報(B)と今回取得したカレンダー情報(A)を比較する
4. 比較して差分があったら差分の情報を元にDiscordに通知

こんな流れで作ってみました。

大枠はこんな流れです。

CleanShot 2025-12-03 at 20.20.55.png

作り方

細かくは解説しないのですが、要点を紹介します。

最初はトリガーで開始する

ワークフローじゃないとトリガーは選べない ので注意です。

CleanShot 2025-12-03 at 11.04.24.png

トリガーを選択

CleanShot 2025-12-03 at 11.04.28.png

スケジュールトリガーを選択します。

CleanShot 2025-12-03 at 11.04.36.png

HTMLの要素特定

アドベントカレンダーのページのカレンダー本体部分のHTMLを取得します。

CleanShot 2025-12-03 at 20.23.53.png

HTTPリクエストノードでカレンダーのURLを指定しますが、その後にコード実行ノードでコンテンツの中身の抽出をしています。

CleanShot 2025-12-03 at 20.25.59.png

正規表現で<table aria-label="Calendar"のあたりの要素を抜き出すと良さそうだなと思ったのでここを抽出しています。

CleanShot 2025-12-03 at 11.30.44.png

コードは以下のように書いていて後で扱いやすいようにJSON文字列にしています。

function main({ html_content }) {
    const extractedItems = [];
    //ステップ1:  <table aria-label="Calendar">...の部分抽出
    const tableRegex = /<table aria-label="Calendar"[^>]*>[\s\S]*?<\/table>/g;
    const tableMatches = html_content.match(tableRegex) || [];
    
    const itemRegex = /href="\/([^"]+)"\s+class="style-zfknvc"[\s\S]*?<div\s+class="style-mpez5z">\s*(?:<a\s+href="([^"]+)"[^>]*>)?\s*([^<]+)/g;

    //ステップ2: 取得したテーブルHTMLごとにループ処理
    tableMatches.forEach(tableHtml => {
        let match;
        
        // 同じ正規表現オブジェクトを使い回すため、インデックスをリセット
        itemRegex.lastIndex = 0;

        // テーブル内のすべての要素に対してマッチングを行う
        while ((match = itemRegex.exec(tableHtml)) !== null) {
            extractedItems.push({
                author: match[1],           // ユーザー名
                url: match[2] || null,      // URL (なければnull)
                title: match[3].trim()      // タイトル (前後の空白削除)
            });
        }
    });

    //最後はJSON文字列へ
    return {
        result: JSON.stringify(extractedItems)
    };
}

情報の保存 KVdb

KVdb( https://kvdb.io )というサービスがあり、簡単に文字列を書き込み&読み込みが出来るAPIサービスです。

中身の信頼などは置いておいて一時保存に便利でした。

このような形で前回の実行内容を保存しておき、今回の実行内容と比較することで差分を検出させてみました。

- 初回
    - HTTPリクエスト
    - コード実行
    - KVDBに保存
- 2回目
    - 最新を実行
        - HTTPリクエスト
        - コード実行
        - KVDBに保存
    - KVDBから初回のデータを取得
    - 初回と2回目の実行を比較(LLM)
- 3回目
    - (あとは繰り返し)

CleanShot 2025-12-25 at 18.03.21.png

DSLファイル

URLなどのhttps://hogehoge.comと適当なものにしてますが多分動く気がします。

https://gist.githubusercontent.com/n0bisuke/479f3dcbb64bc1d2d1f1a9e6065e01f5/raw/3f1fc60353a69ed91923382a4d5291ad3b0e9a6d/dify-qiita-cal.yml

使える方はインポートしてお試しください。

全体はこんな感じ。

CleanShot 2025-12-25 at 18.01.05.png

終わりに 12/25まで運用してみて

(上の章までは11月くらいに書いていて、ここから12/25の最終日に書いてます。)

結果良い感じに通知してくれてよかった!ってところもありますが概ねちゃんと運用は出来ませんでした。

キャンセルが見えるのはいいことなのか...?

xxxさん書くっていってたのになー

CleanShot 2025-12-25 at 18.07.47.png

といったネガティブな感情が多少生まれちゃいます。

アドカレはコミュニティ文化なので仕事でもないのでカジュアルに参加やキャンセルしちゃって良いよねって僕は思ってたりしますが、これが見えちゃうと考えすぎちゃうので良くないなぁーとも思ったりしました。

結果途中からあんまりみなくなるという結果でした... 苦笑

あと多分プロンプトとKVDBからの情報取得タ&更新イミングなど何個かありそうですが差分だけ知りたいのに色々URL送ってくるタイミングもあり、精度は現状いまいちな状態です。

CleanShot 2025-12-25 at 18.07.39.png

結局コミュニティー側には使わず

そんな感じもあり、自分用の通知限定で利用しました。

キャンセルがみんなに見えちゃうのは良くない気もしますよね。

本当はコミュニティのDiscordへいい感じに通知したかったんですけど、キャンセルの部分などの実装修正をする時間を取らずにそのまま行ってしまいました。

12月に入るとあっというまだったので11月までに仕上げておきたかったですね。

これは来年へ持ち越しです。(覚えてたら)

その他 実装学びなど

  • 無料なのはありがたい

Discordは通知したりとAPIは無料で使えますし、LLMはGroq Cloudを使いましたがこれくらいの範囲で1日1回回すくらいだと無料で使えてお手軽です。

  • KVdb

KVdbというサービスをしれたのは今回試して調べてみて良かった点です。これはこれで面白いのでSDK作ってみつつ記事にもしてみました。

  • 他への応用

もう12/25になったので一旦このフローも止めようかと思いますが、似た仕組みは使えそうですね。

セルフ通知などの参考になれば幸いです。

アドカレお疲れ様でした!

そんなこんなでアドカレ今年は完走賞いけそうだったので狙って記事書いてましたがなんとか25記事 いけそうです。 いけました〜

CleanShot 2025-12-25 at 22.18.16.png

管理しているIoTLTカレンダーもおかげさまで盛り上がりました!

12/27にイベントで記事振り返りもするので良かったら配信みにきてください。

今年もお疲れ様でした〜 メリークリスマス!&良いお年を!

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?