Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8902

TwitterでTILしたらGitHubに草が生える

$
0
0

はじめに

TIL(Today I Learned): 今日学んだこと

をtwitterのつぶやきで行おうと思いました

  1. #tilというハッシュタグで学びをつぶやく
  2. 1日1回自分の投稿の #tilハッシュタグを拾いに行く
  3. GitHubにコミット

というのがいけないかな〜と思ったのがきっかけです

AWSで CloudWatch Events + Lambda Functionsあたりでできそうな気がしたのでやってみます

参考

準備

  • AWSアカウント
  • Twitter開発者アカウント
  • TILをコミットしていくGitHubリポジトリ

Twitter APIを利用するためには開発者アカウントの登録が必要です

※ 利用目的とか審査とかあってやや面倒です…

手順

til-twitter.png

  1. Amazon CloudWatch Eventsで定期的にAWS Lambdaを起動
  2. LambdaでTwitter APIを叩いて #tilツイートを取得
  3. #tilツイートがあればGitHub APIを叩いてコミットする

アプリケーションの動きとしては上記の流れを想定します

なのでやらないといけないことは、

  1. Lambda Functionsの作成
    1. Twitter APIを叩いて #tilツイートを取得するjsを作る
    2. GitHub APIを叩いてコミットするjsを作る
    3. Lambdaに登録する
  2. 定期的にLambda Functionsを実行するCloudWatch Eventsの作成

という感じになります

1. Lambda Functionsの作成

最終的にはこんなjsができあがりました

https://github.com/halnique/til-twitter/blob/master/index.js

色々詰め込み過ぎだし改善の余地は大いにありそうですが、中身を見ていきます

1-1. Twitter APIを叩いて #tilツイートを取得する

Twitter開発者アカウントを登録してアプリ作成を行うと、以下の値が得られます

  • Consumer API key
  • Consumer API secret key
  • Access token
  • Access token secret

これらを環境変数から設定し、twitterモジュールを利用します

constTwitter=require('twitter');consttwitterClient=newTwitter({consumer_key:process.env.API_KEY,consumer_secret:process.env.API_SECRET,access_token_key:process.env.ACCESS_TOKEN,access_token_secret:process.env.ACCESS_TOKEN_SECRET,});

あとはTwitter APIのドキュメントを見ながら、特定のツイートを取得するように実装します

constnowString=`${now.getFullYear()}-${now.getMonth()+1}-${now.getDate()-1}`;constparams={q:`(from:${process.env.ACCOUNT_NAME}) since:${nowString}${TARGET_HASHTAG}`,count:process.env.MAX_COUNT||5,};consttweets=awaittwitterClient.get('search/tweets',params).catch(()=>[]);

ACCOUNT_NAMEは自分のTwitterアカウントを環境変数で設定します

最終的には毎日日付が変わったタイミングぐらいで実行させるので、前日以降のツイートに絞っています

※ jsの日付処理貧弱すぎない?みんなmoment.jsとか使うの?

実際はこのあとに各ツイートのハッシュタグを厳密にチェックしてますが、だいたい↑ぐらいでお目当てのツイートは取得できるはずです

1-2. GitHub APIを叩いてPRを作成する

これが地味に大変だった…

CLIなら git addして git commitして git pushするだけのかんたんなお仕事ですが、APIでやろうとするとある程度踏み入った理解が必要になります

流れとしては blobを作って treeを作って commitを作って HEADのSHAを書き換えるということになります

constprevRefsHead=awaitgetRefsHead();constcommitSha=prevRefsHead.object.sha;constprevCommit=awaitgetCommit(commitSha);constblob=awaitpostBlob(data[i]);consttree=awaitpostTree(prevCommit.tree.sha,blob.sha,i+1);constcommit=awaitpostCommit(commitSha,tree.sha,i+1);awaitpatchRefsHead(commit.sha);awaitsleep(1);

中身はそれぞれ対応したAPIを実行しているだけですが、こちらもドキュメントとにらめっこしながらパラメータと流れを調節しました

※ 連続して実行したときにコミットがうまくいかないことがあったので、1件ずつsleepするようにしてます

1-3. Lambdaに登録する

jsは何度もお試し実行すると思うので、ローカルでDockerとかで書くのがよいです

jsができあがったらLambdaに登録していきます

注意点として、Lambda上で外部モジュールは基本的にそのまま requireすることはできません

今回でいうと

constTwitter=require('twitter');

ですね

これは事前に Lambda Layersとして作成しておくことで解決できます

image-lambda-layers1.png

zipファイルを直接アップロードするか、 S3に上げておいてそれを利用することができます

zipファイルの中身は注意が必要で、例えば modules.zipを解凍したときに以下の構成になっている必要があります

$ ls -1 modules/
node_modules/

node_modulesの中に利用したいモジュールが入っているイメージです

この構成になっていないと、Lambda Functionsの方で利用するのにうまくいきません

先にLambda Layersを作ったら、Lambda Functionsを作成していきます

image-lambda1.png

ランタイムはLambda Layersと同じになるようにします

Lambda FunctionsもzipファイルをアップロードしたりS3のファイルを利用することができますが、今回はそのまま作成したコードを貼り付けます

image-lambda2.png

環境変数をたくさん使うので、ぽちぽち登録します

image-lambda3.png

タイムアウト設定をデフォルトの3秒 -> 30秒に変更しておきます

image-lambda4.png

最後にLambda FunctionsにLambda Layersを追加すればOKです

image-lambda5.png

右上から適当なテストイベントを作ってテストしてみて、無事に動けばLambdaとしては完成です

2. 定期的にLambda Functionsを実行するCloudWatch Eventsの作成

image-cloudwatch-events3.png

image-cloudwatch-events2.png

以上

簡単に設定できました

Cron式については、日付が変わったころに前日分のツイートを取得するような感じで実行されるようにします

CloudWatch EventsのCron式で実行されるイベントは、UTCで誤差1分以内だそうです

前日に #tilツイートをしていれば、日本時間でだいたい翌日の朝9時頃にコミットができあがる想定ですね

実行結果

image-tweet1.png

image-commit1.png

コミットされました

これで無事にツイートするだけで草が生える環境ができあがりました

学び

  • node_modulesを Lambda Layersに追加しておくことで、Lambda Functionsで使えるようになって便利
  • Gitのコミットができるまでの流れ 10.2 Git Internals - Git Objects
  • CloudWatch EventsのスケジュールでCron式を使う場合、日と曜日のどちらかは ?にする必要がある

Todo

  • Lambda FunctionsとLambda Layersへのデプロイを GitHub Actionsで自動化したい人生だった…
  • GCPで Cloud FunctionsCloud Schedulerでも似たようなことができそうなのでやってみたい

まとめ

GitHubの草が生えているからといって活発に開発をしているとは限らないぞ


Viewing all articles
Browse latest Browse all 8902

Trending Articles