[discordgo] Snowflake ID からメッセージ作成日時を逆算する
はじめに
discordgo でメッセージを取得した際に Timestamp を使わず、ID を SnowflakeTimestamp() に渡してタイムスタンプを取得したほうがいいかもしれないね、という話です。
ある bot の実装を行っているとき、「指定した日時のメッセージをすべて取得する」という処理を実装する必要がありました。メッセージの取得は discordgo.Session.ChannelMessages() を使うことができますが、これは指定した2つのメッセージID間のメッセージを取得する機能しかなく、指定した日付のメッセージかどうかを確認する処理は別に実装する必要がありました。
discordgo.Session.ChannelMessages() が返す Message 構造体には Timestamp フィールドが含まれており、一見するとこれをそのまま使えばいいように見えました...が、公式ドキュメントを確認したところこれは推奨されないようです。
// The time at which the messsage was sent.
// CAUTION: this field may be removed in a
// future API version; it is safer to calculate
// the creation time via the ID.
Timestamp time.Time `json:"timestamp"`
意訳すると「このフィールドはいつか消すから、代わりにIDから逆算してな」ということらしいです。
「IDから逆算する」とはなんでしょうか?
Snowflake ID
調べたところ、discord の ID 採番は Snowflake ID という採番形態をとっているみたいでした。
「雪片はすべて固有の構造を持っていると信じられている」ことに由来する名前で、ID内に生成時刻を含むのが特徴みたいです。ここから逆算しろってことみたいですね。
やってみる
便利なことに、discordgo には Snowflake ID から作成時刻を取り出す関数 SnowflakeTimestamp があります。
使うときは ID をそのまま突っ込むだけで大丈夫です。time.Time 型でタイムスタンプが返されます。
// discord Snowflake ID からメッセージの作成時間を逆算
ts, err := discordgo.SnowflakeTimestamp(msg.ID)
if err != nil {
ts = m.Timestamp
}
Discussion