UCWA: Unable to send/Receive formatted text - chat

I have a simple chat application working fine with plain text implemented using UCWA api in a ASP.Net MVC web application. I have to implement a formatted text next.
Referring to UCWA: integrating advanced chat options
, I go to know that, before sending the message to using ucwa.Transport.clientRequest we have to set the contentType to text/html which currently is text/plain.
So i have the function to send a message as shown below:
function sendMessage(displayName, msg, timestamp) {
var encodedMsg = encodeURIComponent(msg);
ucwa.Transport.clientRequest({
url: messagingLinks.SendMessage + "?SessionContext=" + ucwa.GeneralHelper.generateUUID(),
type: "post",
contentType: "text/html",
data: encodedMsg,
callback: function () {
addMessageToChat(displayName, encodedMsg, timestamp);
}
});
}
The implementation of handleMessage() is as shown below:
function handleMessage(data, parts) {
alert("Inside Handle message");
if (!data._embedded.message._links.plainMessage) return false;
var message = decodeMessage(data._embedded.message._links.plainMessage.href);
var decodedMsg = decodeURIComponent(message);
addMessageToChat(data._embedded.message._links.participant.title, decodedMsg, formatTime(new Date(Date.now())));
}
The problem in the above implementation is that, on the receiving end, the handleMessage() method is not entered which means i'm not receiving the incoming message.
Can anyone point me where i'm going wrong and Are the any other changes i need to do along with the above changes, so that i can send a formatted text across. A sample will be really helpful regarding the same.
Any suggestion would also be good enough. Thanks in advance.
Edit:
As suggested i have modified my makeMeAvailable method. below is the definition of the same in Authentication.js:
function makeMeAvailable() {
if (!_authenticated) {
cache.read({
id: "main"
}).done(function (cacheData) {
if (cacheData) {
var data = {
SupportedModalities: ["Messaging"],
supportedMessageFormats: ["Plain","Html"]
};
transport.clientRequest({
url: cacheData._embedded.me._links.makeMeAvailable.href,
type: "post",
data: data,
callback: handleState
});
}
});
} else {
handleState({
status: 204
});
}
}
However, the output is still the same.
The second suggestion regarding the communication API, i'm unable to locate it.
Any suggestions with this?

Here are two reasons I did not receive messages sent through UCWA API:
Charset: Default value was ISO-8859-1, I had to use UTF-8 to receive any message.
Negotiated message formats: The receiving contact only supported plain message format, but the messages were sent with text/html content type.

When it comes to the messaging formats in UCWA it should be known that by default all endpoints that support the messaging modality by default support plain messages. It is interesting to note that this limitation does not prevent sending of HTML formatted messages as you have seen in your examples.
There are two ways to enable HTML formatted messages as follows:
When issuing a request to makeMeAvailable supply an SupportedMessageFormats (array) and include Html
Issue a PUT request to communication and include Html in SupportedMessageFormats
Until either 1 or 2 has executed successfully it will be impossible to receive HTML formatted messages.

Related

Parse.com resend verification email

I am using the email verification feature that Parse offers and would like my users to be able to resend the email verification if it fails to send or they cannot see it. Last I saw, Parse does not offer an intrinsic way to do this (stupid) and people have been half-hazzerdly writing code to change the email and then change it back to trigger a re-send. Has there been any updates to this or is changing the email from the original and back still the only way? Thanks
You should only need to update the email to its existing value. This should trigger another email verification to be sent. I haven't been able to test the code, but this should be how you do it for the various platforms.
// Swift
PFUser.currentUser().email = PFUser.currentUser().email
PFUser.currentUser().saveInBackground()
// Java
ParseUser.getCurrentUser().setEmail(ParseUser.getCurrentUser().getEmail());
ParseUser.getCurrentUser().saveInBackground();
// JavaScript
Parse.User.current().set("email", Parse.User.current().get("email"));
Parse.User.current().save();
You have to set the email address to a fake one save and then set it back to the original and then parse will trigger the verification process. Just setting it to what it was will not trigger the process.
iOS
if let email = PFUser.currentUser()?.email {
PFUser.currentUser()?.email = email+".verify"
PFUser.currentUser()?.saveInBackgroundWithBlock({ (success, error) -> Void in
if success {
PFUser.currentUser()?.email = email
PFUser.currentUser()?.saveEventually()
}
})
}
Poking around the source code for Parse server, there doesn't seem to be any public api to manually resend verification emails. However I was able to find 2 undocumented ways to access the functionality.
The first would be to use the internal UserController on the server (for instance from a Cloud function) like this:
import { AppCache } from 'parse-server/lib/cache'
Cloud.define('resendVerificationEmail', async request => {
const userController = AppCache.get(process.env.APP_ID).userController
await userController.resendVerificationEmail(
request.user.get('username')
)
return true
})
The other is to take advantage of an endpoint that is used for the verification webpage:
curl -X "POST" "http://localhost:5000/api/apps/press-play-development/resend_verification_email" \
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{ "username": "7757429624" }'
Both are prone to break if you update Parse and internals get changed, but should be more reliable than changing the users email and then changing it back.
We were setting emails to an empty string, but found that there was a race condition where 2 users would hit it at the same time and 1 would fail because Parse considered it to be a duplicate of the other blank email. In other cases, the user's network connection would fail between the 2 requests and they would be stuck without an email.
Now, with Parse 3.4.1 that I'm testing, you can do (for Javascript):
Parse.User.requestEmailVerification(Parse.User.current().get("email"));
BUT NOTE that it will throw error if user is already verified.
Reference:
http://parseplatform.org/Parse-SDK-JS/api/3.4.1/Parse.User.html#.requestEmailVerification
To resend the verification email, as stated above, you have to modify then reset the user email address. To perform this operation in secure and efficient way, you can use the following cloud code function:
Parse.Cloud.define("resendVerificationEmail", async function(request, response) {
var originalEmail = request.params.email;
const User = Parse.Object.extend("User");
const query = new Parse.Query(User);
query.equalTo("email", originalEmail);
var userObject = await query.first({useMasterKey: true});
if(userObject !=null)
{
userObject.set("email", "tmp_email_prefix_"+originalEmail);
await userObject.save(null, {useMasterKey: true}).catch(error => {response.error(error);});
userObject.set("email", originalEmail);
await userObject.save(null, {useMasterKey: true}).catch(error => {response.error(error);});
response.success("Verification email is well resent to the user email");
}
});
After that, you just need to call the cloud code function from your client code. From Android client, you can use the following code (Kotlin):
fun resendVerificationEmail(email:String){
val progress = ProgressDialog(this)
progress.setMessage("Loading ...")
progress.show()
val params: HashMap<String, String> = HashMap<String,String>()
params.put("email", email)
ParseCloud.callFunctionInBackground("resendVerificationEmail", params,
FunctionCallback<Any> { response, exc ->
progress.dismiss()
if (exc == null) {
// The function executed, but still has to check the response
Toast.makeText(baseContext, "Verification email is well sent", Toast.LENGTH_SHORT)
.show()
} else {
// Something went wrong
Log.d(TAG, "$TAG: ---- exeception: "+exc.message)
Toast.makeText(
baseContext,
"Error encountered when resending verification email:"+exc.message,
Toast.LENGTH_LONG
).show()
}
})
}

SendGrid incoming mail webhook - how to save the JSON format email data into my application folder in C#

This is regarding Sendgrid incoming mail webhook, I have referred this URL SendGrid incoming mail webhook - how do I secure my endpoint, and got some idea how to go about this, but, as I am new to MVC / WebAPI, could anyone give me the controller method code snippet to catch the JSON format HTTP post and save to my application folder.
This is the solution I found after googling and with slight modifications:
[HttpPost, HttpGet]
[EnableCors(origins: "*", headers: "*", methods: "*")]
public async Task Post()
{
if (Request.Content.IsMimeMultipartContent("form-data"))
try
{
//To get complete post in a string use the below line, not used here
string strCompletePost = await Request.Content.ReadAsStringAsync();
HttpContext context = HttpContext.Current;
string strFrom = context.Request.Form.GetValues("from")[0];
string strEmailText = context.Request.Form.GetValues("email")[0];
string strSubject = context.Request.Form.GetValues("subject")[0];
//Not useful I guess, because it always return sendgrid IP
string strSenderIP = context.Request.Form.GetValues("sender_ip")[0];
}
catch (Exception ex)
{
}
}
I tried, retrieving the values as
String to = context.Request.Params["to"];
but, the value returned is not consistent, i.e. most of the times it is returning null and occasionally returns actual value stored in it.
If anyone have a better solution, please let me know.
Thank you
If for some reason ["to"] doesn't work for you, try to get ["envelope"] value,
context.Request.Form.GetValues("envelope")[0]
which looks like
{"to":["emailto#example.com"],"from":"emailfrom#example.com"}

PUT Request not happening at all in Fantom

I am having some trouble with PUT requests to the google sheets api.
I have this code
spreadsheet_inputer := WebClient(`$google_sheet_URI_cells/R3C6?access_token=$accesstoken`)
xml_test := XDoc{
XElem("entry")
{
addAttr("xmlns","http://www.w3.org/2005/Atom")
addAttr("xmlns:gs","http://schemas.google.com/spreadsheets/2006")
XElem("id") { XText("https://spreadsheets.google.com/feeds/cells/$spreadsheet_id/1/private/full/R3C6?access_token=$accesstoken"), },
XElem("link") { addAttr("rel","edit");addAttr("type","application/atom+xml");addAttr("href","https://spreadsheets.google.com/feeds/cells/$spreadsheet_id/1/private/full/R3C6?access_token=$accesstoken"); },
XElem("gs:cell") { addAttr("row","3");addAttr("col","6");addAttr("inputValue","testing 123"); },
},
}
spreadsheet_inputer.reqHeaders["If-match"] = "*"
spreadsheet_inputer.reqHeaders["Content-Type"] = "application/atom+xml"
spreadsheet_inputer.reqMethod = "PUT"
spreadsheet_inputer.writeReq
spreadsheet_inputer.reqOut.writeXml(xml_test.writeToStr).close
echo(spreadsheet_inputer.resStr)
Right now it returns
sys::IOErr: No input stream for response 0
at the echo statement.
I have all the necessary data (at least i'm pretty sure) and it works here https://developers.google.com/oauthplayground/
Just to note, it does not accurately update the calendars.
EDIT: I had it return the response code and it was a 0, any pointers on what this means from the google sheets api? Or the fantom webclient?
WebClient.resCode is a non-nullable Int so it is 0 by default hence the problem would be either the request not being sent or the response not being read.
As you are obviously writing the request, the problem should the latter. Try calling WebClient.readRes() before resStr.
This readRes()
Read the response status line and response headers. This method may be called after the request has been written via writeReq and reqOut. Once this method completes the response status and headers are available. If there is a response body, it is available for reading via resIn. Throw IOErr if there is a network or protocol error. Return this.
Try this:
echo(spreadsheet_inputer.readRes.resStr)
I suspect the following line will also cause you problems:
spreadsheet_inputer.reqOut.writeXml(xml_test.writeToStr).close
becasue writeXml() escapes the string to be XML safe, whereas you'll want to just print the string. Try this:
spreadsheet_inputer.reqOut.writeChars(xml_test.writeToStr).close

Getting a 204 No Content response when I use restSetResponse in Coldfusion 10 REST

I am trying to use restSetResponse to set my own status and content as described in the docs here:
http://help.adobe.com/en_US/ColdFusion/10.0/Developing/WSe61e35da8d318518-5719eac51353e6bb244-7fec.html
Here is my REST method:
remote any function test() httpmethod="get" {
var response = {
status: 400,
content: 'something is wrong'
};
restSetResponse(response);
}
Any help would be greatly appreciated. Thanks!
In the link you provided, note the first numbered bullet under the "Send custom success responses using restSetResponse" heading. If you define the CFC as REST service, you need to ensure the returnType is set to "void". In your example, you have your returnType set to "any".

How to get the REST response message in ExtJs 4?

I'm building upon RESTFul Store example of ExtJs 4. I'd like my script to display errors provided by the REST server, when either Add or Delete request fails. I've managed to obtain the success status of a request (see the code below), but how do I reach the message provided with the response?
Store:
var store = Ext.create('Ext.data.Store', {
model: 'Users',
autoLoad: true,
autoSync: true,
proxy: {
type: 'rest',
url: 'test.php',
reader: {
type: 'json',
root: 'data',
model: 'Users'
},
writer: {
type: 'json'
},
afterRequest: function(request, success) {
console.log(success); // either true or false
},
listeners: {
exception: function(proxy, response, options) {
// response contains responseText, which has the message
// but in unparsed Json (see below) - so I think
// there should be a better way to reach it than
// parse it myself
console.log(proxy, response, options);
}
}
}
});
Typical REST response:
"{"success":false,"data":"","message":"VERBOSE ERROR"}"
Perhaps I'm doing it all wrong, so any advice is appreciated.
I assume that your service follows the REST principle and uses HTTP status codes other than 2xx for unsuccessful operations.
However, Ext will not parse the response body for responses that do not return status OK 2xx.
What the exception/response object (that is passed to 'exception' event listeners) does provide in such cases is only the HTTP status message in response.statusText.
Therefore you will have to parse the responseText to JSON yourself. Which is not really a problem since it can be accomplished with a single line.
var data = Ext.decode(response.responseText);
Depending on your coding style you might also want to add some error handling and/or distinguish between 'expected' and 'unexpected' HTTP error status codes. (This is from Ext.data.reader.Json)
getResponseData: function(response) {
try {
var data = Ext.decode(response.responseText);
}
catch (ex) {
Ext.Error.raise({
response: response,
json: response.responseText,
parseError: ex,
msg: 'Unable to parse the JSON returned by the server: ' + ex.toString()
});
}
return data;
},
The reason for this behavior is probably because of the REST proxy class not being a first class member in the data package. It is derived from a common base class that also defines the behavior for the standard AJAX (or JsonP) proxy which use HTTP status codes only for communication channel errors. Hence they don't expect any parsable message from the server in such cases.
Server responses indicating application errors are instead expected to be returned with HTTP status OK, and a JSON response as posted in your question (with success:"false" and message:"[your error message]").
Interestingly, a REST server could return a response with a non-2xx status and a response body with a valid JSON response (in Ext terms) and the success property set to 'true'. The exception event would still be fired and the response body not parsed.
This setup doesn't make a lot of sense - I just want to point out the difference between 'success' in terms of HTTP status code compared to the success property in the body (with the first having precedence over the latter).
Update
For a more transparent solution you could extend (or override) Ext.data.proxy.Rest: this will change the success value from false to true and then call the standard processResponse implementation. This will emulate 'standard' Ext behavior and parse the responseText. Of course this will expect a standard JSON response as outlined in your original post with success:"false" (or otherwise fail).
This is untested though, and the if expression should probably be smarter.
Ext.define('Ext.ux.data.proxy.Rest', {
extend: 'Ext.data.proxy.Rest',
processResponse: function(success, operation, request, response, callback, scope){
if(!success && typeof response.responseText === 'string') { // we could do a regex match here
var args = Array.prototype.slice.call(arguments);
args[0] = true;
this.callParent(args);
} else {
this.callParent(arguments);
}
}
})