discordで334rankerやりたくない?

アドベントカレンダー19日目

adventar.org

- はじめに -

ぼくはやりたくないですね。

334Rankerは深夜のツイッター早押し大会のことです。毎日午前の3時34分にBOTが"334"ツイートの時間を取得、集計し、ランキング形式で発表します。

他にも称号や階級制度等あるのですが今回の実装には関係がないので割愛、リンク張っておきます。
blog.ranker.page

 

- やること -

今回の実装では最低限の機能として、

・該当ツイート(メッセージ)が送信されたときにIDを取得し、GMTに変換したものを送信する、に

・Discord上で動作する

を加えた2つを満たした時点でゴールとしています。

 

- メッセージIDをGMTに変換 -

f:id:tetl4pot:20191218141910p:plain

上の画像はDiscordの公式リファレンスから引っ張ってきたものです。はじめにこれを参考にしつつメッセージIDから現在時刻を取り出す方法を解説していきます。

 

1. 125928847299117063

        ↓ 2進数に変換

2. 0000001001110001000001100101101011000001000*

        ↓ 上位42ビットを10進数に変換

3. 41944705796

        ↓ 1420070400000を加える

4. 1462015105796

        ↓ UNIX時間をUTCに変換

5. 2016/04/30 11:18:25;796

 

1. 最初の18桁の数字がメッセージIDになっています。これはDiscordのチャット右クリックして"IDをコピー"を選択するともらえるやつです。

2. DiscordはメッセージIDの生成方式にSnowflakeを採用しており、64ビットうち上位42ビットがタイムスタンプとなっています。そのため、IDを2進数に変換した後、下位22ビットを落とす必要があります。

3. タイプスタンプを10進数に変換したものです。

4. タイムスタンプはUNIX時間で記述されています。Discordサービス開始からUNIX時間のカウントアップが開始された1970年までの差分を足しています。たぶん。

5. 画像ではUTCに変換していますが、今回の実装では分までしか見ないので関係ありません。

 

つぎに1~5までのプロセスをC++で書きます。可能であれば後述する入出力の時に使う言語でコーディングしたほうが良いのですがぼくはPython無理なので。

ソースコード丸投げします。

gist.github.com

 

13, 14行目と57行目以降は次の章でお話しします。

pybind11以外はすべて標準ライブラリです。pybindはpipでインストールするためライブラリをそのままC++でインクルード出来ません。showコマンドでpybindの場所を探してインクルードパスに追加する必要があります。

Ubuntu 18.04では、

/usr/include/python3.6m
/home/ユーザー名/.local/include/python3.6m

でした。

 

- CPPファイルをPythonから呼び出す -

pybindを用いてC++Pythonのコードに組み込むことが出来ます、すごい。上記のCPPファイルをコンパイルすることでPythonからのimportが可能になります、すごい。

コンパイルはclangをインストールした上で、

$ clang++ -O3 -Wall -shared -std=c++14 -fPIC `python3 -m pybind11 --includes` ファイル名.cpp -o ライブラリ名`python3-config --extension-suffix`

を実行します。ここで警告が出ますが、スルーします(200IQ)。

.soファイルが生成されると、同階層のPYファイルにインポートしてC++で定義した関数を使用することが出来ます。

 

- 入出力 -

Discordのテキストチャンネルで該当ツイートを検知、ID取得を行い、結果を送信します。今回はpybindを使用するためDiscord.pyを使用しますがBOT入出力自体は他の言語でも動作します。ちょっと遊ぶだけなら環境構築が必要でないJSのがいいなと思いました。

例によってソース丸投げしますが、ほぼ写経。

gist.github.com

4行目の空文字列にBOTトークンを入れます。BOTの作り方はMusicBOT等と変わらないため割愛。

 

- 実行 -

実際にDiscord上で動かすとこんな感じになります。

56

0.0

373

→N時56分0.373秒

 

ほんとに最低限しか作っていないため無機質な感じですがそのうち表示の仕方やランキング機能も実装したいですね。

というか誰か作って。

github.com

 

- さいごに -

2000文字を超えてしまいました、単位が出ますね。ここまで読んでくださっている皆様ほんとうに大好きです。

 

- 参考 -

覚えているハンイで参考になったページ載せておきます、全然覚えていない。

discordapp.com

C++ で Unix time を扱う · GitHub

qiita.com

qiita.com

docs.microsoft.com

qiita.com