Discord API "soft-ban" for Selfbot? It can only read its own messages

Viewed 10390

So today, all of a sudden, my Discord Selfbot stopped working. It has been running for weeks without any issue. All it does is monitoring the bot alerts from other channels and notify me if certain conditions are met.

Basically the problem is that when I print(message.content) I get empty string, and when I print(message.embeds) I get an empty list. This happens for any message that isn't sent by myself. Basically I can pull any message from any channel, but if it's not sent by me, I will see it empty. I can still print(message) and see its ID, author, etc., but can't retrieve the content/embeds.

I thought it was some sort of soft-ban from the Discord API (account didn't receive any warning and works normally), but then tryed to make a new account and got the same issue. I'm so confused and can't find out what's the cause of the problem... Unless they changed the API for everyone.

4 Answers

I've been playing with this for the past few weeks, and using tips and ideas all over the internet, I created a patched version of Discord.py for self-bots.

It seems that you need to do couple of things to get message.content & message.embeds working again:

  • Disable all Intents
  • Edit the IDENTIFY packet sent to Discord

My fork does all that, as well as obfuscate the user-agent and a few other things.

Check the README for things changed + credits.

Link: GitHub, PyPi

The answer to everyone's question:

On April 30th, 2021 discord made some change that broke receiving message content and embeds (and maybe more) on selfbots only. If you have this issue, then you're using a selfbot, which is against the discord TOS... it is also deprecated by discord.py since version 1.7 and won't receive support. You need to change to a real bot if you want support

Turns out actually it doesn't work for me too, I thought it worked because I didn't test it before, and only used history or myself as the user.

A workaround is to use channel.history instead which returns messages that support .content and similar.

With possibly something similar to this

@bot.event
async def on_message(message):
    async for message in message.channel.history(limit=1):
        print(message.content)

I also tried (badly) making discord.py always get it from history, and this seems to work for me. (For v1.x)

From cbbd51bf17bb19ea4835365e08266d06a27c1459 Mon Sep 17 00:00:00 2001
From: Example User <user@example.com>
Date: Fri, 7 May 2021 13:37:50 +0300
Subject: [PATCH] add workaround for on_message on self bots

Recently, now the messages that self bots get in events are broken.
In the case of on_message, .content and .embeds don't work.

However, this isn't the case if the message is retrieved with
channel.history()

This workarounds the issue for on_message by retrieving it from history
always

NOTE: I made the parse call async, didnt seem to break anything (yet)
---
 discord/gateway.py | 6 +++++-
 discord/state.py   | 9 ++++++++-
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/discord/gateway.py b/discord/gateway.py
index 210a8822..019693db 100644
--- a/discord/gateway.py
+++ b/discord/gateway.py
@@ -30,6 +30,7 @@ import concurrent.futures
 import json
 import logging
 import struct
+import inspect
 import sys
 import time
 import threading
@@ -506,7 +507,10 @@ class DiscordWebSocket:
         except KeyError:
             log.debug('Unknown event %s.', event)
         else:
-            func(data)
+            if inspect.iscoroutinefunction(func):
+                await func(data)
+            else:
+                func(data)
 
         # remove the dispatched listeners
         removed = []
diff --git a/discord/state.py b/discord/state.py
index da1212c1..7c713e39 100644
--- a/discord/state.py
+++ b/discord/state.py
@@ -485,9 +485,16 @@ class ConnectionState:
     def parse_resumed(self, data):
         self.dispatch('resumed')
 
-    def parse_message_create(self, data):
+    async def parse_message_create(self, data):
         channel, _ = self._get_guild_channel(data)
         message = Message(channel=channel, data=data, state=self)
+        # This is a workaround for messages not working on self bots
+        async for temp_msg in message.channel.history(limit=1):
+            if temp_msg.id != message.id:
+                log.warning("retrieved on_message from history is not correct one")
+                break
+            
+            message = temp_msg
         self.dispatch('message', message)
         if self._messages is not None:
             self._messages.append(message)
-- 
2.30.2

EDIT: see someone elses answer now instead

Edit the gateway.py source from the discord library and find the line:

if state._intents is not None:
     payload['d']['intents'] = state._intents.value

and change it to:

if state._intents is not None and self._connection.is_bot == True:
     payload['d']['intents'] = state._intents.value

Make sure to include "bot=False" option when calling the client.run. Having an intents option when sending the IDENTIFY payload causes user accounts to not receive message content, no matter what you set the intent value to. I hate doing this, but editing the library source to remove including the intents for non bot users is the only way I can find so you can use discord.py with a user account to view message content. The intents option is however required to be used for bot accounts.

Related