Hangouts Chat Bot - Thread message posting above the thread's last message - hangouts-chat

I created a simple hangout's chat bot. When posting back to the thread, when setting the ThreadId, the message appears ABOVE the last message instead of below. If I remove the threadid it posts as a normal message below the thread. I'm not sure what I'm missing or even why the service would let me inject a message above the last one?
The code is pretty simple:
var response = ParseAndRespond(msg);
var chatMessage = new Message();
chatMessage.Text = response;
if (msg.message.thread != null && !String.IsNullOrEmpty(msg.message.thread.name))
{
chatMessage.Thread = new Google.Apis.HangoutsChat.v1.Data.Thread();
chatMessage.Thread.Name = msg.message.thread.name;
}
var request = ChatClient.Spaces.Messages.Create(chatMessage, msg.message.space.name);
request.Execute();

Related

Actors ReceiveAsync method unable to POST data to the listener

Background
Notification service has a Notify method which is invoked when an event occurs, so here Im creating the FloorActor and sending the message consisting data and post url to the Actor.
public class NotificationService
{
//HttpClient client = new HttpClient();
ActorSystem notificationSystem = ActorSystem.Create("NotificationSystem");
public void Notify(int clientID, FloorEventData data)
{
try
{
string postUrl = "http://localhost:6001";
FloorData floorData = new FloorData() { Data = data,PostURL=postUrl };
//This commented line of code post data and listener gets the POST request
//client.PostAsJsonAsync<FloorEventData>(postUrl, data);
//Create Floor Actor
var floorActor = notificationSystem.ActorOf<FloorActor>("floorActor");
floorActor.Tell(data);
}
catch (Exception exception)
{
//Log exception
}
}
}
ReceiveAsync method of the Floor Actor data just posts the event data to the specified URL.Framework used to implement Actor Model :Akka.Net
public class FloorActor : ReceiveActor
{
HttpClient client = new HttpClient();
public FloorActor()
{
ReceiveAsync<FloorData>(floorActor => client.PostAsJsonAsync<FloorEventData>(floorActor.PostURL, floorActor.Data));
}
}
Issue-
When I debugged the issue the code flow works as expected:-
1) When event occurs Notify method is invoked
2) Notify method creates the Floor Actor and sends the data
3) Floor Actor's ReceiveAsync method is called and the line of code is executed without any errors or exceptions.But the POST listener, doesn't get the POST data request, so not sure what is happening ?
Tried POST data directly from the Notify method its works, the listener gets the POST request.You can see this code snippet commented above in the Notify method.
So when I try to POST data from my Actor's Receive method, the Http listener does not get the request and there is no errors or exception.
Please let me know if I have to change anything?
ActorSystem should be treated as a singleton for your entire system. So put that instance in a static somewhere and reference it from there.
Also try to await on client.PostAsJsonAsync

Bot api, how i can get last message or chat history?

I want implement some functional like user send me a message and I reply to him with my (bot) latest message from chat history.
As you can see in the Telegram Bot API Documentation you can use sendMessage to send a message to the user.
When you receive a message, look for the chat or the from parameter in the JSON (depends if you want to answer to the person when it's a group chat or not). You can use the id parameter of the chat or from to send the message.
So the first parameter for your sendMessage would be chat_id=message.chat.id
You don't need the parse_mode, disable_web_page_preview and reply_markup for this example.
As you want to reply to the message of the user you may want to set the reply_to_message_id to the id of the received message.
reply_to_message_id = message.message_id
Last but not least, you want to set the text parameter. If I understand it correctly, your program will send the last received message.text to the user.
So what you want to do is, as soon as you get a message, save it.
Message oldMessage = message
And when you send the Message to the user use the old messages text property as the text.
text = oldMessage.text
Alright to sum it up here is the pseudocode of the function that will happen as soon as you receive a message:
Message oldMessage = null;
public void NewMessage(Message message){
int chat_id = message.chat.id;
int reply_to_message_id = message.message_id;
String text = "There is no old Message"; //fallback value
if(oldMessage != null){
text = oldMessage.text;
}
//Send Message in this example only has 3 parameters, and ignores the
//not used ones
SendMessage(chat_id,text,reply_to_message_id);
oldMessage = message; //store the received message for future answering
}
As you store the whole message in oldMessage you could also set the text you will send to something like this:
String text = oldMessage.from.first_name+": "+oldMessage.text;
if you simply want to reply on users message you need this function:
public void sendMsg(Message message, String text){
SendMessage sendMessage = new SendMessage();
sendMessage.enableMarkdown(true);
sendMessage.setChatId(message.getChatId().toString());
sendMessage.setReplyToMessageId(message.getMessageId());
sendMessage.setText(text);
try{
setButtons(sendMessage);
sendMessage(sendMessage);
}catch (TelegramApiException e){
e.printStackTrace();
}
}

Marketo rest Api create lead

I have a question about this create/Update leads API, http://developers.marketo.com/documentation/rest/createupdate-leads/.
There is no sample code for C# or JAVA. Only ruby available. So I have to try it by myself. But I always get null return from the response.
Here is my code:
private async Task<CreateLeadResponseResult> CreateLead(string token)
{
string url = String.Format(marketoInstanceAddress+"/rest/v1/leads.json?access_token={0}", token);
var fullUri = new Uri(url, UriKind.Absolute);
CreateLeadResponseResult createLeadResponse = new CreateLeadResponseResult();
CreateLeadInput input = new CreateLeadInput { email = "123#123.com", lastName = "Lee", firstName = "testtesttest", postCode = "00000" };
CreateLeadInput input2 = new CreateLeadInput { email = "321#gagaga.com", lastName = "Lio", firstName = "ttttttt", postCode = "00000" };
List<CreateLeadInput> inputList = new List<CreateLeadInput>();
inputList.Add(input);
inputList.Add(input2);
CreateLeadRequest createLeadRequest = new CreateLeadRequest() { input = inputList };
JavaScriptSerializer createJsonString = new JavaScriptSerializer();
string inputJsonString = createJsonString.Serialize(createLeadRequest);
using (var client = new HttpClient())
{
HttpResponseMessage response = await client.PostAsJsonAsync(fullUri.OriginalString, inputJsonString).ConfigureAwait(false);
// I can see the JSON string is in the message body in debugging mode.
if (response.IsSuccessStatusCode)
{
createLeadResponse = await response.Content.ReadAsAsync<CreateLeadResponseResult>();
}
else
{
if (response.StatusCode == HttpStatusCode.Forbidden)
throw new AuthenticationException("Invalid username/password combination.");
else
throw new ApplicationException("Not able to get token");
}
}
return createLeadResponse;}
//get null here.
Thank you.
-C.
The best way to debug this is to capture the exact URL, parameters and JSON that are submitted by your app and try submitting those manually via a tool like Postman (Chrome plug-in) or SOAP UI. Then you see the exact error message, which you can look up here: http://developers.marketo.com/documentation/rest/error-codes/. Based on that you can update your code. I don't know much about Java, but this is how I got my Python code to work.
Your example code was really helpful in getting my own implementation off the ground. Thanks!
After playing with it for a bit, I realized that the JavaScriptSerializer step is unnecessary since PostAsJsonAsync automatically serializes whatever object you pass to it. The double serialization prevents Marketo's API from processing the input.
Also, I agree with Jep that Postman is super helpful. But in the case of this error, Postman was working fine (using the contents of inputJsonString) but my C# code still didn't work properly. So I temporarily modified the code to return a dynamic object instead of a CreateLeadResponseResult. In debugging mode this allowed me to see fields that were discarded because they didn't fit the CreateLeadResponseResult type, which led me to the solution above.

WCF API and API Key authorisation

Written or started to write a WEB API rest service in WCF. It's all going relatively well. However, I've come across a small problem. I've implemented this;
http://blogs.msdn.com/b/rjacobs/archive/2010/06/14/how-to-do-api-key-verification-for-rest-services-in-net-4.aspx
For key validation. (I'm not sure if this is the correct approach for WCF WEB API, since it looks more like the rest service implementation).
Anyway, it seems to work. However, when the api key is not provided the exception is not been displayed in the browser. I.e. if I provide the key, it returns correctly, if I don't it just shows a blank page.
private static void CreateErrorReply(OperationContext operationContext, string key)
{
// The error message is padded so that IE shows the response by default
using (var sr = new StringReader("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + APIErrorHTML))
{
XElement response = XElement.Load(sr);
using (Message reply = Message.CreateMessage(MessageVersion.None, null, response))
{
HttpResponseMessageProperty responseProp = new HttpResponseMessageProperty() { StatusCode = HttpStatusCode.Unauthorized, StatusDescription = String.Format("'{0}' is an invalid API key", key) };
responseProp.Headers[HttpResponseHeader.ContentType] = "text/html";
reply.Properties[HttpResponseMessageProperty.Name] = responseProp;
operationContext.RequestContext.Reply(reply);
// set the request context to null to terminate processing of this request
operationContext.RequestContext = null;
}
}
}
Instead of this showing an error, the result is a blank response. Can anyone help?

How to communicate WCF exceptions to WebClient

I have a WCF web service which throws exceptions when invalid data is submitted. The data is submitted via an HTTP Post using the WebClient object.
Here is the code for the web service:
[WebInvoke(UriTemplate = "update", Method = "POST")]
public JsonValue Update(HttpRequestMessage message)
{
var context = new Entities();
dynamic response = new JsonObject();
// in order to retrieve the submitted data easily, reference the data as a dynamic object
dynamic data = message.Content.ReadAs(typeof(JsonObject), new[] { new FormUrlEncodedMediaTypeFormatter() });
// retrieve the submitted data
int requestId = data.requestId;
int statusId = data.statusId;
string user = data.user;
string encryptedToken = data.token;
string notes = data.notes;
// retrieve the request with a matching Id
var request = context.Requests.Find(requestId);
// make sure the request exists
if (request == null)
throw new FaultException("The supplied requestId does not exist.");
// make sure the submitted encrypted token is valid
var token = DecryptToken(encryptedToken);
if (token == null)
throw new FaultException("Invalid security token.");
// TODO: Validate other token properties (e.g. email)?
if (!request.User.UserName.Equals(token.UserName))
throw new FaultException("Invalid security token.");
// additional logic removed ...
}
And here is the code that submits data to the web service:
// use the WebClient object to submit data to the WCF web service
using (var client = new WebClient())
{
client.Encoding = Encoding.UTF8;
// the data will be submitted in the format of a form submission
client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
var data = new NameValueCollection();
// prepare the data to be submitted
data.Add("requestId", requestId.ToString());
data.Add("statusId", this.StatusId);
data.Add("token", token.ToString());
data.Add("user", this.User);
data.Add("notes", this.Notes);
// submit the data to the web service
var response = client.UploadValues(this.Address, data);
}
I keep getting an exception with message: "The remote server returned an error: (500) Internal Server Error" at client.UploadValues(this.Address, data);.
Is there a way I can make sure that more detailed information is returned to the WebClient?
Also, how can I make sure that these exceptions (in the WCF service) are logged to the EventLog? (Basically I just need to know what happened).
Take a look at HttpResponseException (namespace Microsoft.ApplicationServer.Http.Dispatcher) - they're the way where you can control the response for error cases. You can specify the status code, and you have control over the HttpResponseMessage, in which you can control the message body.
On the client side, when you call WebClient.UploadValues, wrap that call and catch a WebException. If the service returns a response with a non-successful status code (e.g., 500, 400), the Response property of the WebException will have the body, in which you can read in your client.
Another option is to use HttpClient instead of the WebClient, in which case you can simply look at the HttpResponseMessage directly.