How to convert facebook api response in user readable HTML format?
I call graph api
https://graph.facebook.com/me/feed?access_token=<token>
below is my response data from API.
{
"data": [
{
"id": "100000626589435_240877109276507",
"from": {
"name": "Abhi Patel",
"id": "100000626589435"
},
"type": "status",
"created_time": "2011-08-02T10:36:17+0000",
"updated_time": "2011-08-02T10:36:17+0000"
},
{
"id": "100000626589435_240760105954874",
"from": {
"name": "Abhi Patel",
"id": "100000626589435"
},
"type": "status",
"created_time": "2011-08-02T03:02:21+0000",
"updated_time": "2011-08-02T03:02:21+0000"
},
{
"id": "100000626589435_223775454320006",
"from": {
"name": "Abhi Patel",
"id": "100000626589435"
},
"picture": "http://profile.ak.fbcdn.net/hprofile-ak-snc4/274314_100000898272591_5481895_q.jpg",
"link": "http://www.facebook.com/?ref=nf_fr",
"icon": "http://static.ak.fbcdn.net/images/icons/?8:",
"type": "link",
"created_time": "2011-06-28T18:56:44+0000",
"updated_time": "2011-06-28T18:56:44+0000"
}
],
"paging": {
"previous": "<previous link>",
"next": "<next link>"
}
}
also want paging in facebook response data,
I want 20 records from facebook api response. How to manage this things..
Facebook returns raw JSON data. There are no style elements to it. It's up to you to present the data returned in the format you choose. Imagine if Facebook returned HTML and style elements. That wouldn't work very well for desktop applications or mobile devices. Instead, they just give you the raw data, and you design the HTML elements, or the WPF Views, or whatever to show the data you want to show.
By returning the raw data, you can also store it locally in a database for your own queries, or your own applications purposes.
Edited to add: You can parse out the objects by accessing the JSON elements directly, or you can deserialize the result to C# objects.
Console.WriteLine(response.data[0].from.name);
As for paging, you need to parse out the Paging elements. The Facebook C# SDK returns dynamic objects, so you can do something like
string next = response.paging.next;
string prev = response.paging.prev;
And then just make a request to each URL to fetch the data you want.
Use JSON.net and convert into the XML then it would be easy to manage for you.
Related
I am using adaptive card templating in bot framework. When user selects a particular value from a dropdown, based on the selection, few input fields on the input form card should be auto populated. How to achieve this?
Based on the dropdown, if user chooses 'myself', his email id should be auto populated in his/her email address textbox(email address I can get from user profile stored in user state).
The adaptive card I am using is as below:
{
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "TextBlock",
"text": "Please enter the email Id, on behalf of whom you want to raise the request.",
"wrap": true
},
{
"type": "Input.ChoiceSet",
"id":"dropdown",
"choices": [
{
"title": "Myself",
"value": "Myself"
},
{
"title": "Other",
"value": "Other"
}
],
"placeholder": "Raise request for"
},
{
"type": "Input.Text",
"id": "email",
"placeholder": "Enter email address here",
"validation": {
"necessity": "Required",
"errorMessage": "Email address is required"
}
},
{
"type": "ActionSet",
"actions": [
{
"type": "Action.Submit",
"title": "Submit",
"data": "Submit"
}
]
},
{
"type": "ActionSet",
"actions": [
{
"type": "Action.Submit",
"title": "Cancel",
"data": {
"id": "stepCancel"
}
}
]
}
]
}
I used actions instead of actionset. The card looks something like this:
{
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2",
"body": [
{
"type": "TextBlock",
"text": "Please enter the email Id, on behalf of whom you want to raise the request.",
"wrap": true
},
{
"type": "Input.ChoiceSet",
"id": "dropdown",
"choices": [
{
"title": "Myself",
"value": "Myself"
},
{
"title": "Other",
"value": "Other"
}
],
"placeholder": "Raise request for"
},
{
"type": "Input.Text",
"id": "email",
"placeholder": "Enter email address here",
"validation": {
"necessity": "Required",
"errorMessage": "Email address is required"
},
"inlineAction": {
"type": "Action.Submit",
"title": "Submit"
}
}
]
}
If you want to get Adaptive Cards to do something they were not designed to do, you will need to write your own renderer code using Adaptive Cards extensibility. You can use this answer and its many linked answers as your guide.
I've found that the usual pattern for these kinds of issues has two parts: come up with your own "schema" for your code to read, and then write the code to read it. If you want a choice set input to populate a certain text input with a certain value when a certain choice is selected, then your schema has three pieces of information: the text input's ID, the value to populate it with, and the choice that triggers it. Since this is a lot of information, it would be ideal if you could have all three of those pieces in their own "populate" object property like this:
{
"type": "Input.ChoiceSet",
"id": "dropdown",
"choices": [
{
"title": "Myself",
"value": "Myself"
},
{
"title": "Other",
"value": "Other"
}
],
"placeholder": "Raise request for",
"populate": {
"target": "email",
"with": "my_email#email.com",
"when": "Myself",
},
},
Unfortunately, Direct Line will strip out additional properties from your Adaptive Card so they'll never reach Web Chat. There is a workaround for that problem where you can preserve your full JSON by tricking Direct Line into thinking it's not an Adaptive Card and then making sure Web Chat knows it's an Adaptive Card when it receives it.
If you don't use the workaround, you will need to find some way of getting those three pieces of information to Web Chat. If don't want your code to be reusable for different cards then you can just hardcode the name of the text input and the choice into your JavaScript so that it doesn't need to be transmitted through the card. If you go the usual route of putting the information in the id property then it could look pretty crowded, and a dynamic ID could be hard for your bot to read after the data is submitted:
"id": "populate_email_when_Myself_with_my_email#email.com",
If the user's email is already stored on the Web Chat side somehow then you won't need to transmit it through the card, and the ID could just be "populate_email_when_Myself". That's a bit less imposing, and it would be easier for your bot to find because it's not dynamically generated. I'll go even further by assuming your client has the email address already and the text input's ID "email" is hardcoded in the JavaScript, so the choice set input ID can just be "populateEmail_Myself".
Once you're ready to write the JavaScript code, I usually like to go with onParseElement so most of my code only gets executed at the beginning as part of a sort of initialization. However, I've discovered that a problem with onParseElement is that you'll only have access to the elements that have already been parsed, so if your text input is parsed after your choice set input then the onParseElement function for the choice set input won't have access to the text input. You could solve that problem by having the function look for an element at the very end of your card so that the function will have access to all the other elements, but my example here just uses onInputValueChanged instead of onParseElement. Note that this means the function will be executed any time any input value is changed in any card, including each time a key is pressed in a text input.
window.AdaptiveCards.AdaptiveCard.onInputValueChanged = input => {
const PREFIX_POPULATE_EMAIL = 'populateEmail_';
if (input.id && input.id.startsWith(PREFIX_POPULATE_EMAIL)) {
// Myself
const targetValue = input.id.slice(PREFIX_POPULATE_EMAIL.length);
// The Adaptive Card object
const card = input.getRootElement();
// The text input with the hardcoded ID
const emailElement = card.getElementById('email');
// Did the user choose "Myself"?
if (input.value == targetValue) {
emailElement.renderedInputControlElement.value = THEIR_EMAIL_ADDRESS;
}
}
}
In many cases you'll need to re-render the element after you modify it by calling emailElement.render(). We don't need to do that in this case because we're changing the value in the rendered element directly with renderedInputControlElement rather than changing the value in the internal unrendered card element. This is a bit hacky because renderedInputControlElement is marked as protected in the TypeScript file, but if you wanted to do things the more official way then I suspect you'd have to rerender the whole card.
I'm working on a project that involves automating API calls using a Swagger Definition. I download the swagger.json file. The structure of the JSON Object I need to parse is not consistent. When parsing paths, there are a list of objects, then within that they have the methods that can be used for that specific path. I can retrieve just the path using various string methods but my question was, is there a good way to parse json if the JSON is structured in such a way that it does not have a firm key? Here is an example of what I mean:
{"/user": {
"post": {
"tags": [
"user"
],
"summary": "Create user",
"description": "This can only be done by the logged in user.",
"operationId": "createUser",
"consumes": [
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"parameters": [
{
"in": "body",
"name": "body",
"description": "Created user object",
"required": true,
"schema": {
"$ref": "#/definitions/User"
}
}
],
"responses": {
"default": {
"description": "successful operation"
}
}
}
}
If I wanted to just parse that path and retrieve the method object how could I go about that considering sometimes the object will be "post" or sometimes it will be "get", "put", etc depending on what is allowable for the path.
JObject jsonResp = swaggerDownload();
JObject paths = (JObject)jsonResp["paths"];
foreach (var i in paths)
{
string pathToString = i.ToString();
var shaveSomethings = pathToString.Substring(1, something.Length - 2);
var pathAndJson = shaveSomethings.Split(new[] { ',' }, 2);
string correctJsonStructure = "{\"" + pathAndJson[0] + "\":" + pathAndJson[1] + "}";
JObject bd = JObject.Parse(correctJsonStructure);
//dynamic pathsTest = JsonConvert.DeserializeObject<dynamic>(correctJsonStructure);
//JObject result = JsonConvert.DeserializeObject<JObject>(correctJsonStructure);
//Console.WriteLine(bd["/user"]);
}
The swagger.json file should have full definition of each entity that endpoints return. You can follow How to create Rest API client to get a working client.
I've dealt with an API where responses didn't always match the definition. I saved all responses to a store/log first and then would try to de-serialize JSON. In case of an exception I would go back to store/log and see what was different and update my code to accommodate for the change. After few iterations there were no new changes and the ordeal was over.
Hope that helps.
I followed this guide in order to create account linking in my app
https://developers.google.com/actions/identity/google-sign-in#json
I'm able to verify the user's jwt decoder and send back a response that the user is authorised. Then, according to the guide, in the next request, I should get the user's profile payload (user.profile.payload in the json structure) but It's missing from the next request. More than that, I get the tokenId for jwt verification again.
I think that what i miss here is in the possibleIntent object but I'm not sure, as I didn't see any documentation for that, because I work with asp.net server. There are SDKs with documentation for java and nodeJS only
this is the request provided for the sign in the contain the tokenId
{
"user": {
"locale": "en-US",
"lastSeen": "2019-07-11T14:18:10Z",
"idToken": "<tokenId>",
"userVerificationStatus": "VERIFIED"
},
"conversation": {
"conversationId": "ABwppHH9uZfcKj6pS6A6wItKC1dOXuZJ5oFYt2Og7cqrElSQYC9bv-aV7iQ5FDYaJPp-fa7tQNhc2yS0fw3QBu-M",
"type": "ACTIVE",
"conversationToken": "e0e78f40-a207-49c2-9050-50c6ed526c24"
},
"inputs": [
{
"intent": "actions.intent.SIGN_IN",
"rawInputs": [
{
"inputType": "KEYBOARD"
}
],
"arguments": [
{
"name": "SIGN_IN",
"extension": {
"#type": "type.googleapis.com/google.actions.v2.SignInValue",
"status": "OK"
}
},
{
"name": "text"
}
]
}
],
"surface": {
"capabilities": [
{
"name": "actions.capability.SCREEN_OUTPUT"
},
{
"name": "actions.capability.ACCOUNT_LINKING"
},
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.MEDIA_RESPONSE_AUDIO"
},
{
"name": "actions.capability.WEB_BROWSER"
}
]
},
"isInSandbox": true,
"requestType": "SIMULATOR"
}
this is the response that i provide after verifying the user.
I tried it with both intents actions.intent.TEXT and actions.intent.SIGN_IN but with no success. the next request is provided with the user.idToken property again instead of the user.profile (that should contain the payload)
{
"conversationToken": "b09d915e-6df9-496d-acde-b76858cd95b4",
"expectUserResponse": true,
"expectedInputs": [
{
"inputPrompt": {
"richInitialPrompt": {
"items": [
{
"simpleResponse": {
"textToSpeech": "Hi",
"displayText": "Hi"
}
}
],
"suggestions": []
}
},
"possibleIntents": [
{
"intent": "actions.intent.TEXT",
"inputValueData": {
"#type": "type.googleapis.com/google.actions.v2.SignInValue",
"status": "OK"
}
}
]
}
]
}
The user.profile attribute you're talking about is something that is provided via the actions-on-google library for JavaScript. It isn't in the JSON that you will receive. But...
You don't need it because the basic profile information (name, email, and Google ID) is encoded in the user.idToken. That string, which will be sent to you for every request, is just a JWT token which you can verify and decode. The profile will be in the "payload" section.
I don't know c#, but https://jwt.io/ contains a list of libraries which can decode the JWT string for you so you can read the "payload".
Keep in mind that you don't need to verify the token each time (although if you do it right, this shouldn't be expensive), but that you can decode it to get the information that you're looking for.
If you don't want to decode it, you can decode it when you first verify it, get the information you need, and store that information in the userStorage string (assuming you don't expect it to change).
I'm having a problem with the URL of the Facebook Graph API. Is there any possibility to get all the fields of a Facebook post including reactions? I use the following URL for the posts:
https://graph.facebook.com/{pageName}/feed?access_token={access_token}
Now I'm getting data like this (which is quite nice):
{
"data": [
{
"id": "someId",
"from": {
"Name": "Page name",
"category": "Sports Team",
"id": "someId"
},
"message": "Hello world!",
[...]
"shares": {
"count": 1
},
"likes": {
"data": [
{
"id": "someId",
"name": "Some person"
}
]
}
},
[...]
]
}
As for now I have to get the reactions (LOVE, WOW, HAHA, SAD, ANGRY and THANKFUL) by downloading the json from the following URL for every single post (and this is very time consuming):
https://graph.facebook.com/v2.9/{postId}?access_token={access_token}&fields=reactions
The only problem is that I can't get the reactions when using the "normal" URL (without &fields). Is there any chance to get all information including reactions without having to add all the fields to &fields=from,message,likes,shares,reactions?
From CBroe's comment:
I had to pass all the fields I wanted to save to my DB in my URL:
https://graph.facebook.com/v2.9/{pageName}/feed?access_token={access_token}&fields=id,from,message,name,[...],likes,comments,reactions,shares
I am using Andy Crum's EmberDataModelMaker.
Having punched in the following two classes
// app/models/server-item.js
export default DS.Model.extend({
hostName: DS.attr('string'),
syncServers: DS.hasMany('string'),
subscribers: DS.hasMany('string'),
mailHost: DS.attr('string'),
mailHostLogin: DS.hasMany('credentials')
});
// app/models/credentials.js
export default DS.Model.extend({
user: DS.attr('string'),
password: DS.attr('string'),
server: DS.belongsTo('serverItem')
});
It's showing the following three different expected JSON formats (a very nice feature btw.):
DS.RESTAdapter
"serverItems": [
{
"id": 1,
"hostName": "foo",
"syncServers": [
<stringids>
],
"subscribers": [
<stringids>
],
"mailHost": "foo",
"mailHostLogin": [
<Credentialsids>
]
}
],
"credentials": [
{
"id": 1,
"user": "foo",
"password": "foo",
"server": <ServerItemid>
}
]
DS.ActiveModelAdapter
"serverItems": [
{
"id": 1,
"host_name": "foo",
"sync_server_ids": [
<stringids>
],
"subscriber_ids": [
<stringids>
],
"mail_host": "foo",
"mail_host_login_ids": [
<Credentialsids>
]
}
],
"credentials": [
{
"id": 1,
"user": "foo",
"password": "foo",
"server_id": <ServerItemid>
}
]
DS.JSONAPIAdapter
{
"data": {
"type": "server-items",
"id": "1",
"attributes": {
"HostName": "foo",
"MailHost": "foo",
},
"relationships": {
"SyncServers": {
"data": {
"type": "SyncServers",
"id": <SyncServersid>
}
},
"Subscribers": {
"data": {
"type": "Subscribers",
"id": <Subscribersid>
}
},
"MailHostLogin": {
"data": {
"type": "MailHostLogin",
"id": <MailHostLoginid>
}
}
},
"included": [
{
<sideloadedrelationships>
]
}
}
}
{
"data": {
"type": "credentials",
"id": "1",
"attributes": {
"User": "foo",
"Password": "foo",
},
"relationships": {
"Server": {
"data": {
"type": "Server",
"id": <Serverid>
}
}
},
"included": [
{
<sideloadedrelationships>
]
}
}
}
I am going to implement (or rather change) some WebServices on the Server side (using C#, ASP.NET Web API). Currently, the WebService already creates a result that is pretty similar to the format expected with DS.RESTAdapter - obviously, it would be ideal if I could use it without compromising the Data Integrity - can I?
If yes, would it empower Ember Data to send all the requests necessary to maintain the data consistency on the server? Meaning, would the client send a DELETE request to the server not only for the ServerItem but also for the Credentials item that is referenced via the mailHostLogin property when the user wants to delete a ServerItem?
If not: are both of the other two adapters fulfilling the above mentioned consistency requirement? Which of the other two should I implement - any experiences/recommendations out there?
You should choose whichever Adapter closest fits your API data structure as a basis(sounds like DS.RESTAdapter in this case). You can extend the adapters and serializers that are a closest fit to make any necessary adjustments(this can be done both application wide or on a per model basis).
However, I don't think that the Ember Data model relationships(i.e. belongsTo and hasMany) are binding in such a way that will automatically result in the "data consistency" you are looking for. If your application requirements are to delete all associated Credentials records when a ServerItem is deleted, I would recommend doing that server side when handling the DELETE ServerItem API request. That would result in better performance(1 HTTP call instead of 2 or N depending if credentials can be deleted in bulk) and be much less error prone due to potential network or other failure of calls to delete Credentials after a ServerItem is deleted.
After a successful ServerItem delete, you could loop through it's credentials and unload the records from the client side store to keep it in sync with the new state on the server. Something like:
serverItemCredentials.forEach(function(id) {
if (this.store.recordIsLoaded('credential', id)) {
this.store.unloadRecord(this.store.peekRecord('credential', id));
}
});