Discord.NET Adding Reactions to a SocketMessage - c#

I am using Discord.NET version 1.0.2 to clear things up
I have a MessageReceived Task in my Discord Bot application:
private async Task MessageReceived(SocketMessage message)
This task, as can already be deducted, runs every time a message is received in Discord to this bot. I am trying to figure out how to add a reaction to a message that the bot has received, however. Under SocketMessage there are no methods to add reactions to the message received. I looked online and found that RestUserMessage contains the method AddReactionAsync(IEmote, RequestOptions). I then casted Socket Message to a RestUserMessage as so
var rMessage = (RestUserMessage) await message.Channel.GetMessageAsync(message.Id);
Running the AddReactionAsync method under my variable rMessage for RestUserMessage works, but the parameters are not taken correctly as I can perceive from my reading online and the documentation.
IEmote appears to be a string, but a string does not fulfill this parameter, saying that there is no conversion from a String to an IEmote. I tried casting this String to an IEmote but that did not work.
The RequestOptions variable seems to fulfill the parameter perfectly fine as a new RequestOptions().
My full code for this is:
private async Task MessageReceived(SocketMessage message)
{
var rMessage = (RestUserMessage) await message.Channel.GetMessageAsync(message.Id);
rMessage.AddReactionAsync(???, new RequestOptions());
}
How do I fulfill this IEmote parameter correctly and or how do I define an IEmote variable. Also, is defining a new RequestOptions() variable the correct thing to fulfill this parameter as well. Is this also the correct way to add reactions to a message through Discord.NET and if not what is?
The research I have done:
https://github.com/RogueException/Discord.Net/issues/490
https://discord.foxbot.me/docs/api/Discord.Rest.RestUserMessage.html
https://discord.foxbot.me/docs/api/Discord.IEmote.html
https://discord.foxbot.me/docs/api/Discord.RequestOptions.html

If you head over to Emojipedia, and grab the unicode version as shown below :
After that is copied, you have to create a new Emoji object, like so :
var YourEmoji = new Emoji("😀");
You can then add a reaction to the desired message, I'm going to use Context.Message :
Context.Message.AddReactionAsync(YourEmoji);

Unknown's solution works for regular emotes, but won't work for guild-specific emotes.
This is the solution I came up with:
SocketGuild guild = ((SocketGuildChannel) message.Channel).Guild;
IEmote emote = guild.Emotes.First(e => e.Name == "my-custom-emote");
message.AddReactionAsync(emote);

You already found the way to adding the emoji, but I'll follow up with an additional way of adding a guild emoji to a message. You'd need the raw string of the emoji in this case. Don't confuse it with Emoji, Emoji represents an Unicode emoji, but Emote is from Discord.Net and stands for a custom emoji. The AddReactionAsync method accepts both objects thanks to the IEmote interface.
Emote emote = Emote.Parse("<:craig_cat:603083214281506817>")
In this case, we're creating an Emote object with the emoji called craig_cat and the provided ID.
In order to get the raw string to parse, in your Discord client, simply send the emoji (:craig_cat:), but with a backslash (\) before it.
Note, in case of an animated emoji, it will look like the following:
Emote emote = Emote.Parse("<a:running:703588456198307900>")
There has to be an a before the punctuation mark to identify it as an animated emoji.
In both cases, you can add it to the message by these examples:
Context.Message.AddReactionAsync(emote); //Adds the reaction to the user's message that triggered the task (works only in a command)
Most of the other interfaces/objects also support this method, casting would help though.
You can also use this raw format at any time to include the emoji in a message.

Related

Input text has too few parameters - C# Discord bot

I'm pretty new to all of this, so excuse the fact that this is probably a massive facepalm moment to most people here. I'm trying to get my Discord bot to play audio. It'll join the channel but whenever I use the play command it says "the input text has too few parameters" in the discord chat. As I said I'm new to this so don't know where to start. Here's what I have for the play command;
[Command("play", RunMode = RunMode.Async)]
public async Task PlayCmd([Remainder] string song)
{
await _service.SendAudioAsync(Context.Guild, Context.Channel, song);
}
}
That's just the basic play command I have with nothing extra added just yet. Also, how would I get it to play a specific file? I'm unsure of where or how to add the file path to the command.
Based on the code you provided I assume that you need to give the song-name as the parameter in your command. The function PlayCmd does take a string as a parameter.
Try to use your commad in discord like this syntax:
command parameter
. For example: play Tetris

EWS Attached emails missing DatatimeReceived property after .Load()

I am currently working on a former colleague's project that deals with saving emails from Exchange to our ERP system.
But I have run into a strange problem. Sometimes when the system receives an email, that contains an email as an attachment. It throws an error because the DataTimeReceived date is not set. Even after a .Load();
private int HandleEmail(Item item, Folder moveToFolder, Folder moveToFailedFolder, Mailbox mailbox, int fatherId = 0, string uploaderEmail = "", bool isEmbeddedMail = false)
The way it work. is that the HandleEmail() method goes through the original email until it gets the if-check.
If the attachment is not a FileAttachment, and is an ItemAttachment. The following code is called.
else if (attachment is ItemAttachment)
{
var itemAttachment = attachment as ItemAttachment;
itemAttachment.Load(new PropertySet(ItemSchema.Attachments, ItemSchema.TextBody, EmailMessageSchema.Sender, EmailMessageSchema.DisplayCc, EmailMessageSchema.DateTimeReceived, EmailMessageSchema.From, ItemSchema.MimeContent, ItemSchema.Body, ItemSchema.TextBody, EmailMessageSchema.BccRecipients, ItemSchema.Attachments));
var item_ = itemAttachment.Item;
HandleEmail(item_, null, null, mailbox, (int)mailid, uploaderEmail, true); // The attached email is then looped through like it is an regular email instead of like an image.
}
In this check. It takes the item attachment and loads an additional property set, which contains some data that is needed.
Finally the method calls it self, but now with the Item Attachment as to read it like a regular email.
My issue is the fact, that some attached emails do not have the DatetimeReceived property set.
Instead this error is shown in its place.
Microsoft.Exchange.Webservice.Data.ServicesObjectPropertyException
And this expection message is thrown
You must load or assign this property before you can read its value
And I can't quite figure out why it only happens to some attached emails. When I look at the emails it self, it does have an received date. But for some reason I can't get it using .Load()
I've tried a few things, such as using .Load for both Item and ItemAttachment, both without getting anything worthwhile.
Tried looking into using the service.loadpropertiesforitems()
I've forgotten a few of the other things I've looked into, since I have been looking at this for a few days before the weekend aswell.
Two suggestions i would have is first try the EmailMessageSchema.DateTimeSent (which should be the same as DateTimeReceived) the difference maybe being caused when attaching a messages that was sent. The other thing would be enable tracing and have a look at the traces to see what is actually coming back from the server also maybe just try loading the BasePropertySet.FirstClassProperties rather then your custom set (just to test that property anyway)

getContentResolver() is not defined

I want to create small app to parse sms. I use Visual Studio with Xamarin.
I found these peace of code and want to adapt is for my need.
But getContentResolver() method is not defined. I know, that it needs application context, but i don't understand how to get it.
Could someone give me an example please?
// Create Sent box URI
Uri sentURI = Uri.parse("content://sms/sent");
// List required columns
String[] reqCols = new String[] { "_id", "address", "body" };
// Get Content Resolver object, which will deal with Content Provider
ContentResolver cr = getContentResolver();
// Fetch Sent SMS Message from Built-in Content Provider
Cursor c = cr.query(sentURI, reqCols, null, null, null);
In Java world, you'll see methods like getContentResolver and setContentResolver. In Xamarin and C# those two will be combined to one property called ContentResolver. The latter part of your code should be like this:
// Fetch Sent SMS Message from Built-in Content Provider
Cursor c = ContentResolver.Query(sentURI, reqCols, null, null, null);
When porting Java code to C# (Xamarin), you can usually get basic stuff to work by capitalizing method names. With that logic, you should also modify the first line to this:
Uri sentURI = Uri.Parse("content://sms/sent");
However, this is a very simplified example. Knowing both Java and C# and how to use both the Android and Xamarin documentation will take you quite far.

Reading and parsing email from Gmail using C#, C++ or Python

I have to do a Windows application that from times to times access a Gmail account and checks if there is a new email. In case there is, it must read the email body and subject (a simple text email, without images or attachments).
Please, do not use paid libs, and in case of any other libs used, give the download path.
And I need the email body and subject only. So if the long and complex message that comes from Gmail could be parsed and only two strings containing the subject and the body, it would be perfect.
Finally, I only have to get the new messages arrived since the last execution. So the read messages could be marked as "read" and only the new ones (marked as "new") are considered.
The code can be written in Python or C++, but I prefer it in C#.
Related question:
Properly formatted example for Python iMAP email access?
This prints the subject and body of unseen messages, and marks those messages as seen.
import imaplib
import email
def extract_body(payload):
if isinstance(payload,str):
return payload
else:
return '\n'.join([extract_body(part.get_payload()) for part in payload])
conn = imaplib.IMAP4_SSL("imap.gmail.com", 993)
conn.login("user", "password")
conn.select()
typ, data = conn.search(None, 'UNSEEN')
try:
for num in data[0].split():
typ, msg_data = conn.fetch(num, '(RFC822)')
for response_part in msg_data:
if isinstance(response_part, tuple):
msg = email.message_from_string(response_part[1])
subject=msg['subject']
print(subject)
payload=msg.get_payload()
body=extract_body(payload)
print(body)
typ, response = conn.store(num, '+FLAGS', r'(\Seen)')
finally:
try:
conn.close()
except:
pass
conn.logout()
Much of the code above comes from Doug Hellmann's tutorial on imaplib.
Use one of the many C# IMAP libraries.
Note that there are some differences between Gmail-IMAP and IMAPA. For example, due to the fact that Gmail treats folders like labels, the code like the one below doesn't delete message if it's tagged with some other folder:
imap_instance.uid('store', uid, '+FLAGS', '\\Deleted')
imap_instance.expunge()
I know this is an old post but I wanted to add the following link to the Open Source ImapX 2 Library discussion: https://imapx.codeplex.com/ the developers seem to be keeping the project up to date. Great job to those all involved
Google has opened it's Gmail API for accessing your gmail account. You can check a quickstart sample with the basic functionalities at this link:
https://developers.google.com/gmail/api/quickstart/python
from imap_tools import MailBox, Q
# This prints the subject and body of unseen messages, and marks those messages as seen.
with MailBox('imap.mail.com').login('test#mail.com', 'password') as mailbox:
# *mark_seen param = True by default
print([(m.subject, m.html or m.text) for m in mailbox.fetch(Q(seen=False), mark_seen=True)])
imap_tools

How do I stop my System.Messaging.MessageQueue from wrapping my strings in XML?

I need to communicate with a legacy application from my C# app via the Windows Message Queue.
The legacy application expects plain string messages in a particular private queue, but I can't seem to stop the System.Messaging.MessageQueue from wrapping my message in XML!
The code I'm testing is very simple:
MessageQueue myQueue = new MessageQueue(#".\Private$\tolegacy");
Message msg = new Message("My Test String");
myQueue.Send(msg);
The trouble is that the message is being XML serialized and appears in the queue as:
<?xml version="1.0"?><string>My Test String</string>
I can't modify the behaviour of the legacy application, so I need to stop the System.Messaging.MessageQueue from formatting my message as XML.
Can anyone help?
Using the ActiveXMessageFormatter will give you the desired result. We had the same issue with just wanting to pass a string to a queue and have the listener process read in the body as a string. The ActiveXMessageFormatter is used for serializing/deserializing primitive data types and will not put an XML wrapper on your input as is the case with the default XmlMessageFormatter.
mq.Formatter = new ActiveXMessageFormatter();
Here is another link describing the 3 different formatters as well.
You can create your own formatter (it is a class that implements IMessageFormatter and assign it to the Formatter property of the Message
Here is a link to MSDN to the Message.Formatter property.
I have not tried this but you should be able to write your message using the BodyStream, I believe this will bypass the formatter.

Categories