75
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【GAS】SlackのチャンネルからQiitaの記事を取得して自動でストックする

Last updated at Posted at 2024-06-06

結論

以下ソースコードをGASに登録し、Slack APIとQiita APIのトークンとその他を環境変数に登録するだけ。

// 実行関数
function myFunction() {
  const messages = getSlackMessages()
  putStock(messages)
}
// 定期的にSlackからメッセージを取得するためのトリガーを設定
function setTrigger() {
  ScriptApp.newTrigger("myFunction").everyDays(1).atHour(20).create()
}

// Slack APIのトークン
const SLACK_TOKEN = getVal("SLACK_TOKEN")
// SlackチャンネルID
const SLACK_QIITA_CHANNEL_ID = getVal("SLACK_QIITA_CHANNEL_ID")
const SLACK_BOT_CHANNEL_ID = getVal("SLACK_BOT_CHANNEL_ID")
// Slack APIのメッセージ取得用エンドポイント
const SLACK_GET_MESSAGES = "https://slack.com/api/conversations.history"
// Slack APIのメッセージ送信用エンドポイント
const SLACK_POST_MESSAGES = "https://slack.com/api/chat.postMessage"
// Qiita APIのトークン
const QIITA_TOKEN = getVal("QIITA_TOKEN")
// Qiitaのユーザー名
const QIITA_USER_NAME = getVal("QIITA_USER_NAME")
// Qiita.comのリンクの正規表現
const QIITA_LINK_REGEX = /https?:\/\/qiita\.com\/[\w-._~:/?#[\]@!$&'()*+,;=]+\/items\/[\w-._~:/?#[\]@!$&'()*+,;=]+/g
// QiitaのリンクからuserNameとitemIdを抽出する正規表現
const QIITA_EXTRACTION_REGEX = /https:\/\/qiita\.com\/([^\/]+)\/items\/([^\/]+)/

// 任意のチャンネルからメッセージを取得
function getSlackMessages() {
  const options = {
    method: "post",
    contentType: "application/json; charset=utf-8",
    headers: {
      Authorization: "Bearer " + SLACK_TOKEN,
    },
  }
  
  const requestUrl = `${SLACK_GET_MESSAGES}?channel=${SLACK_QIITA_CHANNEL_ID}&pretty=1&oldest=${timestamp()}`
  const response = UrlFetchApp.fetch(requestUrl, options)
  const messages = JSON.parse(response.getContentText()).messages
  const results = []
  messages.map((message) => {
    const text = message.text
    const links = text.match(QIITA_LINK_REGEX)

    links && results.push(links)
  })
  return results
}
// ストックを追加
function putStocks(results) {
  const options = {
    method: "put",
    contentType: "application/json; charset=utf-8",
    headers: {
      Authorization: "Bearer " + QIITA_TOKEN,
    },
  }

  results.map((links) => {
    links.map((item) => {
      const matches = item.match(QIITA_EXTRACTION_REGEX)
      if (!matches || matches[1] === QIITA_USER_NAME) return
      const requestUrl = `https://qiita.com/api/v2/items/${matches[2]}/stock`
      try {
        const response = UrlFetchApp.fetch(requestUrl, options)
        if (response.getResponseCode() !== 204) throw new Error()
      } catch (e) {
        sendErrorMessage("ストック、失敗してまっせ。")
      }
    })
  })
}
function sendErrorMessage(message) {
  const options = {
    method: "post",
    payload: JSON.stringify({
      text: message,
      channel: SLACK_BOT_CHANNEL_ID,
    }),
    contentType: "application/json; charset=utf-8",
    headers: {
      Authorization: "Bearer " + SLACK_TOKEN,
    },
  }
  UrlFetchApp.fetch(SLACK_POST_MESSAGES, options)
}
// 環境変数から値を取得する
function getVal(e) {
  return PropertiesService.getScriptProperties().getProperty(e)
}
// 日本時間で今日の0時0分のUnixタイムスタンプを取得
function timestamp() {
  const now = new Date()
  const timezoneOffset = 9 * 60 // 日本時間はUTC+9
  now.setMinutes(now.getMinutes() + now.getTimezoneOffset() + timezoneOffset)
  now.setHours(0, 0, 0, 0)
  return Math.floor(now.getTime() / 1000)
}

経緯

後で読みたい記事があったとき、一旦ストックとして登録しておいて、あとで見ることもあるかと思います。
そんな中で、会社内でQiitaの記事が盛んに投稿されており、見てない記事はストックの「後で見る」に自動で追加できないかなーと思って作ってみました。

導入方法

1. GASプロジェクトの作成

Googleアカウントを持っている方はすぐにできます。
Google Driveから「+新規」 > 「その他」 > 「Google Apps Script」にアクセスします。

CleanShot 2024-06-06 at 01.16.05.png

そうしたら、こちらの記事を参考に適当なプロジェクトを作成してください。

2. ソースコードのコピー

結論で乗せているソースコードをそのままコピペしてください。
もうほぼ完成です。

3. Qiita APIのトークンを取得

Qiitaのアカウントを取得している方はすぐに取得できます。
以下の画像を参考にトークンを取得してください。
なお、「発行する」ボタンを押下して実際にトークンが発行された際は、発行されたトークンは一度しか表示されない(リロードすると消える) のでクリップボードに登録しておくなどして忘れないようにしてください。

CleanShot 2024-06-06 at 01.29.01.png

4. Slack APIのトークンを取得

以下記事を参考にトークンを取得してください。

なお、今回使用するトークンは以下画像の箇所にあります。

CleanShot 2024-06-06 at 01.48.30.png

5. Slack APIの権限設定

Slackで作成した各アプリはそれぞれ権限を設定できます。
メッセージを送信することができるようになる、スレッドの内容を取得できるなどですね。
設定箇所は以下になります。

まず、ダッシュボードのサイドバーにある「OAuth & Permission」へ遷移してください。

CleanShot 2024-06-06 at 01.38.53.png

次に「Scopes」という箇所があると思うので、「Bot Token Scopes」 > 「Add an OAuth Scope」から該当の権限を追加してください。

CleanShot 2024-06-06 at 01.41.42.png

なお、設定している権限はドキュメントに記載されているので、今後別のエンドポイントを使用する場合は参考にしてみてください。

以下はチャンネル内にあるメッセージを取得するエンドポイントになります。

CleanShot 2024-06-06 at 01.46.38.png

6. 環境変数を登録

GASのサイドバーにある歯車マークを押下すると「プロジェクトの設定」ページに遷移します。
画面下部にある「スクリプト プロパティ」という箇所でソースコードの実行に必要な環境変数が登録できます。

現在登録されているものとしては以下になります。

  • QIITA_TOKEN : Qiita APIを使う時に必要なトークン
  • SLACK_BOT_CHANNEL_ID : Slack内でbotがあらゆるメッセージを送信するチャンネルのID
  • SLACK_QIITA_CHANNEL_ID : Qiitaの記事を抽出する対象となるSlackチャンネルのID
  • SLACK_TOKEN : Slack APIを使う時に必要なトークン

CleanShot 2024-06-06 at 01.20.36.png

7. 以上!!

まとめ

ここまで見てくださってありがとうございました!

今後追加したい機能としては、

  • 見てないストック記事を特定のSlackのチャンネルに定期送信したり
  • そこから「いいね」が押せるようになる
  • 読んだらストックから外れるようになる
    などができるようになったらもっと便利になりそうですね!

また、GAS・Slack API・Qiita APIのそれぞれの記事は結構あったのですが、それらをつなぎこんだ記事は少ない印象でした。
なので、GASを使って両APIを使って実装する時に、本記事が皆さんの参考になったら嬉しいです!
また、参考になったよーっていう方は「いいね」をよろしくお願いします!

ではでは!

75
33
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
75
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?