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)
}
});
モバイルステータスって?
実はこれ、スマホだとモバイルとして表示されないんですよね。なぜでしょう…?
技術的な内容
実はこれは、接続元デバイスから判定しており、その情報はDiscord Gatewayに接続する際1、identifyに自己申告する形で含まれています2。
そのため、identifyを変更すればよいわけです。要は User-Agent 書き換えのようなものですね。
本題
v13まで
v133までは Client
のコンストラクタに指定するオプションで指定できていました。
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 本体どちらにも WebSocketManager
・WebSocketShard
が存在するので、5今回は前者を WSWebSocketManager
・WSWebSocketShard
と呼称します。
今回は TypeScript で動作する環境で Client
オブジェクトのコンストラクタのオプションのみで、identify オブジェクトを変更することが目的です。
コールツリー
- コード6を読むと、実際に送信される
properties
は<WSWebSocketShard>.strategy.options.identifyProperties
を参照しています7。 -
<WSWebSocketShard>.strategy
については、IContextFetchingStrategy
が使用されています8。この変数は、コンストラクタによって代入されています9。 -
WSWebSocketShard
は、<SimpleShardingStrategy>.spawn
にて生成されています10。 - この
SimpleShardingStrategy
は、<WSWebSocketManager>.strategy
に存在しています11。以後、型はIShardingStrategy
となります。 -
<WSWebSocketManager>.strategy
は、<WSWebSocketManager>.options.buildStrategy
関数によって生成されています12。 -
<WSWebSocketManager>.options
は、デフォルトが指定されているもののoptions
で上書きされています13。 -
WSWebSocketManager
は、<WebSocketManager>.connect
にて生成されています。 -
wsOptions.buildStrategy
は、ws.buildStrategy
を参照しています14。 -
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 信者なので、一番使いやすいライブラリではあるんですが、なんか絶妙な使いたくなさがありますね。
-
https://discord.com/developers/docs/topics/gateway#connection-lifecycle ↩
-
https://discord.com/developers/docs/topics/gateway-events#identify-identify-connection-properties ↩ ↩2
-
不明瞭な情報です。古いコード記載されていたのはこの方式で、その時のDiscord.jsのバージョンがv13だった記憶があるからです。よく調べてません、今使えないものは使えないんで。 ↩
-
2時間かかりました。 ↩
-
お前、嘘だろ…ネーミングセンス………… ↩
-
https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/ws/src/ws/WebSocketShard.ts#L460 ↩
-
https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/ws/src/ws/WebSocketShard.ts#L446 ↩
-
https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/ws/src/ws/WebSocketShard.ts#L117 ↩
-
https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/ws/src/ws/WebSocketShard.ts#L129 ↩
-
https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/ws/src/strategies/sharding/SimpleShardingStrategy.ts#L29 ↩
-
https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/ws/src/ws/WebSocketManager.ts ↩
-
https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/ws/src/ws/WebSocketManager.ts#L231 ↩
-
https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/ws/src/ws/WebSocketManager.ts#L230 ↩
-
https://github.com/discordjs/discord.js/blob/bfc7bb55641c60d4d67e57c27c9d1e63b6f30c9b/packages/discord.js/src/client/websocket/WebSocketManager.js#L159 ↩