LoginSignup
4
2

More than 5 years have passed since last update.

論文をサボっているとリプライで叱ってくれるbotを作った(AWS Lambda + CloudWatch Events)

Last updated at Posted at 2018-11-11

やったこと:投稿論文の進捗管理用TwitterBotを作る

キャプチャ.PNG
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コンソール上からテストします。
    キャプチャ.PNG
    実際にツイートされました。

  • 開発環境からは以下で動かせるはず

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 *

参考

4
2
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
4
2