3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

記事投稿キャンペーン 「2024年!初アウトプットをしよう」

Discord.js v14 でステータスをモバイルにしたい!えっ、プロパティはなくなった…?

Last updated at Posted at 2024-01-29

TL; DR

2024年11月3日現在、この手法は使用可能です。

本記事のコードをコピーした記事に、バグを利用しているとの記述がありますが、バグや非推奨オプションではありません。

const client = new Discord.Client({
    ws: {
        buildStrategy: manager => new (class MobileSimpleShardingStrategy extends SimpleShardingStrategy {
            constructor(manager) {
                manager.options.identifyProperties = {
                    os: "ios",
                    device: "device",
                    browser: "Discord iOS"
                };
                super(manager);
            }
        })(manager)
    }
});

モバイルステータスって?

こういうやつ
image.png

実はこれ、スマホだとモバイルとして表示されないんですよね。なぜでしょう…?

技術的な内容

実はこれは、接続元デバイスから判定しており、その情報はDiscord Gatewayに接続する際1、identifyに自己申告する形で含まれています2

image.png

そのため、identifyを変更すればよいわけです。要は User-Agent 書き換えのようなものですね。

本題

v13まで

v133までは Client のコンストラクタに指定するオプションで指定できていました。

v13 時点での指定方法
const client = new Discord.Client({
    ws: {
        properties: { $browser: "Discord iOS" }
    }
});

しかし、いつからかこのオプションが削除され、変更できなくなりました。
また、直接的な関係はありませんが、Discord API v10においても $browser 短縮プロパティが削除されました2
そのため、この方法はレガシーな方法といえるでしょう。

v14では

しかし、v14ではそもそも Client のオプションの ws に関連する設定が見当たりません。

ではどうすればいいのかというと、ソースを読んでコールツリーを頭の中で生成し、抜け道を探します(力技)4

前提

Discord.js において、WebSocketに実際に接続する役割は @discordjs/ws というライブラリが担っています。このライブラリと、Discord.js 本体どちらにも WebSocketManagerWebSocketShard が存在するので、5今回は前者を WSWebSocketManagerWSWebSocketShard と呼称します。

今回は TypeScript で動作する環境で Client オブジェクトのコンストラクタのオプションのみで、identify オブジェクトを変更することが目的です。

コールツリー

  1. コード6を読むと、実際に送信される properties<WSWebSocketShard>.strategy.options.identifyProperties を参照しています7
  2. <WSWebSocketShard>.strategy については、 IContextFetchingStrategy が使用されています8。この変数は、コンストラクタによって代入されています9
  3. WSWebSocketShard は、<SimpleShardingStrategy>.spawn にて生成されています10
  4. この SimpleShardingStrategy は、<WSWebSocketManager>.strategy に存在しています11。以後、型は IShardingStrategy となります。
  5. <WSWebSocketManager>.strategy は、 <WSWebSocketManager>.options.buildStrategy 関数によって生成されています12
  6. <WSWebSocketManager>.options は、デフォルトが指定されているものの options で上書きされています13
  7. WSWebSocketManager は、 <WebSocketManager>.connect にて生成されています。
  8. wsOptions.buildStrategy は、 ws.buildStrategy を参照しています14
  9. ws は、 this.client.options を参照しています。この先は自明であると思いますが、 Client のコンストラクタに指定できるオプションが参照されています。

結論

つまり、Client のコンストラクタのオプションの、 ws.buildStrategy 関数にカスタムクラスを一枚挟んで、受け取る manager (WSWebSocketManager) の options を変更すればいいということです。

なお、TypeScript と言っておきながら manager は下記コードでは any 型です。@discordjs/ws をインポートして解決することはできますが、私はめんどくさいので any でつぶしています。ごめんね。

const client = new Discord.Client({
    ws: {
        buildStrategy: manager => new (class MobileSimpleShardingStrategy extends SimpleShardingStrategy {
            constructor(manager) {
                manager.options.identifyProperties = {
                    os: "ios",
                    device: "device",
                    browser: "Discord iOS"
                };
                super(manager);
            }
        })(manager)
    }
});

おわりに

Discord.js はドキュメントがふわふわしてたり分かれていたり互換性がなかったり…

TypeScript / JavaScript 信者なので、一番使いやすいライブラリではあるんですが、なんか絶妙な使いたくなさがありますね。

  1. https://discord.com/developers/docs/topics/gateway#connection-lifecycle

  2. https://discord.com/developers/docs/topics/gateway-events#identify-identify-connection-properties 2

  3. 不明瞭な情報です。古いコード記載されていたのはこの方式で、その時のDiscord.jsのバージョンがv13だった記憶があるからです。よく調べてません、今使えないものは使えないんで。

  4. 2時間かかりました。

  5. お前、嘘だろ…ネーミングセンス…………

  6. https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/ws/src/ws/WebSocketShard.ts#L460

  7. https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/ws/src/ws/WebSocketShard.ts#L446

  8. https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/ws/src/ws/WebSocketShard.ts#L117

  9. https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/ws/src/ws/WebSocketShard.ts#L129

  10. https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/ws/src/strategies/sharding/SimpleShardingStrategy.ts#L29

  11. https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/ws/src/ws/WebSocketManager.ts

  12. https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/ws/src/ws/WebSocketManager.ts#L231

  13. https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/ws/src/ws/WebSocketManager.ts#L230

  14. https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/discord.js/src/client/websocket/WebSocketManager.js#L159

3
1
0

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
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?