LoginSignup
2

More than 1 year has passed since last update.

posted at

updated at

【Node.js+heroku】Twitter星座占いbot作成

作ったもの

スマホゲーム「#コンパス」の「魔法少女リリカルルカ」をモチーフにしたTwitter星座占いbotを作成しました。

bot本体:リリカルルカのドリーム☆星座占い
bot紹介動画:【ドリーム☆星座占い】コンテンツのご案内
仕様書等:基本設計書・結合テスト仕様書・ソースコード
※占いデータを格納しているため、GitHubは非公開です。
参考:#コンパス 戦闘摂理解析システム | スマホゲーム

★2022/1/4★
仕様改善しました。
[参考]【Node.js,heroku】Twitter星座占いbot仕様改善・機能追加

1.作成の契機

ゲーム内のチャットで毎日投稿していた星座占いのフルバージョンを投稿するために作成しました。
ゲーム内チャットは手動投稿となるため、12星座分全てではなく、以下のように1位のみに絞って投稿していました。
そのため、Twitterで1~12位までのフルバージョンを投稿することにしました。

そもそも何故こんなことをしているのか等、もし詳しい経緯等が気になる場合は以下ご参照下さい(技術的な話以外はこちらに記載しています)。
参考:【プログラミング】Twitter星座占いbot作成【Node.js+heroku】

2.開発言語・サーバーの選定

既存のbotサービスの利用も考えましたが、スレッド形式での投稿や画像の編集が行えるようなサービスはなさそうだったので、自作することにしました。自作するにあたり、開発言語とbotを稼働させるサーバーを選定する必要がありました。

(1)開発言語の選定

ブログでたまにjavascriptを扱うことがあったため、また、bitFlyer(暗号通貨取引所)のAPIをNode.jsで試してみたことがあったため、今回もNode.jsを使うことにしました。
ただ、bot作成に関する参考記事はPythonの方がやや多かった印象でしたので、新しく作るならPythonの方がやりやすいかもしれません。

(2)サーバーの選定

「無料で利用できること」を条件に選定しました。
以下の①~③を候補として検討しました。
最終的にはherokuで動かすことになったのですが、ここは色々と悩みました。

①共有レンタルサーバー

XFREEなど無料で利用できるサービスはあったものの、Node.jsに対応しているレンタルサーバーはなく、自分でインストールして利用するのも利用規約に抵触するか、抵触しなくても推奨されるものではないようでしたので、候補から外しました。

参考:Node.jsに対応しているレンタルサーバーはある?国内・外のホスティングサービスをリサーチ
参考:無料レンタルサーバー【XFREE(エックスフリー)】
参考:さくらレンタルサーバー node.jsのインストールできない

②仮想専用サーバー(VPS)

無料で利用できるものはあるものの、スペック的に厳しそうでしたので、候補から外しました。

参考:意外と使える?無料のVPSサービスを調べてみた結果
参考:VPSを無料で使えてデメリットのないところを紹介【2019年版】

③サーバーレス

私にはサーバーの知識が乏しく、このようなサービスがあることを知りませんでしたが、上記の参考記事のいくつかに代替手段として記載があり、調べてみることにしました。
結果、様々な制約はあるものの、herokuを利用してbotを稼働させるという結論に至りました。

・heroku
約24時間に1回dynoが再起動される、無料枠では毎月550時間(クレカ登録で1000時間)までしか稼働できない、等の制約はあるものの、今回作成したいbotの要件は満たせると判断して、こちらのサービスを利用させて頂くこととしました。

参考:Heroku を使って無料でアプリを開発
参考:知っておきたい!Herokuを使う上では当たり前?の16の常識

・Unubo
herokuと似たようなサービスのようですが、検索してもあまり参考記事がなく、候補から外しました。

参考:Node.js,Python,RubyなどのWebアプリを完全無料でホスティング可能な「Unubo」を使ってみた!

・GAS
herokuを使い始めた後で存在に気付いたのですが、こちらの方が簡単だったような気もします。
今度機会があれば利用してみたいと思います。

参考:【GAS】Twitterのbotを作ってみました。サクッとできます! - Webird Programming.Tech
参考:GASで作るサーバーレスTwitter Bot【Google Apps Script】

3.環境構築

(1)Node.js

私のPCはWindows10ですので、Windowsにインストールする方法を調べてインストールしました。

参考:Node.jsをWindows10にインストールする方法

(2)Twitter API利用申請

私はすんなり申請が通りましたが、はまる時ははまるようです(はまっていた記事は少し昔の記事なので、今はすんなり通るのかもしれません)。
参考:2021年度版 Twitter API利用申請の例文からAPIキーの取得まで詳しく解説
参考:Twitter開発者アカウントを申請してから承認されるまでの全記録

(3)heroku

基本的にはスターターガイドに沿って進め、上手くいかなかった時は適宜検索しました。

参考:Heroku スターターガイド (Node.js)
参考:twitter定期botをHerokuにデプロイ
参考:heroku 初級編 - GitHub から deploy してみよう -
参考:Herokuのタイムゾーンを日本に合わせる

大体はGoogle検索で解決するのですが、自動デプロイの設定で少しはまりました。
heroku管理画面のdeployタブにて、下記画像の項目のチェックを外さないと、自動デプロイされませんでした。
下記項目は自動テストツールと連携している場合のみチェックする項目のようです。
image.png

(4)GitHub

herokuの自動デプロイを利用するにはGitと連携させる必要があるので、インストールしてherokuと連携しました。

参考:いまさらGit for Windowsのインストール、GitHubに接続してみた。

4.設計

設計書を作る前に正常系の処理は大体作り終えてローカルPCで動く状態にはなっていました。
設計書なしでもいいかなと思ったのですが、脳内設計書だと後々どうしてこのような作りにしたのか忘れてしまったり、テストケースを作る際に漏れが出てしまうかなと思い、作成しました。

詳しくは設計書をご参照頂ければと思いますが、以下で簡単に説明します。

(1)システム概要

全体像はこんな感じです。占いデータを作成するエクセルマクロなどもあるのですが、その辺は端折っています。
image.png

(2)処理概要

処理の一覧は以下の通りです。
image.png

以下、主要な処理について、簡単に説明します。

①星座占いツイート

このbotのメインの機能です。
最初に画像付き投稿⇒スレッド形式で1~12位まで順位を投稿⇒最後にランキング画像を投稿
という流れです。
データは事前に2~3か月分登録してあります。このデータを元に、スマホからゲーム内チャットに投稿するためのコピペ用テキストファイルを生成しています。
image.png

②自動リプライ処理

おまけの機能です。おみくじとタロット占いがあります。
image.png

③その他定期投稿

賑やかしの定期投稿です。
image.png

④自動星座占いツイート処理

星座占いツイートは事前に登録した占いデータを元にツイートを実行しますが、占いデータに不備があった場合や読み込みに失敗した場合に、ランダムに占い結果を生成する自動代行占いを実行します。
これは、万が一の場合にも可能な限り業務を継続させるための仕組みです。
占いデータは2~3か月分登録していますが、追加の登録を忘れた場合にもこの仕組みが発動します。

⑤エラーリプライ処理

エラー時に管理者アカウントにリプを飛ばします。
image.png

(3)処理フロー

処理フローの一覧は以下の通りです。
image.png

以下、工夫した部分について、簡単に説明します。

①星座占いテーブルデータ不正エラー/自動星座占いテーブルデータ不正エラー

自動代行占いの流れを図にすると以下のようになります。

自動代行占いも失敗した場合には、諦めてシステムエラーが発生している旨のツイートを投稿します。

②リプライ回数制限チェック

意図的な多量連続リプライによる負荷掛けを回避するため、1ユーザーに対するリプライ応答は1日につき2回(おみくじ・タロット占い)までに制限しています。
image.png
参考:【初めての個人開発】FlaskアプリとTwitterの自動返信BotをHerokuにデプロイした話

③リプライ受信エラー

Streamが一度切断されてしまうと、再接続しない限りリプライを受信できないため、再接続の処理を実装しています。
今のところ運用上差し支えないのですが、リプライを受信しないとリトライカウントが初期化されないという問題があるので、時間があれば修正したいと思います。
image.png
参考:node-twitterでstreamAPIに再接続するときの実装

5.データ作成

データファイルの一覧は以下の通りです。
image.png

(1)テーブルデータ

データはエクセルマクロで作成しています。
データの文字コードはUTF-8です。
参考に、データの一部を抜粋したサンプルを記載します。

①自動星座占いテーブル(auto_horoscope_table.csv)

自動星座占い処理で使用するデータです。
配列形式のデータを5レコード登録しています。実際の処理では、これらをランダムソートして占い結果を生成します。
image.png
image.png

②星座占いテーブル(horoscope_table.csv)

星座占い処理で使用するデータです。
今日日付と同じ日付のレコードを取得し、上から順に1位~12位としてツイートします。
image.png
変数名に「date」はミスったなと思います。
昔業務で変数名を「bin」とか「index」とかにしてしまって、OSの組み込み関数名と重複して面倒なことになったことがあるので、変数名は関数名と重複しないような名称にすべきでした。バグってはいませんが、色々と紛らわしいので今後時間があれば修正したいと思います。

③ランチテーブル(lunch_table.csv)

ランチツイートに使用します。トッピングとランチをランダムに組み合わせて使用します。
image.png

④スイーツテーブル(sweets_table.csv)

スイーツツイートに使用します。トッピングとスイーツをランダムに組み合わせて使用します。
image.png

⑤タロットテーブル(tarot_table.csv)

タロット占いに使用します。誤字があることに今気づきました…
image.png

⑥データ作成マクロについて

大したマクロではないのでコード等は端折りますが、考慮した点と参考記事は以下の通りです。
・占いデータのランダムソート
参考:ランダムに並び替える- やむえむのExcel VBAメモ
・UTF-8でCSVファイル出力する
参考:【EXCEL VBA】BOM無しUTF-8でCSVファイル出力をしたい - EXCEL VBA 研究所(入門)

(2)フォントデータ

herokuではそのままだと日本語が文字化けしてしまうため、日本語フォントのデータを配置して、それを利用する必要があります
(CSVファイルから読み込んだ文字列やハードコーディングした文字列をツイートする際には日本語でも文字化けしませんが、画像に文字を編集する際に文字化けしてしまいました)。

参考:herokuで日本語フォントを奇麗に使うには? - Qiita
参考:Heroku環境でフォントを追加する
参考:RailsアプリでPDFを出力する (Heroku対応)
参考:IPAex フォント Ver.004.01 - 一般社団法人 文字情報技術促進協議会

(3)画像データ

キャラクターの画像はVカツを使用して作成し、エクセルで加工しています。
その他の画像(タロット画像)はエクセルで作成しています。

参考:Vカツ | 世界初のVtuber支援サービス「Vカツ」

(4)ソースコード

コーディングはサクラエディタにJSの設定を入れて行っています。
サクラエディタを使っていると、文字コードのデフォルトがSJISになりますが、確か何か不都合があってUTF-8に変えた記憶があります。多分モニタ出力かツイートが文字化けするとかだった気がしますが、失念しました。

参考:サクラエディタ用JavaScript強調キーワード(シンタックスハイライト)、入力補完、ヘルプの設定

6.製造

非同期処理の扱いにとても苦慮しました。
結局エラー処理含めてテストケースは全て想定通りの挙動になることは確認しており、今のところ運用上の問題は発生していませんが、この実装が適切なものなのか、今の私には正直判断できていません。なので、書籍等で体系的に理解するようにしたいと思っています。

(1)ツイート処理

テキストのみのツイート処理や画像付きツイートの方法は、下記参考記事を元にしています。
スレッド形式のツイートは、前のツイートのツイートIDを変数で持ちまわって繋げるようにしています。
ツイート処理の関数をいくつかに分けて作成してしまったのですが、もっと共通化できると思いますので、時間があれば取り組んでみたいと思っています(statusを引数にするとか?)。

参考:node-twitter-examples at master · desmondmorris-node-twitter

(2)リプライ処理

下記記事の処理に加えて、前述の再接続処理を実装しています。

参考:20 行で作る node.js による Twitter bot 作成講座
再掲:node-twitterでstreamAPIに再接続するときの実装

(3)画像編集

星座占い結果画像、おみくじ画像、タロット画像は元画像を編集してツイートに貼付しています。
下記記事等を参考にしています。
ここはなかなか想定通りにいかず、色々試行錯誤しました。

参考:Node.jsで画像に文字を書く
参考:Node.jsでCanvas(ImageData)を使った簡単な画像処理

(4)スケジューリング

定時に処理を実行するのは、node-cronライブラリを利用しています。

参考:node.js で定時に処理を実行する

(5)スリープ

下記参考にさせて頂いています。

参考:JavaScript(Node.js) で sleep() アラカルト

(6)ライン番号取得

エラー発生個所が分かるように、エラーメッセージにはライン番号を付与しています。

参考:Node.jsでカレント実行行を取得する

(7)ファイル操作(存在チェック・読込)

下記参考にさせて頂いています。

参考:Node.jsを使ったやっつけのファイル操作

(8)CSV操作

下記参考にさせて頂いています。

参考:Node.jsでCSVの読み込みや保存をする
参考:CSV Parser for Node.js

(9)ランダムソート

下記参考にさせて頂いています。

参考:配列の要素の並びをシャッフルする

(10)スペースパディング

下記参考にさせて頂いています。

参考:Javascript で簡単にゼロ埋めやスペース埋めする関数

(11)環境変数の代わりに .env ファイルを使用する

heroku上ではなく、ローカルPC上で試しに動かす場合、環境変数の代わりに.envファイルを使用する方法が便利です。

参考:環境変数の代わりに .env ファイルを使用する (dotenv) - まくまくNode.jsノート

(12)herokuのプロセスタイプについて

herokuのプロセスタイプには、web、woker、clockの3種類があります。
今回はWEBサイトは稼働させないので、下記再掲記事の通り、workerプロセスで実行させています。

再掲:【初めての個人開発】FlaskアプリとTwitterの自動返信BotをHerokuにデプロイした話

その他、プロセスタイプの使い分け等については下記参照。
参考:Worker dyno、バックグラウンドジョブ、キューイング
参考:プロセスモデル

(13)エラー処理

下記参考にさせて頂いています。

参考:【JavaScript】エラー処理 完全ガイド

(14)非同期処理

ここもなかなか想定通りにいかず、色々試行錯誤しました。
下記サイトを始め色々な記事を拝見しましたが、まだ理解しきれていません。
このあたりの理解が不足しているせいで、何度か全体的な修正を行うこととなってしまいました。
最終的にやりたいことはできるようになりましたが、めちゃくちゃな実装になっている気がしてなりません…

参考:async.js で非同期処理のフロー制御を行う (3) 複数の非同期処理を指定した順に実行する (async.series, async.waterfall) - まくまくNode.jsノート
参考:async/await 入門(JavaScript)
参考:【JavaScript】 async/await で非同期処理をわかりやすく記述する
参考:JavaScriptの非同期処理を理解する その1 〜コールバック編〜
参考:node.jsがやたら非同期化しようとするのをasync/awaitでどうにか同期化する

7.テスト

103ケース実施し、6件の不具合を検出しました。

(1)ケース作成

ケースは設計書から洗い出して作成しています(計103ケース)。
フォーマットは以下のような形式です。下記画像は抜粋なので、全量は前述のアップロード版をご覧下さい。
image.png

(2)テスト実施

①テスト環境

テストは基本的にはローカルPCの検証環境で実施していますが、一部heroku本番環境で実施しています(Papertrailのメールアラート確認)。

②テスト方法

・定期実行処理
ローカルPCのシステム時刻を変更して実施しています。

・エラー処理
途中まで正常に通して、途中でエラーにしたい場合が結構あります。
その場合は、デバッグで一時停止して、その間にデータを入れ替えたり通信を切断/接続してエラーを発生させました。

参考:Node.js デバッガの基本的な使い方
参考:初心者向けにNode.jsのデバッグ(debug)手法を徹底解説
参考:Debugger - Node.js v16.6.0 Documentation

・Papertrailのメールアラート確認
例外的にheroku本番環境でテストを実施しています。

参考:Herokuにログ管理ツール「papertrail」を導入&利用してみる - vdeep

③エビデンス

サンプルを記載します。
・コンソールログ

・Twitterツイートのスクショ
image.png

・Papertrailメール通知

(3)不具合対応

以下6件の不具合を検出しました。
image.png

つまらないものから致命的なものまであったのですが、特にNo.5が致命的で、全体的な見直しを余儀なくされました。スレッド形式のツイートは当初3秒スリープを入れて次のツイートを実行させていたのですが、稀に追い越しが発生することがあり、前のツイートの完了を待ち、且つ、念のため3秒スリープを入れるように改修しました。

(4)不具合分析

簡単に分析してみました(IPAの結合テストの指標を適用しています。やり方があっているのかいまいち不安ですが…)。
品質としては、中の下といった所でしょうか。
評価としては「前工程の品質確保不足、内容点検」ということですが、詳細設計・単体テストは実施していないので、それはその通りだと思います…

image.png

参考:テスト密度、バグ密度計算
参考:「ソフトウェア開発データ白書 2018-2019」のご紹介
参考:ソフトウェア開発データ白書と定量データの活用方法
参考:メトリクスについての学習 (ゾーン分析)

8.運用

①死活監視

herokuのdyno再起動の度に下記のようなリプライが管理用アカウントに飛んできます。
herokuが問題なく稼働していることが確認できます。
image.png

②エラー監視

Stream切断エラーが稀に発生する位で、その他のエラーは今のところ発生していません。
image.png

③アラート監視

重大なエラーが発生した際にはPapertrailからメールでアラート発砲させる設定にしていますが、今のところ発動したことはありません。

④ログ監視

Papertrailのログはこんな感じです。
Streamエラーが頻発した時にたまに確認する位で、あまり見ることはありません。
image.png

9.所感

(1)好きな物を自由に作るのは楽しい

このbotを作るのは、とても楽しい時間でした。
久しぶりに童心に返り、時間を忘れて夢中になっていた気がします。
会社の業務での開発はスケジュールとか何をどうするとか周りと色々調整しないといけないので、今回のように全部自分の好きに作れるというのは、やはり普段の開発とは違った面白さがありました。

また、普段は汎用機でPL/1やC言語で開発しているので、herokuでNode.jsで~というのはとても新鮮で普段と違う感覚で楽しかったですね。

開発手法は普段なじみ深いウォーターフォールモデルでやっていますが、アプリ開発はアジャイルとかもっと違ったやり方もあるのかなと思ったり…

(2)検索すれば大体何とかなるけど…

基本的にGoogle検索で何とかなるのですが、何とかならなかった時は色々と試行錯誤してなんとかしました。
その試行錯誤のプロセスは楽しいものがあるのですが、本当は書籍等で体系的に理解した上で実装に取り組んだ方が効率的なんだろうと思います(非同期処理とか非同期処理とか…)。
ので、体系的な学習は今後進めていきたいと思います。

(3)個人で開発することについて

①楽しい部分

全部自分の好きにできるのが楽しいです。
また、問題に直面したときに自力でなんとかするしかないので、解決できたときの喜びも大きいです。

②辛い部分

レビュアがいないのがとにかく辛いです。
この実装で正しいのか?もっと効率的な実装はないのか?設計に考慮不足な点はないか?テストケースに漏れはないか?などなど…不安はつきません。

その点、会社の業務なら全ての工程にレビューが入るので、安心感があります。
フリーランスで個人でやってる方とかって、その辺どうされているんでしょうか…

10.おわり

拙い記事ですが、この記事が何かの参考になれば幸いです。
また、設計書やソースをご覧になった方で、不具合や考慮不足な点に気付かれましたら、ご指摘頂けますと大変助かります。

以上、宜しくお願い致します。

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
What you can do with signing up
2