As some of you may know Facebook is migrating its users pages progressively to what is called the "New Page Experience" (NPE), the thing is some previous endpoints and data such as "locations" are not available by the same means anymore, for NPE you need to use the page token.
In my case, I used to do the following query on the facebook-graph-api with a facebook user token:
me/accounts?fields=access_token,category,tasks,name,is_published,locations.limit(100){access_token,category,name,is_published,parent_page}
This returned a JSON array with all the pages linked to the account of the user token, and the associated locations for each page.
However since the New Page Experience partial migration, if at least one page has been migrated to New Experience by Facebook, the whole call returns an error
{
"error": {
"message": "Invalid OAuth 2.0 Access Token",
"type": "OAuthException",
"code": 190,
"error_subcode": 2069032,
"is_transient": false,
"error_user_title": "Token d’accès utilisateur non pris en charge",
"error_user_msg": "Un token d’accès de Page est requis pour cet appel dans la nouvelle version des Pages."
}
Facebook has added a boolean field on pages called has_transitioned_to_new_page_experience, which should allow us to filter the pages.
However it doesn't seem to work, I've tried thing such as (true, 1, "true"...) which do work for other boolean parameters but not for has_transitioned_to_new_page_experience :
me/accounts?has_transitioned_to_new_page_experience=true // return all pages without filtering
me/accounts?is_place=true // Filters properly based on if the page is a place
I'd like to be able to single out the NPE, or do a filtered query to avoid needless calls through loops and array management, as most of the pages are still not NPE yet, and this would allow me to keep my code for "legacy pages" untouched.
Have any of you experienced this issue, or been able to solve it?
Maybe talk with the Facebook dev support?
Do you think this behavior is buggy?
Thanks!
Related
I'm trying to pull some specific data from a wiki site; pcgamingwiki.
I would like to pull the save game data path from the site but I'm not understanding how to make the request properly. I also wanna state I'm not very knowledgeable about Visual Basic or even using C#, I did some VB back 5+ years ago and I remember bits a pieces.
What I want my app to do is using the steam game ID to search PCGamingWiki for the relevant game page ID, and then parse the save game location path of that game on that page.
I am using WikiClientLibrary with the Cargo extension support too.
This is the Visual Basic code that I have:
Async Sub main2()
Dim client As New WikiClientLibrary.Client.WikiClient()
Dim site As New WikiClientLibrary.Sites.WikiSite(client, "https://pcgamingwiki.com/w/api.php?")
Await site.Initialization
Dim page = New WikiClientLibrary.Pages.WikiPage(site, 3098)
Await page.RefreshAsync(WikiClientLibrary.Pages.PageQueryOptions.FetchContent)
RichTextBox1.AppendText(site.SiteInfo.SiteName)
RichTextBox1.AppendText(page.Content.Substring(0, 10000))
End Sub
And this Cargo query that gets the page ID from the Steam app ID
https://www.pcgamingwiki.com/w/api.php?action=cargoquery&tables=Infobox_game&fields=Infobox_game._pageID%3DPageID%2CInfobox_game.Steam_AppID&where=Infobox_game.Steam_AppID%20HOLDS%20"21000"&format=jsonfm
This is getting me the page information but I know there is a better way of getting the info.
Doing a wiki query for the sections gives me
{
"toclevel": 2,
"level": "3",
"line": "Save game data location",
"number": "3.2",
"index": "6",
"fromtitle": "Lego_Batman:_The_Videogame",
"byteoffset": 5842,
"anchor": "Save_game_data_location"
}
But the issue is that from what I could find is that I can only use the fromtitle and the index to get this information but on a different game page the fromtitle is different as it is the game name and the index changes as the content can be placed different on the page depending on the game.
I was hoping that I could use "number" as it seems they all are "3.2" or "anchor" as they all have "save_game_data_location" but I can't see how I could search by these identifiers. PCGamingWiki uses the Cargo extension but I'm not sure how I could make the right queries in visual basic to get the information I need or if there is another way of getting this content.
This is what the content on the page looks like
I'm just not sure how I convert the normal API queries cleanly and that Cargo query into Visual Basic code so any advice would be appreciated.
I am using the mediawiki api to upload a file. I am sending a mutlipart POST request to
https://commons.wikimedia.org/w/api.php?format=json&action=upload&filename=xxx
In the header I include my Autherzation: Bearer accessToken123 and in the body I include my CSRF token, as well as my multipart file, all as per documentation.
However, the response I get from the server is the following:
{
"error": {
"code": "permissiondenied",
"info": "The action you have requested is limited to users in one of the groups: *, [[Commons:Users|Users]].",
"*": "See https://commons.wikimedia.org/w/api.php for API usage. Subscribe to the mediawiki-api-announce mailing list at <https://lists.wikimedia.org/postorius/lists/mediawiki-api-announce.lists.wikimedia.org/> for notice of API deprecations and breaking changes."
},
"servedby": "mw1448"
}
This would be quite self-explainatory by itself, however when I check my rights/groups with
https://commons.wikimedia.org/w/rest.php/oauth2/resource/profile
I get the following:
{"sub":xxxx,"username":"xxxxx","editcount":7,"confirmed_email":true,"blocked":false,"registered":"xxxx",
"groups":["*","user","autoconfirmed"],
"rights":["read","writeapi","viewmyprivateinfo","abusefilter-view","abusefilter-log","upload","upload_by_url","reupload-own","purge","reupload","autoconfirmed","editsemiprotected","skipcaptcha","abusefilter-log-detail","transcode-reset"],
"grants":["basic","uploadfile","uploadeditmovefile","privateinfo"],"realname":"","email":"xxxx"}
As you can see I am both a part of the required groups and also have the neccessairy upload right. The error message is quite clear, so I don't know what I am missing. It is not the CSRF token or access token, supplying these wrong results in a different error message. Any help is appreciated.
Well I finally figured it out: When requesting the app keys from mediawiki, you can select rights which the app has on behalf of the users. If you want to upload pictures to wikimedia commons, you do not only need the `
Interact with media: Upload new files; Upload, replace, and move
files
right, but also the
Create, edit, and move pages
right, since you are creating a new page with each upload. I hope this helps someone else in the future :`)
I am trying to make a simple python script that posts a text message to a facebook page using requests.
I actually managed to succeed this feat, however, when I add the same logic to a bigger project of mine, a certain request returns a different json.
According to this page https://developers.facebook.com/docs/pages/access-tokens I can exchange the short lived user token I generate in the graph explorer tool for a long lived one that lasts 60 days. This worked for me until now. When I run the same functions, same variables on another .py file that includes other logic as well the request does not return this line:
"expires_in": SECONDS-UNTIL-TOKEN-EXPIRES
And of course later on if I continue the logic and use the token it returns (which is the same) for, let's say, a make_post function the request prints
{'error': {'message': '(#200) If posting to a group, requires app being installed in the group, and \\\n either publish_to_groups permission with user token, or both manage_pages \\\n and publish_pages permission with page token; If posting to a page, \\\n requires both manage_pages and publish_pages as an admin with \\\n sufficient administrative permission', 'type': 'OAuthException', 'code': 200, 'fbtrace_id': 'AqYMMeOcOniWAGgEEtsEURs'}
Why does it not successfully return, the user token had not expired and it has the requires rights. Furthermore I tested this in a smaller .py file and it worked.
Another thing I found out here https://developers.facebook.com/support/bugs/523165725596520/?join_id=f1ff8392b49675c here is that other people have actually reported the same issue but it has been closed as 'intended by design' however there is no information of a solution.
Running the request in my browser also does not work correctly.
Do you have any ideas? I am completely clueless.
Thank you very much in advance
As #CBroe in a comment said, the expires_in didn't have anything to do with my error. The token it returns if valid. The issue I had later on had to do with the url I was parsing
I'm trying to test the pass_thread_control function on Facebook Messenger, to have my Dialogflow bot direct ongoing conversation to a human operator. So far I'm stuck at even trying to get a "success" code in Graph API Explorer. I have reviewed Facebook's documentation ( https://developers.facebook.com/docs/messenger-platform/reference/handover-protocol/pass-thread-control/ ), carefully looked through different threads here or elsewhere. I have:
Subscribed my Facebook Page to receive messaging_handovers.
Set the Dialogflow chatbot app as the Primary Receiver.
Set the Page Inbox as Secondary Receiver.
...And I keep on getting various errors. For example, I try this request in Graph API explorer:
POST to https://graph.facebook.com/v5.0/me/pass_thread_control
with params:
{
"recipient": {
"id": "myPageID"
},
"target_app_id": "263902037430900"
}
{
"error": {
"message": "Unsupported post request. Object with ID 'me' does not exist, cannot be loaded due to missing permissions, or does not support this operation. Please read the Graph API documentation at https://developers.facebook.com/docs/graph-api",
"type": "GraphMethodException",
"code": 100,
"error_subcode": 33,
"fbtrace_id": "AipGijCLKQOwOl6L792ZEgG"
}
}
Maybe the issue is the recipient PSID? This is the only parameter I have no idea where to get. What is the page scoped app-id? How do I get it?
Or maybe I missed some permissions...?
Any help getting me unstuck much appreciated...
Okay, I actually managed to figure it out.
First and foremost - I discovered the Page I was trying to pass the thread control to wasn't linked to my Facebook Business account and the chatbot app was. I added the page in Facebook Business Manager so that it's linked to the same business account as the chatbot app. NOTE: I am not sure that this is a prereq for everyone, so take caution. It might not be required in all scenarios.
To retrieve the Page PSID, which can then be used in the 'recipient' param of the POST request to pass_thread_control, Sent a GET request using Graph API Explorer as shown here: https://developers.facebook.com/docs/facebook-login/connecting-accounts#examples
Even though the example request does not contain the appsecret_proof param, I used it and haven't tested the request without it. A very simple way of generating appsecret_proof using PHP is shown here: https://developers.facebook.com/docs/graph-api/securing-requests#generate-proof
Then when providing the PSID obtained using method shown in point 2., I got "success:true" while testing the pass_thread_control, which did pass the thread control to Secondary Receiver = Page Inbox. Yaaay! 😊
All of the above is described also in this thread, which helped me figure it out, so credit to Sunil: Is Facebook Messenger PSID PageScope constant for User
I got problem with shopify API and with data it provides. When i try to get list of all meta-fields with my app I end up with invalid data that tell all meta-fields are owned by shop (owner_id, owner_resource in JSON result). In shop I work with there is over 2000 meta-fields, created mostly by installed apps, that most certainly belong directly to resources like page, blog or product and most of them are most certain not associated directly with shop.
What is more strange when i use chrome plugins or free shopify app to edit meta-fields, that in data i recieve present as associated with shop, they are displayed as belonging to particular aspects of shop as it should be. Adding or deleting meta-field does not reflect on the data or count of meta-fields I get in way explained below.
So what I do first is getting count of metafields with following request, to later know how split data requests into pages.
/admin/metafields/count.json
then to get complete set of data i make series of requests like this
/admin/metafields.json?limit=200&page=1
...
As result i get (example data)
{ "id": 2488777, "namespace": "content_value", "key": "[default]3883205", "value": "There are no items in your cart. ", "value_type": "string", "description": "", "owner_id": 2174481, "created_at": "2014-12-30T20:23:56+01:00", "updated_at": "2014-12-30T20:33:56+01:00", "owner_resource": "shop" }
So my question is what wrong I do here making these requests and why i get invalid data, or it is maybe another "shopify thing" to get such behaviour. Can someone direct me how to get full valid list of meta-fields with rightfully associated owners? Is there any caching involved with metafields that could cause lack of update?
When you make a call to /admin/metafields.json without any query parameters then you will see the metafields that belong to the shop.
You can retrieve metafields that belong to another resource by making an authenticated GET request to a URL like this one: /admin/orders/3250063171/metafields.json
An alternate format for the URL is this: /admin/metafields.json?metafield[owner_id]=3250063171&metafield[owner_resource]=order