❔ Need help with discord command to toggle a task
So I'm trying to make a command that takes a user as an input and toggles a task that uses that user as an input parameter for the toggled task. So you do something like:
/ToggleTest user1
Then anytime user1 sends a message the bot will respond with "Test success"
Then you can do /ToggleTest user1 to toggle it off.
80 Replies
So basically you want each user to have their own
IsOwn
value - that can be done using a Dictionary or HashSet for example
What a dictionary does is map a certain key (what would identify a Discord user uniquely?) to a value (in your case, a boolean) - that way you can have multiple "variables" at onceEventually yes, but right now just trying to get it to work in general as I'm getting errors and I'm not sure how to solve them
Does your current code not send messages? 🤔
Getting 2 errors each on the Ifs:
The name 'e' does not exist in the current context
Cannot implicitly convert type 'System.Threading.Tasks.Task' to 'DSharpPlus.AsyncEvents.AsyncEventHandler<DSharpPlus.DiscordClient, DSharpPlus.EventArgs.MessageCreateEventArgs>'
Been looking at the discord.MessageCreated += async (s, e) => part in the "Your First Bot" in the DSharpPlus documentation and took that as a guide for something like this
Nope, because of the errors I can't run it, If I remove the _clientInstance.MessageCreated += TestMessage(user, e); and _clientInstance.MessageCreated -= TestMessage(user, e); then I can run it and get the messages that the toggle is on because there's no errors
I'll have to look into that library as I have never used it, brb
Here's the part I'm looking at:
https://dsharpplus.github.io/DSharpPlus/articles/basics/first_bot.html
Scroll down to bottom and you'll see the Finished Product part with the discord.MessageCreated += async (s, e) =>
From those docs, it looks like
MessageCreated
is an event handler - you use that to detect messages are coming
instead of adding a hook to that event handler every time the command is run, I'd suggest adding a hook once in your application and then using a variable to figure out if the user should be replied to or notSomething like this?
hmm, nope
here's the thing: your bot is always receiving Discord messages, adding a hook to MessageCreated only forwards them to your code instead of voiding
so there's pretty much no extra cost in always listening to Discord messages ^
I'm not sure how to do what you're suggesting
where do you create _clientInstance?
that's only created once, right?
At the top of the code yeah
right, but you're just assigning
client
to it
where do you create the instance that goes into client
?In my Bot.cs:
perfect :)
you're doing this here:
that tells your function
OnClientReady
that the bot is connected to Discord and ready for using
why not have the MessageCreated
hook added there aswell?
that way you're always getting Discord's messages to process yourself, and don't have to deal with adding or removing that hook when a command is runI'm not sure I understand what you mean here?
You want me to add Client.Ready += TestMessage; ?
Sorry, I know must be frustrating trying to help me
nah it's fine! :)
I just don't want to give you copy-pasteable code because that would most likely not teach anything 😂
Yeah that's fair
Client.Ready
is an event handler, when you use +=
you're adding a hook (a function that listens to events) to it - that's the same as saying "whenever this event happens, make sure my hook function is called"Also try to keep all code relating to a command inside the same class, Idk if it's good or bad practice but I feel like it's more organized
that's actually a pretty interesting topic in more advanced architectures xD
there's a big debate on how to divide code, and what you described is pretty close to what VSA (Vertical Slice Architecture) would suggest
I understand that part, I come from Python background only started playing around with C# like 2 days ago
I don't have an IDE with me at the moment so can you try switching
_clientInstance.MessageCreated += TestMessage(user, e);
to _clientInstance.MessageCreated += TestMessage;
?
same thing for -=
trying to go with your suggestion of having everything in the same file :pThis is what my first approach was but didn't work, will try again though
Yeah this was the error I was getting:
No overload for 'TestMessage' matches delegate 'AsyncEventHandler<DiscordClient, MessageCreateEventArgs>'
that error tells me the compiler wants
DiscordClient
as first parameterFrom reading it I thought it's because I didn't pass anything in as parameters so I tried adding them
but here you're asking for DiscordUser:
I don't know why though, I don't ask for a DiscordClient in my TestMessage Task
https://dsharpplus.github.io/DSharpPlus/api/DSharpPlus.DiscordClient.MessageCreated.html
those are the arguments actually being declared by DSharpPlus
your hook function has to match those, as there's no way to go from DiscordClient (what DSharpPlus passes) to DiscordUser (what your hook function is asking for)
So I need something like this?
_clientInstance.MessageCreated += TestMessage(_clientInstance, e);
Is this bad practice or something? I thought it was good because of being more modular 😅
if you write
TestMessage(_clientInstance, e)
you're calling TestMessage with those arguments, but you want the event handler to be calling the function instead 🤔
_clientInstance.MessageCreated += TestMessage;
would be the correct
with you changing TestMessage to
public async Task TestMessage(DiscordClient client, MessageCreateEventArgs e)
But how am I going to pass the user into the task to check against if I do that?
well, those arguments are what DSharpPlus' API sends so you don't have control over that
MessageCreateEventArgs
will contain the user that sent the message you're receiving the event ofThat's what I'm using to check against for the input user of the command though, I'll just end up checking against the same thing which will means it will always be true
I think you're misunderstanding how event handlers work 😅
they're defined in code somewhere and when triggered cause all listening hooks to be executed
if an event handler passes DiscordClient instead of DiscordUser, you have to accept DiscordClient - there's no way to force it to pass DiscordUser
you'll have the user that sent the message inside
MessageCreateEventArgs
, so what you can do is create another place to store if an user should be replied to or not - then compare those two
what I mean with this is DSharpPlus defines what the parameters in your function should be, not youSo there's no way for me to pass on the user variable in this code to the TestMessage Task?
public async Task Toggle(InteractionContext ctx, [Option("user", "Specified user")] DiscordUser user)
correct
you could actually create another lambda function to pass the user variable that way, but then you're doing the same thing as using a variable in the class
Sorry, I'm just so confused how there's no way for me to just pass on a variable to my function 😅
no worries :)
it's because in this case DSharpPlus is what will be calling your function, not you
that's why the arguments are defined by it and you can't have different ones 🤔
I think I understand this part now, but I still don't get how there isn't a simple way to pass it on to the function
Wait
I think I have something that Might work?
seems fun
This is what I did
looks pretty good :)
I declared a _user variable outside the command
made it equal to user when the command is executed
and that can be used by the TestMessage function without being a parameter of the function, not sure if it will work
that's what I was going for yep 😂
you can't change hook function arguments... so add variables to your class and use them inside it xD
I don't think that code will work the way you want it to yet, but that was some progress
Is my methodology good practice? cx
having everything needed to handle a feature inside the same code file? I honestly like it
Vertical Slice Architecture is all about that, but probably not worth for you researching it rn 😂
Then all I do is register the commands into this SlashRegistry commands which is then used by my Bot.cs, I thought it made it super easy to manage and very modular
yeah that's fine in my opinion
The bot doesn't respond lol, but yeah it's progress
should that check be inside the other
if
?
Whoops nope it should not
Thanks for catching that
can you add a
Console.WriteLine
call to your code to check if your Toggle function is being run?Wait nvm
Not getting any Console.Writelines
getting this error
This is where I've added them
hmmm... when doing
/toggletest
are you passing an user?
does Discord give you that option?Yeah
It does
perhaps your bot doesn't have the permission to send messages?
It does, it works with other commands
I gave it all intents and perms in the dev portal
alright I'll look into it then
Thank you very much
I'm thinking it might be to do with the client variable I have in the TestCommand class not being the same as the one in my Bot class
I didn't spot anything wrong with your code 🤔
from https://dsharpplus.github.io/DSharpPlus/articles/slash_commands.html
I don't think that would be the cause of the issue though, as the command shows in your Discord client
Here's the updated TestCommand:
And here's my Bot.cs:
silly thing... the docs always use
[SlashCommand]
with lowercase name - maybe that's a requirement?
can you try changing SlashCommand("ToggleTest"
to SlashCommand("toggletest"
?
Discord client is showing that command in lowercase tooDidn't work, I'd be super surprised if that was the case though
yeah me too lol
I think it's to do with this. 1st picture is from TestCommand, 2nd is from Bot.cs. I'm thinking the _clientInstance is being set to the Client variable in the Bot.cs like I thought it was
any reason why you create a blank config here?
Haven't gotten around to filling that out yet
doc doesn't pass that
so maybe passing it blank is not expected, idk though
My other slash commands have worked fine
yeah I'm not sure why your first Console.WriteLine isn't being hit 😅
I use Disnake for my bots and when developing slash commands I always add the guild ID as that updates a lot faster than no guild ID... doubt that's the issue here though
D#+ has the same thing in their docs https://dsharpplus.github.io/DSharpPlus/articles/slash_commands.html#setup
I just tried to do a try catch on it and it's not giving me anything either
I GOT IT WORKING
Now I need to figure out how I'm going to make it work for multiple users
Thank you so much for all your help
Was this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.