ツイッターbotから投稿するツイートの順序を、ランダムに入れ替えます。
ツイッターbotには、登録したツイートをランダムに投稿できるものがあります。しかしツイートがランダムに選ばれると、以下のような状況が発生します。
- あるツイートは短期間に繰り返し投稿される
- あるツイートいつまで経っても投稿されない
- 最近思いついたネタをすぐに投稿する方法がない
そこでこのようなスクリプトを作って、上記の問題を解決することにしました。
- それぞれのツイートは、全ツイートが一周するまでに、一回ずつ投稿される。全ツイートが一周しそうになったら、全ツイートを一括ダウンロードしてから、本スクリプトでツイート順序を並べ替えてアップロードする。
- 最近思いついたネタをすぐ投稿できる。Botサービスで、まもなく投稿されるネタを最近思いついたネタで上書きし、上書きされたネタを最後に追加する。
一行一ツイートです。改行などはbotサービスごとに指定される形式でエスケープされているものとします。文字エンコーディングは、UTF-8.jpのみ受け付けます。
入力の行をランダムに入れ替えたものを出力します。それぞれの行の内容は変更しません。
まずお試しとして、以下の通り実行すると、 cppFriendsBot.txt の各行を入れ替えたものが標準出力に出力されます。
ruby -Ku shuffleLines.rb -i cppFriendsBot.txt
オプションは下表の通りです。オプションの値は、オプションに続けて-i input.txt
または--input=input.txt
のように書きます。オプションの値の、先頭および末尾にある空白は取り除きます。
オプション | 意味 | 省略値 |
---|---|---|
-i, --input | 入力ファイル名 | 標準入力 |
-o, --output | 出力ファイル名 | 標準出力 |
-p, --phrase | 最後のツイートに含まれる文字列 | 指定しない |
-c, --[no-]check | ツイートを検査する | 検査しない |
以下を実行すると、input.txtの内容を変換して、output.txtに出力します。
ruby -Ku shuffleLines.rb -i input.txt -o output.txt
--phrase=stringオプションをつけると、string が最後に含まれる行とそれより前の行を、string が最後に含まれる行より後ろにある行よりも、後に出力します。後述のように、ツイートが一周する前に順番を入れ替えるために用います。空白を含むオプションの値をシェルから渡すときは、""で囲ってください。
ruby -Ku shuffleLines.rb -i input.txt -o output.txt -p "わ-い たーのしー"
--checkオプションをつけると、ツイートを検査して、指摘事項を標準エラー出力に書き出します。--checkオプションが無い場合および--no-checkオプションを指定した場合は指摘しません。指摘事項は後述します。
WindowsコマンドプロンプトからActiveScriptRubyを使って実行するときは、あらかじめコードページをUTF-8に変更する必要があります。
chcp 65001
本スクリプトは入力した行をランダムに入れ替えますが、以下の規則に従います。ツイートを並べ替える目的で作りましたのでツイートと記しますが、ツイート以外の任意のUTF-8.jp文字列にも適用可能です。
既に述べた通り、ツイートの順序を入れ替えるのは、全ツイートが一周する直前です。そこであるツイートより後にあるツイートは未投稿とみなして前に出力し、それ以外の(投稿済みの)ツイートをその後に出力します。
例として、本レポジトリにあるshuffleLinesSample.txtを用います。このファイルには{1,2,3,4,5,a,b,c,d,e}と、各行に先頭から順に記述しています。ここで最後のツイートが5だとします。このとき、はじめに未投稿のツイート=a..eをランダムに選んで出力し、その後に投稿済のツイート=1..5をランダムに選んで出力するには、以下の通り実行します。
ruby -Ku shuffleLines.rb -i shuffleLinesSample.txt -p 5
結果は毎回変わりますが、必ず英字が前に続き、その後に数字が続きます。
この機能を有効にするためには、-pオプションを用います。-pオプションで与える文字列を最初に含む行を、最後の投稿とみなします。最後の投稿以外のツイートに一致しないよう、-pオプションで与える文字列は、改行を除いたツイート全文にするなど十分長くしてください。例えばwcコマンドで調べるとよいでしょう。
# int3を指定したつもりが、int32が混じっている
$ grep int3 cppFriendsBot.txt
わざとint3を踏んで...
uint32_t = 1を一度に35回シフトして...
uint32_tとかuint64_tとか...
$ grep int3 cppFriendsBot.txt | wc
3 15 736
-pオプションを指定しない場合は、全ツイートをランダムに入れ替えます。
具体的には、「やめるのだフェネック」で始まるツイート、「けものフレンズ」を含むツイート、それ以外のツイートが、できるだけ交互に出現するようにします。現在は「やめるのだフェネック」で始まるツイートが過半数を占めていますので、「やめるのだフェネック」で始まるツイートが連続することがありますが、それ以外のツイートが連続することは少なくなるようにします。
上記以外の分類を用いる場合は、本スクリプトの LINE_PATTERN_SET 変数に、順に適用する正規表現を設定してください。
-cまたは--checkオプションをつけると、ツイートを検査して、指摘事項を標準エラー出力に書き出します。このオプションの有無によって、出力されるツイートが変わることはありません。指摘内容が的外れであれば、単に無視してかまいません。指摘内容は以下の通りです。
おそらく他のツイッターユーザに、何かを1回だけ伝えてたくてbotにツイートを登録したのでしょう。もう一度伝えたいのでなければ、そのツイートは削除したいのだと思います。
メンションとして扱う文字列は、@の後に英数字またはアンダーバー(_)が並び、前後が空白、行頭または行末の文字列です。
あるハッシュタグが流行ったのでツイートしたが、次回botで投稿する頃には旬を過ぎていることがあります。そのようなツイートを見つけるために、未登録のハッシュタグを列挙します。今後も使い続けそうなハッシュタグは、スクリプトの変数 HASHTAG_SET に追加してください。C++プリプロセッサ指令(#include)はハッシュタグと誤認されるので、適宜追加してください。
入力ストリームに含まれるハッシュタグ一覧は、以下のシェルコマンドから作ることができます。
$ cat cppFriendsBot.txt | tr "\\r " "\\n" | egrep -o "#\\S+" | sort | uniq
正常終了時は、終了ステータス0で終了します。それ以外の場合は、0以外の終了ステータスで終了します。例えば以下のような場合に終了します。異常系は作り込んでいませんので、明示的に例外を投げる場合以外にも、Ruby処理系が例外を投げて終了することがあります。
- 指定したファイルを開けなかった
- 入力ファイルと出力ファイルが同じだった
- 入力に解釈できない文字があった。入力がShift_JISだった場合もエラーになります。
- -pオプションで与えた文字列を含むツイートが見つからなかった
以下を実行すると、結果を報告します。実行には本レポジトリにある、先の例で用いたcppFriendsBot.txtとshuffleLinesSample.txtが必要です。cppFriendsBot.txtは、私が自動投稿しているTwitterアカウントの原稿です。
ruby -Ku shuffleLinesTest.rb
本レポジトリのREADME.mdに記載の通りです。