見出し画像

GASでRSSフィードを取得してDiscordに投稿する

DiscordにはMonitoRSSというBotがあるが、無料では最大で5フィードまでしか購読できないので、Google Apps Scriptを使って自作してみた。
※SlackにもRSSというAppがあり、こちらは制限なし

Webhook

投稿したいチャンネルの設定からIntegrations > Create Webhookを選択してWebhook URLを生成してコピーする。
※Botの名前やアイコン画像を適宜変更する

スプレッドシートを用意

まず購読したいフィードや取得した記事を管理するスプレッドシートを用意して、以下のようにシート名を変更して、購読したいフィードを記載する。

feedsシート

購読するRSSフィードを定義するシート。任意のフィード名(投稿時にハイライト)とRSSリンクを記載する。

  • A列:RSSフィード名

  • B列:RSSリンク

articlesシート

このシートは、定期実行でそれぞれのフィードから記事を取得して、自動的に新規記事の行が挿入される。

  • A列:RSSフィード名

  • B列:記事タイトル

  • C列:記事リンク

  • D列:記事の掲載日時(yyyy-MM-dd'T'HH:mm:ssXXX)

スクリプト

スプレッドシートの拡張機能でApps Scriptを編集する。

フィード定義を取得する

/**
 * フィード定義を取得
 */
function getFeeds() {
  // feedsシートのA1:B最終行を取得する
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('feeds');
  const lastRow = sheet.getDataRange().getLastRow();
  const values = sheet.getRange(1,1,lastRow,2).getValues();

  const feeds = [];
  values.forEach((value) => {
    const feed = {};
    feed["name"] = value[0];
    feed["link"] = value[1];

    feeds.push(feed);
  });

  return feeds
}

RSSフィードから記事を取得する

/**
 * RSSフィードから記事を取得する
 */
function getArticles() {
  // フィード定義を取得
  const feeds = getFeeds();

  for (const feed of feeds) {
    // RSSの読み込み
    let xml = UrlFetchApp.fetch(feed.link).getContentText();
    let document = XmlService.parse(xml);
    let items = document.getRootElement().getChild('channel').getChildren('item');

    // スプレッドシートからデータを取得
    let articlesSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('articles');
    let lastRow = articlesSheet.getDataRange().getLastRow();
    let urls = articlesSheet.getRange(1, 3, lastRow).getValues();

    // 新しい記事かどうかを古いアイテム(記事)から比較するため
    items.reverse();

    // RSSから取得したデータと比較と保存
    for (var item of items) {
      let title = item.getChild('title').getText();
      let link = item.getChild('link').getValue();
      let pubDate = Utilities.formatDate(new Date(item.getChild('pubDate').getValue()), "JST", "yyyy-MM-dd'T'HH:mm:ssXXX");

      // URLが一致しないときは新しいデータ
      if (urls.some(url => url[0] === link)) {
        continue;
      }

      // スプレッドシートへの保存
      articlesSheet.appendRow([feed.name, title, link, pubDate]);

      // チャンネルに投稿
      postToChannel(feed.name, title, link);

      console.log(feed.name + ': ' + title);
    }
  }
}

チャンネルに投稿

/**
 * チャンネルに通知を投稿する
 * @param {string} name フィード名
 * @param {string} title 記事タイトル
 * @param {string} link 記事リンク
 */
function postToChannel(name, title, link) {
  const webhookURL = "<https://discord.com/api/webhooks/XXXX>";

  const message = {
    "content": '`' + name + '`\\n' + '**' + title + '**' + '\\n' + link
  }

  const param = {
    "method": "POST",
    "headers": { 'Content-type': "application/json" },
    "payload": JSON.stringify(message)
  }

  UrlFetchApp.fetch(webhookURL, param);
}

※Slackに投稿する場合は、message.contentをmessage.textに変更すればよい(こちらを参照)。

定期実行

最後に任意のトリガーを設定して、実行する関数にgetArticlesを設定すれば、定期的に自動でRSSフィードから記事を取得して、新規記事があればチャンネルに投稿される。

参考


この記事が気に入ったらサポートをしてみませんか?