LoginSignup
6
3

More than 1 year has passed since last update.

技術記事を定期的にLINEに投げたい

Posted at

これは何?

自主的に勉強をしたり記事を探したりするのがとても苦手なので、勝手に情報入ってくるようにしたいと思い、qiitaの記事が勝手にLINEに流れてくるようにしてみます

まずはqiitaのapiを調べる

ありました
https://qiita.com/api/v2/docs
利用制限 認証している状態ではユーザごとに1時間に1000回まで、認証していない状態ではIPアドレスごとに1時間に60回までリクエストを受け付けます。
認証してなくても叩けるようですが、開発過程とかもっと叩くだろうということで認証認可の部分参考にして、個人用のtokenを発行します
image.png
投稿の取得はこの辺でできそうです
https://qiita.com/api/v2/docs#%E6%8A%95%E7%A8%BF
試してみます

curl -H 'Authorization: Bearer xxxxxxxxxxxxxxxxxxxx' 'https://qiita.com/api/v2/items?page=1&per_page=1' | jq

結果は載せませんが、結論上記で取れました
さらに、取得する記事はそれなりに絞り込みたいので、どんな条件で絞れるか調べてみます
https://help.qiita.com/ja/articles/qiita-search-options
特定の日付以降でストック10件以上とかで絞り込みます

https://qiita.com/api/v2/items?page=1&per_page=20&query=created:>2022-01-01+stocks:>10

複数条件使う時はちょっと癖があるみたいなので以下を参考にしました
https://qiita.com/kijibato/items/1f8b86fc5e7cd3b0db17

取得した記事を記録していく

Google spread sheetに書いていきます
自動でLINEに送る仕組みの構築にはGASを使います
最初、cloud functions上で実行してapiでspread sheetに記載しようかと思ったのですが、
Google sheet apiが結構苦労する感じだったので、
spread sheetの値の読み取り、書き込みなどやりやすいGASでやることにしました

とりあえずQiitaのapi叩いてspread sheetに書き込むところまではこんな感じで動きました

function getQiitaItems(tag) {
  var searchTag = tag ? tag : 'javascript';
  const page = 1;
  const perPage = 2;
  const createdLimit = Utilities.formatDate(new Date('2022/01/01'), "Asia/Tokyo", "YYYY-MM-DD");
  const stocks = 100;
  var url = `https://qiita.com/api/v2/items?page=${page}&per_page=${perPage}&query=created%3A%3E${createdLimit}+stocks%3A%3E${stocks}+tag%3A${searchTag}`;

  const token = "xxxxx"
  const options = {
    method: 'GET',
    headers: {
      Authorization: `Bearer ${token}`
    }
  };
  var response = UrlFetchApp.fetch(url, options);
  var data = JSON.parse(response.getContentText()).map((d) => ({
    id: d['id'],
    title: d['title'],
    url: d['url'],
    likes_count: d['likes_count']
  }));
  return {data, dataLength: data.length};
}

function writeQiitaItemsToSheet() {
  var {data, dataLength} = getQiitaItems("typescript");
  var spreadSheet = SpreadsheetApp.getActiveSheet();
  var currentMaxRow = spreadSheet.getLastRow();
  var currentItemIds = spreadSheet.getRange(2, 1, currentMaxRow).getValues();
  var dataNum = 0;
  for (var i = currentMaxRow; i < currentMaxRow + dataLength; i++) {
    var id = data[dataNum].id;
    if (currentItemIds.some(itemId => itemId == id)) {
      console.log('skip write', data[dataNum].id);
      dataNum++;
      continue;
    }
    var maxRow = spreadSheet.getLastRow();
    spreadSheet.getRange(maxRow + 1, 1, 1, 4).setValues(
      [[data[dataNum].id, data[dataNum].title, data[dataNum].url, data[dataNum].likes_count]]
    );
    dataNum++;
  }
}

結果はこんな感じ
image.png

LINEに投稿する

LINEの公式ドキュメントを参考にします
https://developers.line.biz/ja/docs/messaging-api/

LINEのDeveloper consoleからアカウント登録し、チャンネルなどを設定します
image.png
各項目を埋めて規約に同意し、チャンネルを作成します
作成が完了すると管理画面が開きます
image.png
Messaging API設定を開きます。
このQRコードを読み込めば友達として追加できるみたいです
image.png
Messaging apiをGASから実行するにはこのチャネルアクセストークンを利用すればできそうです
image.png
あと送信先ってどう指定すればいいのかなと思ったんですが、今回は送り先が自分だけなので、
その場合はチャネル基本設定の中に「あなたのユーザーID」を参照して指定すれば良いようです
image.png
LINEへの投稿はこんな感じでできました

function postMessageToLINE(message) {
  var msg = message ? message : "Hello, world!";
  const myUserId = "userId";
  const token = "ACCESS_TOKEN";
  const url = "https://api.line.me/v2/bot/message/push";
  const data = {
    "to": myUserId,
    "messages":[
        {
            "type":"text",
            "text":msg
        },
    ]
  };
    var headers = {
      'Content-Type': 'application/json',
      'Authorization': "Bearer " + token, 
    }
    var options = {
  'method' : 'post',
  'headers': headers,
  'payload' : JSON.stringify(data)
  };
  var res = UrlFetchApp.fetch(url, options);
}

さらに、すでに送信されたものは投稿したくないので、スプレッドシートに送信日を記録しておいて、送信日が埋まっているものは送信スキップするようにしました

function postQiitaToLINE() {
  var spreadSheet = SpreadsheetApp.getActiveSheet();
  var currentMaxRow = spreadSheet.getLastRow();
  var data = spreadSheet.getRange(2, 1, currentMaxRow, 5).getValues();
  for (var i = 0; i < currentMaxRow - 1; i++) {
    if (data[i][4]) { // 送信日の列が埋まっている場合はスキップ
      continue;
    }
    const today = Utilities.formatDate(new Date(), "JST","yyyy-MM-dd");
    const title = data[i][1];
    const url = data[i][2];
    postMessageToLINE(title + '\n' + url); // LINEに送信
    spreadSheet.getRange(i + 2, 5).setValue(today); // 送信日を記録
    break;
  }
}

image.png
こんな感じで投稿できました
image.png
あとはこの投稿関数が定期的に実行されるようにします
GASのconsoleでトリガーのタブを開き、新しいトリガーを作成します
image.png
時間主導型で日付ベースのタイマー、午前6時 ~ 7時にすることで、毎朝見れるようにします
image.png
翌朝見たらちゃんと時間通りに通知されました!
image.png
これを使って継続的にインプットしていきます..!

6
3
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
6
3