显然,discord 机器人可以具有移动状态,而不是默认获得的桌面(在线)状态。
经过一番挖掘后,我发现这种状态是通过修改IDENTIFY packet
in discord.gateway.DiscordWebSocket.identify https://github.com/Rapptz/discord.py/blob/45d498c1b76deaf3b394d17ccf56112fa691d160/discord/gateway.py#L370修改值$browser
to Discord Android
or Discord iOS
理论上应该让我们获得移动状态。
修改我在网上找到的执行此操作的代码片段后,我最终得到以下结果:
def get_mobile():
"""
The Gateway's IDENTIFY packet contains a properties field, containing $os, $browser and $device fields.
Discord uses that information to know when your phone client and only your phone client has connected to Discord,
from there they send the extended presence object.
The exact field that is checked is the $browser field. If it's set to Discord Android on desktop,
the mobile indicator is is triggered by the desktop client. If it's set to Discord Client on mobile,
the mobile indicator is not triggered by the mobile client.
The specific values for the $os, $browser, and $device fields are can change from time to time.
"""
import ast
import inspect
import re
import discord
def source(o):
s = inspect.getsource(o).split("\n")
indent = len(s[0]) - len(s[0].lstrip())
return "\n".join(i[indent:] for i in s)
source_ = source(discord.gateway.DiscordWebSocket.identify)
patched = re.sub(
r'([\'"]\$browser[\'"]:\s?[\'"]).+([\'"])',
r"\1Discord Android\2",
source_,
)
loc = {}
exec(compile(ast.parse(patched), "<string>", "exec"), discord.gateway.__dict__, loc)
return loc["identify"]
现在剩下要做的就是覆盖discord.gateway.DiscordWebSocket.identify
在主文件的运行时,类似这样的内容:
import discord
import os
from discord.ext import commands
import mobile_status
discord.gateway.DiscordWebSocket.identify = mobile_status.get_mobile()
bot = commands.Bot(command_prefix="?")
@bot.event
async def on_ready():
print(f"Sucessfully logged in as {bot.user}")
bot.run(os.getenv("DISCORD_TOKEN"))
And we do get the mobile status successfully
![successful mobile status for bot](https://i.stack.imgur.com/RQ54p.png)
但这是问题所在,我想直接修改该文件(包含该函数),而不是在运行时对其进行猴子修补。所以我在本地克隆了 dpy lib 并在我的机器上编辑了该文件,它最终看起来像这样:
async def identify(self):
"""Sends the IDENTIFY packet."""
payload = {
'op': self.IDENTIFY,
'd': {
'token': self.token,
'properties': {
'$os': sys.platform,
'$browser': 'Discord Android',
'$device': 'Discord Android',
'$referrer': '',
'$referring_domain': ''
},
'compress': True,
'large_threshold': 250,
'v': 3
}
}
# ...
(编辑了两者$browser
and $device
to Discord Android
只是为了安全起见)
但这不起作用,只是给了我常规的桌面在线图标。
所以我接下来要做的就是检查identify
功能after它已经被猴子修补了,所以我可以查看源代码,看看之前出了什么问题,但由于运气不好,我得到了这个错误:
Traceback (most recent call last):
File "c:\Users\Achxy\Desktop\fresh\file.py", line 8, in <module>
print(inspect.getsource(discord.gateway.DiscordWebSocket.identify))
File "C:\Users\Achxy\AppData\Local\Programs\Python\Python39\lib\inspect.py", line 1024, in getsource
lines, lnum = getsourcelines(object)
File "C:\Users\Achxy\AppData\Local\Programs\Python\Python39\lib\inspect.py", line 1006, in getsourcelines
lines, lnum = findsource(object)
File "C:\Users\Achxy\AppData\Local\Programs\Python\Python39\lib\inspect.py", line 835, in findsource
raise OSError('could not get source code')
OSError: could not get source code
Code :
import discord
import os
from discord.ext import commands
import mobile_status
import inspect
discord.gateway.DiscordWebSocket.identify = mobile_status.get_mobile()
print(inspect.getsource(discord.gateway.DiscordWebSocket.identify))
bot = commands.Bot(command_prefix="?")
@bot.event
async def on_ready():
print(f"Sucessfully logged in as {bot.user}")
bot.run(os.getenv("DISCORD_TOKEN"))
由于每个修补函数都表现出相同的行为(上述函数和loc["identify"]
)我无法再使用inspect.getsource(...)
然后依靠dis.dis
这导致了更令人失望的结果
反汇编的数据看起来与猴子补丁的工作版本完全相同,因此尽管功能内容完全相同,但直接修改的版本根本无法工作。 (关于拆解数据)
备注:做Discord iOS
直接也不起作用,改变$device
到其他一些值,但保持$browser
不起作用,我已经尝试了所有组合,但没有一个起作用。
TL;DR:如何在运行时不对其进行猴子修补的情况下获取不和谐机器人的移动状态?