Discord.Net bot reply - contains word - c#

I have just started tinkering with discord.net for creating a bot. I have a very basic bot right now that already replies with my given response when I type the command text. So if I type, "Hello" it will reply with, "...world!"
However, what I want, is to have the bot reply with a canned response whenever a message contains a certain word at any point. So if a user types, "Well, hello there" it will still reply with, "...world!" even though the command word is in the middle of the message. I think I may be able to swing it with the .Contains() method, but I'm a little stuck.

private async Task OnMessageReceived(SocketMessage arg)
{
if (!(arg is SocketUserMessage message)) return;
if (message.Source != MessageSource.User) return;
string[] filters = { "hello" };
string content = message.Content;
bool contains = filters.Any(x => content.Split(" ").Any(y => y.Contains(x)));
if (contains)
{
var guild = _client.GetGuild((message.Channel as SocketGuildChannel).Guild.Id);
await message.Channel.SendMessageAsync($"{arg.Content} world!");
return;
}
}
This is the MessageReceived event that you can get from the DiscordSocketClient. Put this in your CommandHandler.

Related

How do I get a discord bot send a DM to someone I ping?

I'm fairly new coding and thought I'd take a shot at making a discord bot. So far it's been easy enough to follow and I've started to try to make commands for my bot. But I can't figure out how to get my bot to DM a person I ping ex. !warn #person (reason). I've tried looking it up and can't find out how.
[Command("warn")]
[RequireUserPermission(GuildPermission.KickMembers, ErrorMessage = "You don't have the persmission ''warn_member''!")]
public async Task WarnMember(IGuildUser user = null, [Remainder] string reason = null)
{
if (user == null)
{
await ReplyAsync("Please Specify A User"); return;
}
if (reason == null) reason = "Not Specified";
this is where I'm trying to send the DM but it sends it to the person who ran the command and not who I pinged
await Context.User.SendMessageAsync("You have been warned for " + reason);
var EmbedBuilder = new EmbedBuilder()
.WithDescription($":white_check_mark: {user.Mention} was warned\n**Reason **{reason}")
.WithFooter(footer =>
{
footer
.WithText("User Warn Log");
});
Embed embed = EmbedBuilder.Build();
await ReplyAsync(embed: embed);
}
Context.User always refers to the user who is executing the command. To send a message to the person mentioned in the command, you need to call the SendMessageAsync() function on your user argument.
await user.SendMessageAsync(...)
Keep in mind that users can have direct messages disabled for the server your bot is in, this could result in an exception.

botframework confirm dialog, send message as user

I have created a confirm dialog where the user can select yes/no
private async Task Confirm(IDialogContext context, IAwaitable<bool> result)
{
var res= await result;
await context.PostAsync(res? "Proceed" : "Ok then");
if (res) {
......
}
}
If the user selects Yes he will receive the message "Proceed"
At the same time (again if "res" is true), i want to send a
specific message to the bot without appearing in the conversation.
Is there a way to send a custom message back to the bot when user
press Yes?
You could try constructing a new activity using data stored in the context which you have access to in this method. I don't fully understand your scenario but it seems this may work for what you need.
var a = new Activity();
a.Conversation = context.Activity.Conversation;
a.Recipient = context.Activity.Recipient;
a.From = context.Activity.From;
a.Id = context.Activity.Id;
... //set whatever else you need set
a.Text = "Whatever you need the text to be";
//send or process the activity do what it is you are trying to accomplish
Edit: I think what you are actually looking for is Prompt.Confirm().

Discord C# User Join messages

I'm using Discord.Net in C#, making a bot. My bot works fantastic so far, but I want it to automatically assign users a specific role when they join a specific server. I've never actually learned any C#, only a bit of C++ so I know the basic Grammar. How would I go about this?
I'm assuming I would use UserJoined, but doing this heeds results telling me to use it before or after a += or -+ (Which I understand, but I don't understand it's usefullness in this given scenario)
You gave little information to work with but here is how to do it in all releases (so far):
This is IN the dependency map but below the "handlecommand", CommandHandleAsync or HandleCommandAsync:
client.UserJoined += AnnounceJoinedUser; //Hook into the UserJoined event of the client.
This is under the dependency map:
public async Task AnnounceJoinedUser(SocketGuildUser user) //Welcomes the new user
{
var channel = client.GetChannel(/*/TextChannelID/*/) as SocketTextChannel; // Gets the channel to send the message in
await channel.SendMessageAsync($"Welcome {user.mention} to {channel.Guild.Name}"); //Welcomes the new user
}
In case any of you wanted to send a message directly to the joining user
client.UserJoined += HandleUserJoinedAsync;
private async Task HandleUserJoinedAsync(SocketGuildUser gUser)
{
if (gUser.IsBot || gUser.IsWebhook) return;
var dmChannel = await gUser.GetOrCreateDMChannelAsync();
await dmChannel.SendMessageAsync("Witaj");
}
For all those who need an answer, in this period, I leave you this piece of code, just to send a message to a user's join, (1 line):
Client.UserJoined += join;
private async Task join(SocketGuildUser user)
{
await (user.Guild.DefaultChannel).SendMessageAsync("Text")
return;
}

How to get most recent update in Telegram Bot API

I am struggling on how to get the text of a message to my C#-console tool with a telegram bot. Here is a piece of that is supposed to just print all messages in the telegram channel
private async Task getTelegramMessage()
{
var bot = new Telegram.Bot.TelegramBotClient("token")
var updates = await bot.GetUpdatesAsync();
foreach (var update in updates)
{
Console.WriteLine("Bot: " + update.Message.Text);
}
}
the problem is that i always get all old updates. The maximum length of the array updates is 100. So after I sent 100 messages in the telegram channel, I would only have access to the first 100 messages and no access to the newest. How can I get access to the most recent update? Or can I somehow delete the message after my tool has processed it?
I have seen that the bot provides the Event OnUpdate but I couldnt figure out how to use it.
Thanks a lot for help on that issue.
According documentation, you can use offset -1 to get the last update.
Just put in mind all previous updates will forgotten.
getUpdates Docs
https://api.telegram.org/bot{TOKEN}/getUpdates?offset=-1
oh, I just figured it out. for the offset you have to set the ID returned in the update.
Notes
2. In order to avoid getting duplicate updates, recalculate offset after each server response.
Instead subscribe to the BotOnUpdateReceived event to handle the updates. In main.cs:
Bot.OnUpdate += BotOnUpdateReceived;
Bot.StartReceiving(Array.Empty<UpdateType>());
Console.WriteLine($"Start listening!!");
Console.ReadLine();
Bot.StopReceiving();
And handle the event:
private static async void BotOnUpdateReceived(object sender, UpdateEventArgs e)
{
var message = e.Update.Message;
if (message == null || message.Type != MessageType.Text) return;
var text = message.Text;
Console.WriteLine(text);
await Bot.SendTextMessageAsync(message.Chat.Id, "_Received Update._", ParseMode.Markdown);
}
The Offset is internally working in it and it also internally call GetUpdatesAsync().
From Here you can also get channel post via:
var message = e.Update.ChannelPost.Text; // For Text Messages
I hope it will Help!!

MS Bot Framework stuck sending messages in an infinite loop

My bot that uses MS Bot Framework is stuck sending messages to the user in an infinite loop, both on the facebook and emulator channels.
My bot has a "root" IDialog, kind of like a menu, that calls a few other IDialogs depending on the user's selection. The child dialogs are called in this way:
...
else if (response.Text == MainOptions[2])
{
await context.Forward(new InfoCounterDialog(), ChildDialogComplete,
response, CancellationToken.None);
}
...
response is an IMessageActivity sent by user;
ChildDialogComplete is a method that builds the main menu again and ends with these lines:
.
await context.PostAsync(restartPrompt);
context.Wait(MainScreenSelectionReceived);
All dialogs work fine except this one very short dialog, which causes an infinite loop - the bot keeps sending this message again and again until I stop the web app.
namespace XXXX
{
[Serializable]
public class InfoCounterDialog : IDialog
{
public async Task StartAsync(IDialogContext context)
{
var hourNow = DateTime.Now.Hour;
var openNow = "";
if (hourNow >= 7)
{
openNow = "It is open now and will close at midnight.";
}
else
{
openNow = "It is closed now and will open at 7:00";
}
var card = HeroCardUtils.CardWithImageAndMiscButtons(
"Our information counter can help!",
"It's located in Shop 081, Level 3 in Building 2. " + openNow,
"http://www.[image URL here].jpg",
new[] { "More Details" },
new[] { ActionTypes.OpenUrl },
new[] { "[webpage URL here]" }
);
await BotUtils.SendCardToChat(context, card);
context.Done(this);
}
}
}
If you're wondering what SendCardToChat does:
public async static Task SendCardToChat(IDialogContext context, HeroCard card)
{
var activity = context.MakeMessage();
activity.Attachments = HeroCardUtils.CardToAttachments(card);
await context.PostAsync(activity);
}
To recap:
I'm launching a dialog from another dialog using context.Forward()
The dialog is supposed to show a message to the user and immediately terminate without extra input from user
Instead, it keeps sending the "Our information counter can help!" message infinitely.
My best guess is that the child dialog somehow returns the user's initial message to the conversation, which triggers the same dialog again and again. But this shouldn't happen, the child IDialog shouldn't send anything to the conversation except the HeroCard I created.
Or maybe I'm looking in a wrong direction and Bot Framework just doesn't support IDialogs that do something and immediately terminate without a context.Wait()?
I found that there isn't much documentation on context.Done(R value) but its really important in controlling the flow of the dialog.
I'm guessing that context.Done(this) calls your Dialog again? have you tried
context.Done(true);
I'm finding it frustrating that there isn't a context.Done() method (no parameter) to tell the dialog that your finished.
Further to this, i've found that in this Microsoft Example they use
// within a HotelsDialog.cs
context.Done<object>(null);
This is possible because they call the dialog from a root dialog
// within RootDialog.cs
context.Call(new HotelsDialog(), this.ResumeAfterOptionDialog);

Categories