From 37ecac009df72b72200aacc3ecb41620b5f83872 Mon Sep 17 00:00:00 2001 From: holl0wstar Date: Mon, 25 Sep 2023 00:32:06 -0300 Subject: [PATCH] Add the ability to PATCH discord nicknames and roles. --- evennia/accounts/bots.py | 3 ++ evennia/commands/default/comms.py | 6 ++++ evennia/server/portal/discord.py | 57 +++++++++++++++++++++++++++++-- 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/evennia/accounts/bots.py b/evennia/accounts/bots.py index 0f5a2cbddd..6fae561d38 100644 --- a/evennia/accounts/bots.py +++ b/evennia/accounts/bots.py @@ -637,6 +637,9 @@ class DiscordBot(Bot): # send outputfunc channel(msg, discord channel) super().msg(channel=(strip_ansi(message.strip()), dc_chan)) + def change_nickname(self, new_nickname, guild_id, user_id, **kwargs): + super().msg(nickname=(new_nickname, guild_id, user_id)) + def direct_msg(self, message, sender, **kwargs): """ Called when the Discord bot receives a direct message on Discord. diff --git a/evennia/commands/default/comms.py b/evennia/commands/default/comms.py index 8a1762d784..63d83285f1 100644 --- a/evennia/commands/default/comms.py +++ b/evennia/commands/default/comms.py @@ -1942,6 +1942,7 @@ class CmdDiscord2Chan(COMMAND_DEFAULT_CLASS): "list", "remove", "start", + "nickname", ) locks = "cmd:serversetting(DISCORD_ENABLED) and pperm(Developer)" help_category = "Comms" @@ -1981,6 +1982,11 @@ class CmdDiscord2Chan(COMMAND_DEFAULT_CLASS): self.msg("Starting the Discord bot session.") return + if "nickname" in self.switches: + discord_bot.change_nickname("Test", 541788744471281700, 124523120668311552) + self.msg(f"Changed username") + return + if "guild" in self.switches: discord_bot.db.tag_guild = not discord_bot.db.tag_guild self.msg( diff --git a/evennia/server/portal/discord.py b/evennia/server/portal/discord.py index 38f387f04f..8126d8cd66 100644 --- a/evennia/server/portal/discord.py +++ b/evennia/server/portal/discord.py @@ -375,6 +375,39 @@ class DiscordClient(WebSocketClientProtocol, _BASE_SESSION_CLASS): d.addCallback(cbResponse) + def _patch_json(self, url, data, **kwargs): + """ + Post JSON data to a REST API endpoint + + Args: + url (str) - The API path which is being posted to + data (dict) - Content to be sent + """ + url = f"{DISCORD_API_BASE_URL}/{url}" + body = FileBodyProducer(BytesIO(json.dumps(data).encode("utf-8"))) + d = _AGENT.request( + b"PATCH", + url.encode("utf-8"), + Headers( + { + "User-Agent": [DISCORD_USER_AGENT], + "Authorization": [f"Bot {DISCORD_BOT_TOKEN}"], + "Content-Type": ["application/json"], + } + ), + body, + ) + + def cbResponse(response): + if response.code == 200: + d = readBody(response) + d.addCallback(self.post_response) + return d + elif should_retry(response.code): + delay(300, self._post_json, url, data, **kwargs) + + d.addCallback(cbResponse) + def post_response(self, body, **kwargs): """ Process the response from sending a POST request @@ -483,10 +516,30 @@ class DiscordClient(WebSocketClientProtocol, _BASE_SESSION_CLASS): """ - data = {"content": text} + data = {"nick": text} data.update(kwargs) self._post_json(f"channels/{channel_id}/messages", data) + def send_nickname(self, text, guild_id, user_id, **kwargs): + """ + Changes a user's nickname on a Discord server. + + Use with session.msg(nickname=(new_nickname, guild_id, user_id)) + """ + + data = {"nick": text} + self._patch_json(f"guilds/{guild_id}/members/{user_id}", data) + + def send_roles(self, current_roles, role, guild_id, user_id, **kwargs): + """ + Assign the user a role on a Discord server. + Use with session.msg(roles=(current_roles, role, guild_id, user_id)) + """ + + data = {"roles": current_roles.append(role)} + data.update(kwargs) + self._post_json(f"guilds/{guild_id}/members/{user_id}", data) + def send_default(self, *args, **kwargs): """ Ignore other outputfuncs @@ -552,4 +605,4 @@ class DiscordClient(WebSocketClientProtocol, _BASE_SESSION_CLASS): # send the data for any other action types on to the bot as-is for optional server-side handling keywords = {"type": action_type} keywords.update(data["d"]) - self.sessionhandler.data_in(self, bot_data_in=("", keywords)) + self.sessionhandler.data_in(self, bot_data_in=("", keywords)) \ No newline at end of file