やったこと:投稿論文の進捗管理用TwitterBotを作る
https://twitter.com/naoki_maejima/status/1061196481762222080
- 論文を書き上げるためには、論文を書くためだけの時間を作ることが必要らしい。
- そこで、論文を書く予定の日に論文ドラフト管理用GitHubリモートリポジトリにコミットがなかった時にリプライで叱ってくるTwitterのBotを作った。
- 毎週月・火・木(金曜はやっぱり遊びたかった)を絶対論文書く日とする。この日にコミットがないと怒られる仕様。
- 公共の目に触れるTwitterでbotを作るほうが、Slackbotなどより効果的だと考えた。
- 開発に使ったもの:Python3.6, AWS Lambda, AWS CloudWatch Events
- TwitterDevelopersAccountやGitHubのアクセストークンなどは取得した前提で書いています。
ファイル構成
twitter_bot
├── config.yml
├── lambda_function.py
└── requirements.txt
この他に後ほどPythonのパッケージがインストールされる。
requirements.txt
- 必要なPythonパッケージは以下。
- git_lambdaはLambdaからgitを動かす用。gitのバイナリがバインドされていて、PATHも通してくれるスグレモノ。スクラッチで実装するのは面倒だったので…(感謝)。
{requirements.txt}
requests_oauthlib==1.0.0
GitPython==2.1.11
git_lambda==1.1.3
PyYAML==3.13
各種設定用のyamlファイル(config.yml)
- 認証情報やリプライ先の指定を外部化している。
- 叱るだけではあんまりなので褒める文章も用意
{config.yml}
keys:
twitter:
consumer_key: "XXXXXXXXXXXXXXXXXXX"
consumer_secret: "XXXXXXXXXXXXXXXXXXX"
access_token: "XXXXXXXXXXXXXXXXXXX"
access_secret: "XXXXXXXXXXXXXXXXXXX"
github:
repository: "https://username:token@github.com/username/repository.git"
config:
twitter:
user: "@twitter_user"
alert_text: #サボった時のお叱り
- "論文を書け、まだ間に合う。"
- "論文を書きなさ~い!!"
- "論文を進めれば、不安は消える。"
- "明日やろうはバカ野郎だ。"
praise_text: #サボってなかった時の褒め
- "論文を書いて、えらーい!!"
- "論文を書いたので救われた。"
- "いいね、この調子!!明日はもっと書ける!!"
- "がんばった!!投稿まであと少し!!"
#スクリプト(lambda_function.py)
{lambda_function.py}
import git_lambda
git_lambda.setup() #lambdaからgitを使えるように設定しておく
from git import Repo, RemoteProgress
import yaml
import os
import random
from datetime import datetime, timedelta, timezone
from requests_oauthlib import OAuth1Session
def lambda_handler(event, context):
#各種パラメータの設定
TEMP_DIR = '/tmp/git_test_' + str(datetime.now().timestamp()) #git init用の一時フォルダ。lambdaでは/tmp以下でしか書き込みができない
JST = timezone(timedelta(hours=+9),'JST') #日本時間に設定
TODAY_DATE = datetime.now(JST).date() #現在の月日を取得
UPDATE_URL = 'https://api.twitter.com/1.1/statuses/update.json' #Twitter投稿用
#設定ファイルを読み込む
with open('./config.yml','r') as f:
keys = yaml.load(f)
#Twitterの認証情報
consumer_key = keys['keys']['twitter']['consumer_key']
consumer_secret = keys['keys']['twitter']['consumer_secret']
access_token = keys['keys']['twitter']['access_token']
access_secret = keys['keys']['twitter']['access_secret']
#gitリモートリポジトリからfetchする
os.makedirs(TEMP_DIR, exist_ok=True)
repo = Repo.init(TEMP_DIR)
origin = repo.create_remote('origin',keys['keys']['github']['repository'])
origin.fetch()
commits = repo.iter_commits('origin/master')
#最新のコミットから順に読まれていくので、今日のコミットでなくなるまで詳細を取得していく
today_insertions = 0
today_deletions = 0
today_commit_count = 0
for commit in commits:
commit_date = datetime.fromtimestamp(commit.committed_date,JST).date()
if(commit_date == TODAY_DATE):
commit_stats = commit.stats.total
today_insertions += commit_stats['insertions']
today_deletions += commit_stats['deletions']
today_commit_count += 1
else:
break
#ツイートを部品ごとに生成していく
header_text = "\n".join([keys['config']['twitter']['user'], #リプライ先の指定
TODAY_DATE.strftime("%Y/%m/%d")]) #日付
result_text = "\n".join(["コミット数:" + str(today_commit_count),
"追加した行:" + str(today_insertions),
"削除した行:" + str(today_deletions)])
if(today_commit_count == 0):
#サボってた場合のテキスト
comment_text = random.choice(keys['config']['twitter']['alert_text'])
else:
#頑張って論文を書いた場合のテキスト
comment_text = random.choice(keys['config']['twitter']['praise_text'])
text = "\n".join([header_text,result_text,comment_text])
#TwitterAPI経由で実際にツイートを行う
params = {"status": text}
twitter = OAuth1Session(consumer_key, consumer_secret, access_token, access_secret)
req = twitter.post(UPDATE_URL, params = params)
return "Tweet OK"
パッケージごとzipで固める
pip install -r requirements.txt -t .
zip -r twitter_bot.zip ./*
- こうしてできたzipファイルをLambdaにアップロードします。
- 15MBちょいくらいのzipファイルができるはずです
Lambdaコンソールからテスト
- 適当にテストイベントを設定して、Lambdaコンソール上からテストします。
- 開発環境からは以下で動かせるはず
{main.py}
from lambda_function import lambda_handler
lambda_handler(None,None)
CloudWatch Eventsから定時実行の設定
- ターゲットを先程のLambda関数に設定。
- 日本時間の毎週月火木の23:59(UTC 14:59)に起動するように、CloudWatchEventsのスケジューラに以下のcron式を記述。
59 14 ? * MON,TUE,THU *