Discord.Net -- How to make Bot Ping users with "#" - c#

I'm working on coding a bot that will retrieve an image based on search parameters. When the bot returns the message after the command, I want the bot to alert the user that sent the command with a ping. (the notification of a message using the "#" symbol in discord).
Here's what I've got so far:
await Context.Channel.SendMessageAsync("#" + Context.Message.Author + "\n" + imageNode.Attributes["src"].Value);
I'm able to correctly grab the author of the command and it sends as it should--
Output in channel:
However, it's not actually sent as a tag, just plain text.
Is there a way to actually ding the user with a notification?

Yes, using User.Mention.
await Context.Channel.SendMessageAsync(Context.Message.Author.Mention + "\n" + imageNode.Attributes["src"].Value);
You can also just put their id in between <#>. For example, "Hello <#1234>"

One of my favorite things about C# 6 is that you can also use String Interpolation. Very useful in Discord.Net!
var id = Context.Message.Author.Id;
await Context.Channel.SendMessageAsync($"<#{id}> \n {imageNode.Attributes["src"].Value}";

Related

Send template-notification to tile and toast once

I register two different templates for my WindowsPhone clients (one for tile-update and one for toasts).
Is there a possibility to only send one notification and my WindowsPhone clients getting a toast notification and a tile update?
I found a forum thread on msdn with following message (in the answer):
If you call a method SendTemplateNotificationAsync({“properties of
template”}, “en-us”)) like this, That will target the toast and tile
both notifications to the device A.
But that won't work for me. My client only gets the tile-update and not the toast notification.
I also tried a template with both in xml (tile and toast). Found here. But that also won't work (only toast visible on client).
I know, I can work with additional tags (like "toast" and "tile") and send the notifications like following code snippet. But I think this is an ugly solution:
await hubClient.SendTemplateNotificationAsync(content, tags + " && toast");
await hubClient.SendTemplateNotificationAsync(content, tags + " && tile");
Any help is appreciated. Thanks
Edit: My templates and my notification-properties:
Properties:
var content = new Dictionary<string, string>
{
{"title_en", "English title"},
{"message_en", "English content"},
{"title_de", "Deutscher Titel"},
{"message_de", "Deutscher Inhalt"},
{"url", url},
{"count", count.ToString()}
};
Toast-Template (WindowsPhone)
String.Format("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<wp:Notification xmlns:wp=\"WPNotification\">" +
"<wp:Toast>" +
"<wp:Text1>$(title_{0})</wp:Text1>" +
"<wp:Text2>$(message_{0})</wp:Text2>" +
"<wp:Param>$(url)</wp:Param>" +
"</wp:Toast>" +
"</wp:Notification>", language);
Tile-Template (WindowsPhone)
String.Format("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<wp:Notification xmlns:wp=\"WPNotification\">" +
"<wp:Tile Template=\"IconicTile\">" +
"<wp:SmallIconImage>Small.png</wp:SmallIconImage>" +
"<wp:IconImage>Large.png</wp:IconImage>" +
"<wp:WideContent1>$(title_{0})</wp:WideContent1>" +
"<wp:WideContent2>$(message_{0})</wp:WideContent2>" +
"<wp:WideContent3 Action=\"Clear\"></wp:WideContent3>" +
"<wp:Count>$(count)</wp:Count>" +
"<wp:Title>AppName</wp:Title>" +
"</wp:Tile>" +
"</wp:Notification>", language)
await hubClient.SendTemplateNotificationAsync(content, tags + " && toast");
await hubClient.SendTemplateNotificationAsync(content, tags + " && tile");
This is not an ugly solution, actually there is a reason behind it.Selection of
template/registration always based on tags not based on payload keys. so actually you've registered the templates to different set of tags like =>
device A - toast template, tags: {"en-us", "toast"}
device A - tile template , tags : {"en-us", "tile"}
In this case Device tile template is registered with tags : {"en-us", "tile"} and Toast is tags: {"en-us", "toast"} and these two registrations are different so you can't send them in single request.
IMO you can't have the both notification with this single call => SendTemplateNotificationAsync({“properties of template”}, “en-us”))' because again IMO(As I was not able to work it out some time before) Notification hub is not able to decide which template (tile, toast) he has to send to the device. because each of them is registered with different tags set as mentioned above.
Also Why it is not an ugly solution, because It gives you more control over your notifications because you know toast and tile notifications have different purpose, they simultaneously don't provide any extra value.
Tile notification => It is used for info that can last long for some time and does not stale sooner. Like counter, Back image, Some new update etc. also this info does not require instant user's attention immediately.
Toast Notification => It is used for sending out info that is quite instant(hope you understand what I mean).Like some new message came, you have released a new update etc.
If you send two notification simultaneously all the time then in that case It really does not add extra value.

Encoding a line break for Twilio SMS using C#?

I'm using WebApi 2.2 to ramp up on the Twilio API. I have the Twilio C# libraries installed.
I'm using a form to capture a string in my web app, and I send that down to webAPI. I'm wondering how I can leverage the C# libraries to send a message with line breaks.
The example code shows the following:
var msg = twilio.SendMessage("+15084043345", "+15084043345", "Can you believe it's this easy to send an SMS?!");
However, I'm not sure how to include a line break in this message. Should I be inserting anything into this string clientside to represent a linebreak? Any guidance would be awesome.
Twilio Evangelist here.
This is actually super simple:
var msg = twilio.SendMessage("+15084043345", "+15084043345", "Hello.\nCan you believe it's this easy to send an SMS?!");
Will result in:
Hello.
Can you believe it's this easy to send an SMS?!
Just like printing strings to the console, \n, \r\n, and \r can be used to insert a new line. I can't say definitively what is best to use across all handsets, but I have found \n to be pretty reliable. (I can say all three of these work on my iOS 8 device perfectly...)
If you want to show new line in sms like
Account Name : suraj
Age : 24
then here is a code for asp.net VB
Dim value As String = "Account Name :" & "suraj" & vbCrLf & "Age :" & " 24"
it will show new line in SMS not in web page

Delete Ical event not working

I am creating an ical event dynamically in my web application and when someone cancel the appointment on the application we are generating a delete ical event *.ics file to their email to remove the event in their calendar.
Creating is working perfectly but when we try to delete the appointment we created it doesn't remove it from the calendar
Creating Ical event code :
string[] contents = {
"BEGIN:VCALENDAR",
"VERSION:2.0",
"PRODID:-//dev.com//iCal//EN",
"X-WR-CALNAME:development",
"X-WR-RELCALID:928C8448-048A-4aa2-BE27-A920773AF3DC",
"X-FUNAMBOL-ALLDAY:0",
"METHOD:REQUEST",
"BEGIN:VEVENT",
"UID:" + Args.EventUID,
"SEQUENCE:1",
"DTSTART:" + Args.EventStartTime.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"),
"DTEND:" + Args.EventEndTime.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"),
"LOCATION: " + Args.EventLocation,
"ORGANIZER: test#outlook.com",
"DESCRIPTION;ENCODING=ESCAPED-CHAR:" + Args.EventName,
"SUMMARY:" + Args.EventDescription,
"STATUS:CONFIRMED",
"TRANSP:OPAQUE",
"PRIORITY:" + Args.EventPriority.ToString(),
"END:VEVENT",
"END:VCALENDAR"
};
Creating an event works perfectly on iphone/android/outlook
Delete event part:
string[] contents = {
"BEGIN:VCALENDAR",
"VERSION:2.0",
"METHOD:CANCEL",
"X-WR-CALNAME:development",
"X-WR-RELCALID:928C8448-048A-4aa2-BE27-A920773AF3DC",
"PRODID:-//dev.com//iCal//EN",
"X-FUNAMBOL-ALLDAY:0",
"BEGIN:VEVENT",
"UID:" + Args.EventUID,
"SEQUENCE:2",
"DTSTART:" + Args.EventStartTime.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"),
"DTEND:" + Args.EventEndTime.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"),
"LOCATION: " + Args.EventLocation,
"DESCRIPTION;ENCODING=ESCAPED-CHAR:" + Args.EventName,
"SUMMARY:" + Args.EventDescription,
"ORGANIZER: test#outlook.com",
"PRIORITY:" + Args.EventPriority.ToString(),
"STATUS:CANCELLED",
"TRANSP:OPAQUE",
"END:VEVENT",
"END:VCALENDAR"
};
When I click this file generated to remove the event that is already created it doesn't remove the event and sometimes it duplicates the event.
The ical UID on creating and delete are the same.
First, scrutinise the UID. I know you say they're the same, but check ! Whitespace? Case?
Next, put PRODID on the second line, straight after BEGIN (Ignore the validators when they tell you to put VERSION on the second line.) This sounds trivial, the field is not even used, but Outlook in particular is ridiculously picky. Copy a working example. Test and tell me if I'm wrong.
Next, SEQUENCE is indexed from 0. Clients may interpret SEQUENCE:1 as an update, and wonder where is the original invitation.
Next, check the structure and mime type headers of your emails. I got best results by sending a simple single part email with Content-type: text/calendar; method="[REQUEST/CANCEL]" in the MIME header.
Still not working? Try adding an ATTENDEE element, with participation required, rsvp true etc, repeating the email address of the recipient.
Still problems? Use the online Icalendar validators to check your output, but also copy exactly a working example. Send yourself an invitation, then cancel it, from gmail and/or outlook. Everything is important - the structure of the message, the order of the fields in the Icalendar, the MIME headers of the email. Sending to GMail lets you see exactly what is received, via the gmail show original option.
I notice you are doing nothing for wrapping. Ical lines are limited to 75 characters, not much, and overflowing lines must start with a space. A validator will quickly tell you.
The difference may also be whether the calendar app has 'subscribed' or 'imported' the ics file? Subscribed events should update, imported ones generally may not as the user could have changed them - may vary between calendar apps.
Try using PUBLISH as METHOD and 0 as SEQUENCE for submitting and 1 as SEQUENCE for erasing.
Example of submitting:
string[] contents = {
"BEGIN:VCALENDAR",
"VERSION:2.0",
"PRODID:-//site.domain//iCal//EN",
"METHOD:PUBLISH",
"BEGIN:VEVENT",
"UID:" + Args.EventUID,
"SEQUENCE:0",
"DTSTART:" + Args.EventStartTime.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"),
"DTEND:" + Args.EventEndTime.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"),
"SUMMARY:" + Args.EventDescription,
"STATUS:CONFIRMED",
"END:VEVENT",
"END:VCALENDAR"
};
Example of erasing:
string[] contents = {
"BEGIN:VCALENDAR",
"VERSION:2.0",
"PRODID:-//site.domain//iCal//EN",
"METHOD:CANCEL",
"BEGIN:VEVENT",
"UID:" + Args.EventUID,
"SEQUENCE:1",
"DTSTART:" + Args.EventStartTime.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"),
"DTEND:" + Args.EventEndTime.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"),
"SUMMARY:" + Args.EventDescription,
"STATUS:CANCELLED",
"END:VEVENT",
"END:VCALENDAR"
};

C# Imap Sort command with special characters

I'm working on a problem with imap sort extention:
My command is the following:
var query = "icône";
//byte[] bytes = Encoding.Default.GetBytes(query);
//query = Encoding.UTF8.GetString(bytes);
var command = "SORT (REVERSE ARRIVAL) UTF-8 " + "{" + query.Length + "}";
var imapAnswerString = client.Command(command);
imapAnswerString = client.Command(query);
I get the following error:
BAD Error in IMAP command SORT: 8bit data in atom
I found this:
C# Imap search command with special characters like á,é
But I don't see how to prepare my code to send this request sucessfully.
If you want to stick with MailSystem.NET, the answer that arnt gave is correct.
However, as I point out here (and below for convenience), MailSystem.NET has a lot of architectural design problems that make it unusable.
If you use an alternative open source library, like MailKit, you'd accomplish this search query far more easily:
var query = SearchQuery.BodyContains ("icône");
var orderBy = new OrderBy[] { OrderBy.ReverseArrival };
var results = folder.Search (query, orderBy);
Hope that helps.
Architectural problems in MailSystem.NET include:
MailSystem.NET does not properly handle literal tokens - either sending them (for anything other than APPEND) or for receiving them (for anything other than the actual message data in a FETCH request). What none of the authors seem to have noticed is that a server may choose to use literals for any string response.
What does this mean?
It means that the server may choose to respond to a LIST command using a literal for the mailbox name.
It means that any field in a BODYSTRUCTURE may be a literal and does not have to be a quoted-string like they all assume.
(and more...)
MailSystem.NET, for example, also does not properly encode or quote mailbox names:
Example from MailSystem.NET:
public string RenameMailbox(string oldMailboxName, string newMailboxName)
{
string response = this.Command("rename \"" + oldMailboxName + "\" \"" + newMailboxName + "\"");
return response;
}
This deserves a Jean-Luc Picard and Will Riker face-palm. This code just blindly puts double-quotes around the mailbox name. This is wrong for at least 2 reasons:
What if the mailbox name has any double quotes or backslashes? It needs to escape them with \'s.
What if the mailboxName has non-ASCII characters or an &? It needs to encode the name using a modified version of the UTF-7 character encoding.
Most (all?) of the .NET IMAP clients I could find read the entire response from the server into 1 big string and then try and parse the response with some combination of regex, IndexOf(), and Substring(). What makes things worse is that most of them were also written by developers that don't know the difference between unicode character counts (i.e. string.Length) and octets (i.e. byte counts), so when they try to parse a response to a FETCH request for a message, they do this after parsing the "{}" value in the first line of the response:
int startIndex = response.IndexOf ("}") + 3;
int endIndex = startIndex + octets;
string msg = response.Substring (startIndex, endIndex - startIndex);
The MailSystem.NET developers obviously got bug reports about this not working for international mails, so their "fix" was to do this:
public string Body(int messageOrdinal)
{
this.ParentMailbox.SourceClient.SelectMailbox(this.ParentMailbox.Name);
string response = this.ParentMailbox.SourceClient.Command("fetch "+messageOrdinal.ToString()+" body", getFetchOptions());
return response.Substring(response.IndexOf("}")+3,response.LastIndexOf(" UID")-response.IndexOf("}")-7);
}
Essentially, they assume that the UID key/value pair will come after the message and use that as a hack-around for their incompetence. Unfortunately, adding more incompetence to existing incompetence only multiplies the incompetence, it doesn't actually fix it.
The IMAP specification specifically states that the order of the results can vary and that they may not even be in the same untagged response.
Not only that, but their FETCH request doesn't even request the UID value from the server, so it's up to the server whether to return it or not!
TL;DR
How to Evaluate an IMAP Client Library
The first thing you should do when evaluating an IMAP client library implementation is to see how they parse responses. If they don't use an actual tokenizer, you can tell right off the bat that the library was written by people who have no clue what they are doing. That is the most sure-fire warning sign to STAY AWAY.
Does the library handle untagged ("*") responses in a central place (such as their command pipeline)? Or does it do something retarded like try and parse it in every single method that sends a command (e.g. ImapClient.SelectFolder(), ImapClient.FetchMessage(), etc)? If the library doesn't handle it in a central location that can properly deal with these untagged responses and update state (and notify you of important things like EXPUNGE's), STAY AWAY.
If the library reads the entire response (or even just the "message") into a System.String, STAY AWAY.
You're almost there. Your final command should be something like
x sort (reverse arrival) utf-8 subject {6+}
icône
ie. you're just missing a search term to describe where the IMAP server should search for icône and sort the results. There are many other search keys, not just subject. See RFC3501 page 49 and following pages.
Edit: The + is needed after the 6 in order to send that as a single command (but requires that the server support the LITERAL+ extension). If the server doesn't support LITERAL+, then you will need to break up your command into multiple segments, like so:
C: a001 SORT (REVERSE ARRIVAL) UTF-8 SUBJECT {6}
S: + ok, whenever you are ready...
C: icône
S: ... <response goes here>
Thanks all for your answer.
Basically the way MailSystem.net sends requests (Command method) is the crux of this problem, and some others actually.
The command method should be corrected as follows:
First, when sending the request to imap, the following code works better than the original one:
//Convert stuff to have to right encoding in a char array
var myCommand = stamp + ((stamp.Length > 0) ? " " : "") + command + "\r\n";
var bytesUtf8 = Encoding.UTF8.GetBytes(myCommand);
var commandCharArray = Encoding.UTF8.GetString(bytesUtf8).ToCharArray();
#if !PocketPC
if (this._sslStream != null)
{
this._sslStream.Write(System.Text.Encoding.UTF8.GetBytes(commandCharArray));
}
else
{
base.GetStream().Write(System.Text.Encoding.UTF8.GetBytes(commandCharArray), 0, commandCharArray.Length);
}
#endif
#if PocketPC
base.GetStream().Write(System.Text.Encoding.UTF8.GetBytes(commandCharArray), 0, commandCharArray.Length);
#endif
Then, in the same method, to avoid some deadlock or wrong exceptions, improve the validity tests as follows:
if (temp.StartsWith(stamp) || temp.ToLower().StartsWith("* " + command.Split(' ')[0].ToLower()) || (temp.StartsWith("+ ") && options.IsPlusCmdAllowed) || temp.Contains("BAD Error in IMAP command"))
{
lastline = temp;
break;
}
Finally, update the return if as follows:
if (lastline.StartsWith(stamp + " OK") || temp.ToLower().StartsWith("* " + command.Split(' ')[0].ToLower()) && !options.IsSecondCallCommand || temp.ToLower().StartsWith("* ") && options.IsSecondCallCommand && !temp.Contains("BAD") || temp.StartsWith("+ "))
return bufferString;
With this change, all commands work fine, also double call commands. There are less side effects than with the original code.
This resolved most of my problems.

Sending OSC message bundles from C# and receiving in Processing got weird address pattern and errors

I am relatively new to programming, so please excuse me if the question is stupid. I am now working on a project which involves Kinect. I am using C# to extract the live joint information (such as position and orientation) and then sending the data into Processing using OSC message -Udp protocal. I sent OSC message bundle from C# the problem is I don't know how to dispatch the message to what I want in Processing. Or possibly, I sent the data in a wrong format in C#. I would be very appreciate if someone can tell me what could possible gone wrong in the code and caused the errors.
I send the joint position from C# by using these code:
if (joint0.JointType == JointType.ElbowRight)
{
// distance in meter
String temp = "ElbowRight " + joint0.Position.X * 1000 + " " + joint0.Position.Y * 1000 + " " + joint0.Position.Z * 1000;
Console.WriteLine(temp);
OscElement message = new OscElement("/joint/" + joint0.JointType.ToString(), joint0.Position.X * 1000, joint0.Position.Y * 1000, joint0.Position.Z, joint0.TrackingState.ToString());
bundle.AddElement(message);
}
OscSender.Send(bundle); // send message bundle
The part,"/joint/", is the address pattern of the message. The following data are the arguments of the message. According to http://opensoundcontrol.org/spec-1_0 a OSC type tag string should be added following to the address pattern, which is an OSC-string beginning with the character ',' (comma) followed by a sequence of characters corresponding exactly to the sequence of OSC Arguments in the given message. However when I tried this, a format exception was caused and the error was reported as: Invalid character (\44). What I did was simply added ",s" to the OSC message:
OscElement message = new OscElement("/joint/" + ",s" + joint0.JointType.ToString(), joint0.Position.X * 1000, joint0.Position.Y * 1000, joint0.Position.Z, joint0.TrackingState.ToString());
How do I suppose to add the type tag? Can this be the reason that caused the following errors?
In my Processing code, I tried to get the joint position value by using these code:
if(theOscMessage.checkAddrPattern("/joint")==true) {
String firstValue = theOscMessage.get(0).stringValue();
float xosc = theOscMessage.get(1).floatValue(); // get the second osc argument
float yosc = theOscMessage.get(2).floatValue(); // get the second osc argument
float zosc = theOscMessage.get(3).floatValue(); // get the second osc argument
String thirdValue = theOscMessage.get(4).stringValue(); // get the third osc argument
println("### values: "+xosc+", "+xosc+", "+zosc);
return;
}
However I got this error:
[2013/6/16 20:20:53] ERROR # UdpServer.run() ArrayIndexOutOfBoundsException: java.lang.ArrayIndexOutOfBoundsException
Than I tied receiving the messaging using a example given in Processing, which displays the address pattern and type tag of the massage:
println("addrpattern\t"+theOscMessage.addrPattern());
println("typetag\t"+theOscMessage.typetag());
It printed out this:
addrpattern pundle
typetag u???N?N?$xlt???
I dont understand what's wrong with the code. Souldn't the address pattern be "joint"? or at least "bundle"? What is the pundle...
P.s. I am using Visual C# 2010 Express and Processing 2.0b9 64bit on a Win7 os computer.
Thank you so much for the help!
Update:
Although I still can't figure out how to solve this problem, I found a way to receive messages in Processing. Instead of using OSC bundle, I am sending Osc messages with different address pattern. then use message plug (e.g. oscP5.plug(this,”leftFoot”,”/joint/AnkleLeft”);) in the draw method. Then create a method called leftFoot
public void leftFoot(float fx, float fy, float fz, String state) {
println("Received: "+fx+", "+fy+", "+fz+", "+state);
}
Then you can see the data being print out. p.s. in C# the OSC message was send using:
OscElement message = new OscElement("/joint" + "/" + joint0.JointType.ToString(), joint0.Position.X * 1000, joint0.Position.Y * 1000, joint0.Position.Z, joint0.TrackingState.ToString());
OscSender.Send(message);
Hmmm... not sure exactly, but you could just use OSCeleton. It comes with a Processing example - I've used it before, and it works fine.
(the example may also help you understand how to use the OSC address patterns correctly... )
https://github.com/Sensebloom/OSCeleton
https://github.com/Sensebloom/OSCeleton-examples
OSC requires padding to next 32-bit boundary, meaning that you need to add zeros to pad the message, until its length is an even multiple of four bytes.
You need to do the same for the typetag. Pad it with zeroes even if you only send one typetag, so ,s00 instead of just ,s

Categories