これ、は何⁈
Twitterで有名な謎のインド人ことマツヤ氏。
彼のような独特の文体で気温に対して感想を述べるbotを作ったので、その過程などを簡単に書く。
実装内容(ライブラリ部分):https://github.com/Syuko4omi/matsya_temperature
bot:https://misskey.io/@matsya_temperature
アー、⁇⁉︎、⁇マツヤの、。じこしようかい??。☆
- Twitterのアカウント:मत्स्य
- Twitterのフォロワー数20万人超え
- 日常のさもないツイートで毎回のように万バズする謎のインド人(日本在住)
- カレー屋(店名や所在地不明)
- 犬を飼っている
はぁ‼︎!?、botをつくるって。、⁇!なによ、、⁉︎
以下のような手順で作る。
- マツヤ風ツイートを生成する部分を作る
- 手順1で作ったライブラリをベースに、テキストを生成するアプリを作る
- アプリをデプロイし、定期実行するスクリプトを走らせる
手順1:マツヤ風ツイートを生成する部分を作る
- Pythonで実装する
- まず、OpenWeatherMapのAPIを使い、外部から天候の情報を取得する
- その後、取得した天候の情報を元に、ツイートの核となる気温や季節の情報を生成し、特殊な文体に直す
💬ライブラリ部分の処理の具体例
- 日付や天候の情報 → 2024年3月24日 体感気温4度
- 上記の情報を元に判断した気温や季節 → 寒い・冬
- 気温や季節を特殊な文体に変換 → さム!
🧑💻ライブラリ部分の実装の概要
非本質なので読み飛ばしてOK🚩
期間 | 体感気温 | 気温・季節 |
---|---|---|
1月〜5月 | 18度以上 | 暑い・春 |
8度〜18度 | 暖かい・春 | |
8度以下 | 寒い・冬・ふゆ | |
6月〜9月 | 28度以上 | 暑い・夏 |
24度〜28度 | 涼しい・秋 | |
24度以下 | 寒い・秋 | |
10月〜12月 | 28度以上 | 暑い・夏 |
18度〜28度 | すずしい・秋 | |
18度以下 | 寒い・冬・ふゆ |
- ステップ1:気温は暑い・暖かい・涼しい・寒いの四種類から選ぶ。季節も春夏秋冬の四種類から選ぶ。気温や季節の肌感覚は、過去のマツヤ氏のツイートから独断と偏見で上記表のように決定した。その上で、マツヤ氏が普段どのようにそれぞれを形容しているのかを、直近のツイートを参考に集めた上で、核となる部分を生成する。
- 季節
- (これは(ね|ですねえ))<春夏秋冬>(ネ)
- 寒暖
- (これは)<気温>
- 暖かい→ あたかい・あたたかい・あたたかネ・あったかくない?
- 涼しい→ すじゆし・すじゆしとおもいますけど
- 暑い→ あつい・あつくネ?・あつくない?・あついとおもいますけど
- 寒い→ さむ・サむ・さム・さむい・サむい・さムい・さむくネ?・さむいとおもいますけど
- (これは)<気温>
- 季節
- ステップ2:気温や季節を形容する部分(ツイートの核となる部分)を生成したら、それに対してマツヤ風な文章になるように調整を施す。以下はその例である
- 形容詞や副詞を挿入する。例えば、季節の前に「かんぺきに(ねえ)・しょうみな話(ねえ)」といったフレーズを入れる
- カタカナをランダムに半角にする
- 文節の切れ目で、記号(句読点・!・?・!!・??・?!・☆)をランダムに挿入する
手順2:手順1で作ったライブラリをベースに、テキストを生成するアプリを作る
🔧アプリ部分の実装の概要
- Flaskで実装する
- (※ライブラリ部分の実装では、pip installでライブラリがインストールできるような構造を心がけた。)アプリの実装では、ライブラリの上にapp.pyとしてアプリケーション部分を乗せるだけで完了した
- アプリが担うのは、URLにアクセスしたら、ライブラリで生成したテキストを返却する役割である
- ローカル環境で下記のapp.pyを実行して、自分自身を指すループバックアドレス(127.0.0.1)にアクセスすると、マツヤ風ツイートが生成される
import os
from flask import Flask
from matsya_temperature.generate_sentence import generate_sentence
app = Flask(__name__)
@app.route("/")
def matsya_report_temperature():
return generate_sentence()
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
> poetry run python3 app.py
かんぺきに!?‼︎あたかい!
手順3:アプリをデプロイし、定期実行するスクリプトを走らせる
- Cloud Runと、Google Apps Script (GAS)を用いる
- Cloud Runは、サーバーなどの管理を考えずにアプリを実行できるプラットフォームを提供してくれる。クラウド上でアプリを立ち上げておけるので、任意のタイミングでマツヤ風ツイートが生成できるようになる
- Google Apps Scriptは、ブラウザ上で作成したプログラムをGoogleのクラウド上で実行するプラットフォームを提供してくれる。PCを立ち上げなくてもプログラムを定期的に実行してくれる機能などもある
🏗️Cloud Runでアプリをデプロイ
- デプロイ後に所定のURLにアクセスすると、手順2で実装したアプリが走り、以下のようにテキストが返却される
Cloud Runでアプリをデプロイする詳しい手順。この記事の末尾にあるCloud Runの参考リンクを見れば大体分かるので、読み飛ばしてOK🚩
-
まずはこのページからcloud runのアカウントを作る。それから、google-cloud-sdkをこちらからダウンロードし、ホームディレクトリで解凍する
-
gcloudコマンドが使えるようにするためにパスを通す。.zshrcに以下を書く
source '/Users/<user_name>/google-cloud-sdk/path.zsh.inc' source '/Users/<user_name>/google-cloud-sdk/completion.zsh.inc'
-
ターミナルを終了すると以下のようなエラーが出たので、こちらのページに従って修正した
zsh compinit: insecure directories, run compaudit for list. Ignore insecure directories and continue [y] or abort compinit [n]?
-
-
gcloudコマンドが使えるようになったら、gcloud initする。アカウントの紐付けとかやると、cloud project IDが発行される
-
Dockerfileを書く。app.pyと同じディレクトリに置く
-
以下のコマンドを実行してビルドを行う。pip installする都合上、pyproject.tomlのpythonバージョンがDockerfileと対応していないとエラーが出るので注意(ここにないバージョンでもワンチャンいける 3.9.13とか)。
gcloud builds submit --tag gcr.io/<cloud_project_id>/matsya_temperature
- 以下のコマンドを実行してデプロイする。regionを選ぶように言われるので、東京に対応するasia-northeast1を選択。
gcloud run deploy --image gcr.io/<cloud_project_id>/matsya_temperature --platform managed
- アクセスに認証などいるかを聞かれるので、不要の方(y)を選ぶ。するとデプロイが完了し、Cloud Runに記載されている当該サービスのURLにアクセスできるようになる
Allow unauthenticated invocations to [matsyatemperature] (y/N)?
- update-env-varsなどのオプションを使えば、ローカルの環境変数(例えば、今回はOWMのAPIキー)を渡すこともできる。詳しくはこちらを参照
gcloud run services update matsyatemperature --update-env-vars OWM_API_KEY=xxx
⏰Google Apps Script (GAS)を使い、misskeyへの投稿を定期実行するスクリプトを書く
- Google Apps Script (GAS)を使い、定期的にURLにアクセスしてテキストを取得してmisskeyに投稿するスクリプトを作成した
- スクリプトを実行すると以下のようにテキストが生成され、これがmisskeyのタイムラインに投稿される
botを作る部分の概要。この記事の末尾にある、misskeyのbotを作る記事とほとんど内容が同じなので、読み飛ばしてOK🚩
- misskeyでbot用のアカウントを作る。適当な権限を設定(例:投稿のみ許可など)してアクセストークン(APIキー)を発行する
- GASで新しいプロジェクトを立ち上げ、以下のようにテキストを投稿するコードをJavascriptで記述する
function TLPost() {
const url = 'https://<app-url>';
try {
const response = UrlFetchApp.fetch(url);
const receivedText = response.getContentText();
console.log(receivedText);
let postURL = "https://misskey.io/api/notes/create"
var headers = {"Content-Type": "application/json",}
var data = {
"method": "post",
"headers": headers,
'payload': JSON.stringify({
"i" : "<access-token>",
"text": receivedText
})
}
let responses = UrlFetchApp.fetch(postURL, data)
} catch (error) {
console.error('Error:', error);
}
}
- 上記のスクリプトを定期実行するように、トリガーを設定する
- 時間になると、以下のようにスクリプトが走り、タイムラインに投稿される
まとめネ
〜こうしてこの世界にまた一つ 新たなインターネットデブリが生まれた〜