Discord bot can't use @

An error occurs when I ask the bot to say @{username}

Here is the source code:

import discord as Discord
from rich.console import Console

# start init
BotTOKEN = <has been hidden>

MessageTable = {
	"hi":  "hi"
}

#------------------------------------------------------------------------ init start
Console = Console()

Console.log("initializing...")

DiscordIntents = Discord.Intents.default()
DiscordIntents.members = True
Bot = Discord.Client(intents=DiscordIntents)
#------------------------------------------------------------------------init end

#------------------------------------------------------------------------function start
async def SendMessage(Message, User=-1):
	Text = ""

	if User != -1:
		Text += "<@{}>".format(str(Message.author.id))

	Text += Message

	Message.channel.send(Text)

	Console.log("Message Send: %s" % Message)

def ToText(Content):
	return Content.replace("<@" + str(Bot.user.id) + ">", "", 1)[1:]
#------------------------------------------------------------------------function end

#------------------------------------------------------------------------core function start
async def OnBotInit():
	Console.log("Running:\nUser Name: %s\nUser ID: %s" % (Bot.user.name, Bot.user.id))

async def OnMessage(Message): #Called when the user sends a message
	if Message.author == Bot.user:
		return

	if Message.content.startswith("<@" + str(Bot.user.id) + ">"):
		Text = ToText(Message.content)

		Find = False
		for i in MessageTable:
			if i == Text:
				Find = True

		if Find:
			await SendMessage(MessageTable[Message.content], User=Message.author.id)
#------------------------------------------------------------------------core function end

#------------------------------------------------------------------------main start
def Main(): #main
	@Bot.event
	async def on_ready():
		await OnBotInit()

	@Bot.event
	async def on_message(Message):
		await OnMessage(Message)

	Bot.run(BotTOKEN)

if __name__ == '__main__':
	Main()
#------------------------------------------------------------------------main end

This is the error content:

[13:24:01] initializing...
[2022-08-19 13:24:01] [INFO    ] discord.client: logging in using static token
[2022-08-19 13:24:03] [INFO    ] discord.gateway: Shard ID None has connected to Gateway (Session ID: 91c5fa6fd2ce064425e89cdc7783576c).
[13:24:05] Running:
           User Name: wsyong13
           User ID: 1009822123008741386
[2022-08-19 13:24:12] [ERROR   ] discord.client: Ignoring exception in on_message
Traceback (most recent call last):
  File "C:\Users\%UserName%\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\client.py", line 409, in _run_event
    await coro(*args, **kwargs)
  File "C:\Users\%UserName%\Desktop\DiscordBot.py", line 66, in on_message
    await OnMessage(Message)
  File "C:\Users\%UserName%\Desktop\DiscordBot.py", line 55, in OnMessage
    await SendMessage(MessageTable[Message.content], User=Message.author.id)
KeyError: '<@1009822123008741386> hi

How to solve?

Hi there!

After looking at your code, this is what I think you are trying to do:

  • Wait for a message
  • Check if that message is something that is stored in the MessageTable (I assume that the MessageTable would supply a response to a given message)
  • If so, then ping the user who sent the original message with the corresponding response.

In await SendMessage, you set the message argument as MessageTable[Message.content].

The thing is, while the variable Text is a string containing Message.content but with the “@” ping removed (that you used to check if you have a response stored in MessageTable), MessageTable[Message.content] is trying to retrieve a response to the original message, including the “@” ping.

In other words, instead of getting the response to “hi” (which is what you want to do), you are trying to get the response to “<@1009822123008741386> hi” (which your code doesn’t know how to respond to).

The solution:
Instead of
await SendMessage(MessageTable[Message.content], User=Message.author.id)
,
await SendMessage(MessageTable[Text], User=Message.author.id)
will work instead.

Also, I noticed you were using a for loop to check if Text has a corresponding response in MessageTable. An easier way to write this code is to change

Find = False
		for i in MessageTable:
			if i == Text:
				Find = True

		if Find:

to

if Text in MessageTable.keys():

Feel free to message me if you have any more questions.

Cheers!