In my iOS app I'm trying to use the Facebook Swift SDK so that a user can post a URL to a specific Facebook page that they manage.
I've managed to get the following code working - but it only shares the post to my home timeline:
let content = LinkShareContent(url: URL(string: urlString)!)
let sharer = GraphSharer(content: content)
sharer.failsOnInvalidData = true
sharer.completion = {
(result) in
print(result)
}
do {
try sharer.share()
}
catch (let error) {
print(error.localizedDescription)
}
I believe that I need to use the graphNode property to specify the destination page and that the correct format is as follows:
sharer.graphNode = "/\(pageId)"
However, when I set this property before posting, I am getting an error:
failed(Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL"
I've tried a dozen different formats to specify the node but they all return the same error and I can't find any working examples.
I managed to resolved this issue. It turns out that the graphNode path above is correct but I was looking in the wrong place due to the error message I was getting. Instead I just needed to specify the accessToken parameter.
graphSharer.accesstoken = myPageAccessToken
Note: The access token is not the user's current access token, but an access token you can retrieve when calling the /me/accounts API.
var graphPath = "/me/accounts"
I also then had an issue posting to the page because I had only requested the publish_actions permission. From the documentation, this appears to be suitable but it only worked where I requested further permissions as follows:
loginManager.logIn(withPublishPermissions: ["publish_actions",
"manage_pages", "publish_pages"], ...
Hopefully this will be of use to someone in future. :-)
Related
I try to upload video to Facebook using Graph API.
But always see error message
(#100) No permission to publish the video.
Facebook app has Development mode. I created test user there. My role is admin. FB access token is valid.
Here my code here:
private func upload(url: URL) {
guard let data = try? Data(contentsOf: url) else { return }
let connection = GraphRequestConnection()
connection.delegate = self
var items: [String: Any] = [:]
items["title"] = "Test title from api"
items["\(url.absoluteString)"] = data
let keys = ["value" : "EVERYONE"]
items["privacy"] = keys
let request = GraphRequest(graphPath: "me/videos", parameters: items, httpMethod: .post)
connection.add(request) { reqconnection, anyInfo, error in
print(reqconnection)
print(anyInfo)
print(error)
}
connection.start()
}
I saw a lot of questions about it, but mostly they are too old and don't work for me.
Share video to FB
From thread FB Developers here - the same error, but they didn't find solution
Also check this docs - doesn't work
Also I'm a bit confused what docs are right for post video in Facebook.
Because in docs I see
The Video API allows you to publish Videos on Pages and Groups. Publishing on Users is not supported.
but also in another docs see Graph API with path me/videos. So it confused me a bit.
What docs are correct for my case:
here
here
From docs I see that
Your app should manage permissions as follows:
Graph API Requests - Before you send Graph API requests, you should check for necessary permissions and request them if needed.
Where can I find permission publish_actions?
Please help to figure out how to fix that.
I only can upload via ShareDialog. Like here and docs here
I've been working with the Amplify SDK to get federatedSignIn working with my iOS app with "Sign in with Apple" and Cognito to eventually make calls to API Gateway / Lambda functions.
TL;DR : My access token does not appear to be "automatically included in outbound requests" to my API as per the last paragraph of this section of the docs : Cognito User pool authorization
I have successfully authenticated using the tutorial found here Authentication Getting Started and other various Youtube videos on the Amazon Web Services channel.
Upon successful sign in through Apple I'm given an ASAuthorizationAppleIDCredential object. This contains the user field (token) which I pass to the Amplify.Auth class using the following Swift code :
func signIn (with userId: String)
{
guard
let plugin = try? Amplify.Auth.getPlugin(for: AWSCognitoAuthPlugin().key),
let authPlugin = plugin as? AWSCognitoAuthPlugin,
case .awsMobileClient (let client) = authPlugin.getEscapeHatch()
else
{
return
}
client.federatedSignIn(providerName: AuthProvider.signInWithApple.rawValue, token: userId) { (state, error) in
if let unwrappedError = error
{
print (unwrappedError)
}
else if let unwrappedState = state
{
print ("Successful federated sign in:", unwrappedState)
}
}
}
All appears to be successful and to double check I use the following bit of code to ensure I'm authorized :
func getCredentialsState (for userId:String)
{
let provider = ASAuthorizationAppleIDProvider()
provider.getCredentialState(forUserID: userId) { (credentialsState, error) in
if let unwrappedError = error
{
print (unwrappedError)
}
switch credentialsState
{
case .authorized:
print ("User Authorized")
case .notFound, .revoked:
print ("User Unauthenticated")
case .transferred:
print ("User Needs Transfer")
#unknown default:
print ("User Handle new use cases")
}
}
}
In the console I see "User Authorized" so everything appears to be working well.
However when I then go to make a call to Amplify.API.post I get the following error:
[Amplify] AWSMobileClient Event listener - signedOutFederatedTokensInvalid
Failed APIError: Failed to retrieve authorization token.
Caused by:
AuthError: Session expired could not fetch cognito tokens
Recovery suggestion: Invoke Auth.signIn to re-authenticate the user
My function for doing the POST is as follows :
func postTest ()
{
let message = #"{'message": "my Test"}"#
let request = RESTRequest (path: "/test", body: message.data(using: .utf8))
Amplify.API.post (request:request)
{
result in switch result
{
case .success(let data):
let str = String (decoding: data, as: UTF8.self)
print ("Success \(str)")
case .failure(let apiError):
print ("Failed", apiError)
}
}
}`
I then went into the API Gateway UI and changed the generated Method Request on my resource from AWS IAM to my Cognito User Pool Authorizer thinking this was the issue. I also changed the awsAPIPlugin authorizationType to "AMAZON_COGNITO_USER_POOLS" in my amplifyconfiguration.json file. This unfortunately did not have any affect.
I've seen posts such as this issue User is not created in Cognito User pool for users logging in with Google federated login #1937 where people discuss the problem of having to to use a web ui to bring up the social sign in. I understand that Apple will reject your app sometimes for this. Therefore this is not a solution.
I then found this post which seems to resolve the issue however this appears to use the old version of the SDK? Get JWT Token using federatedSignIn #1276
I'm not great with Swift (I'm still an Objective C expert, but am slowly learning Swift) so I'm uncertain which path to go here and whether this is actually a solution? It does seem to be quite more complicated than the function I have that does my POST? The RESTRequest does seem to be a simple and easy solution but I'm uncertain how to pass it the Authorization token (or even how to get the token if it is needed here).
However, everything I've read about the SDK is that the authorization should be handled automatically in the background according the docs in my first link above. Specifically pointed out, again, here : Cognito User pool authorization. The last paragraph here states 👍
With this configuration, your access token will automatically be included in outbound requests to your API, as an Authorization header.
Therefore, what am I missing here as this does not appear to automatically include my access token to my outbound requests to my API?
I am experiencing issue while trying to create pin with Pinterest SDK, I use this code:
PDKClient.sharedInstance().createPin(with: imageToShare, link: URL.init(string: "https://someUrl"), onBoard: "MyBoard", description: "",
progress: { (percent) in
}, withSuccess: { (response) in
print("Success")
}) { (error) in
if let error = error {
print(error)
}
}
And I receive this particular response:
Error Domain=com.alamofire.error.serialization.response Code=-1011
"Request failed: not found (404)" UserInfo
{NSLocalizedDescription=Request failed: not found (404),
NSErrorFailingURLKey=https://api.pinterest.com/v1/pins/
User is logged in into Pinterest application, just before calling this line of code, I am able to successfully create board with name MyBoard via the same API, but I am stuck within creation of the pin.
I tried to create pin with image url (because I thought that maybe it is because of my image), but it outputs the same response.
I am using twitter and facebook sdk within the same code, Info.plist seems allright.
Any clues?
Apparently the problem was, that onBoard actually requires not a board name, but it's identifier. So when you create pin board programatically -- (PDKClient.sharedInstance().createBoard) you should fetch and save it's identifier, which can be fetched in response (response.board().identifier).
I was stuck within this problem for the past 1.5 hours and figured it out just after posting the question :) I think it can be useful for someone else, because official SDK wiki is not very informative and git repository is quite dead too.
How can I get token_for_business from Facebook login? I have setup a business and associated my application with that business. Facebook documentation says you need to call GET /me?fields=token_for_business on User node, and it will return following json.
{
"id": "1234567890"
"token_for_business": "weg23ro87gfewblwjef"
}
I tried by providing token_for_business in parameter list of /me call but didn't work. Need advises.
Edit
I found this URL https://developers.facebook.com/docs/graph-api/reference/v2.5/user and tried by passing token_for_business in param of initWithGraphPath but no gain. I checked in Graph API Explorer and getting the required data. But not sure how to call from my objective-C code.
Edit 2
I Inspected the error object of initWithGraphPath:#"me?fields=token_for_business" call and found following details
Error Domain=com.facebook.sdk.core Code=8 "(null)" UserInfo={com.facebook.sdk:FBSDKGraphRequestErrorCategoryKey=0, com.facebook.sdk:FBSDKGraphRequestErrorHTTPStatusCodeKey=403, com.facebook.sdk:FBSDKErrorDeveloperMessageKey=(#200) Application must be associated with a business. https://business.facebook.com/, com.facebook.sdk:FBSDKGraphRequestErrorGraphErrorCode=200, com.facebook.sdk:FBSDKGraphRequestErrorParsedJSONResponseKey={
body = {
error = {
code = 200;
"fbtrace_id" = "EN9bN/YMloA";
message = "(#200) Application must be associated with a business. https://business.facebook.com/";
type = OAuthException;
};
};
code = 403;
}}
But if I try my app in Graph API Explorer then I'm getting the required data. So now it confusing me.
I want to use the YouTube Data API to get the links to thumbnails for a specific YouTube video in my iOS app. I went to Google Developers Console and created a new project.
For that project I then went to "APIs" and removed the default APIs it enables for me and added the YouTube Data API. I then went to credentials, created a Public Key (as I don't need the user to log in or anything, just getting the thumbnail URLs) as iOS, which gave me an API key. I added the Bundle Identifier for my project under Allowed Applications.
Now in my app I tried the following code:
let test = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "https://www.googleapis.com/youtube/v3/videos?id=7lCDEYXw3mM&key=*MYKEYHERE*&part=snippet,contentDetails,statistics,status")!, completionHandler: { (data, response, error) -> Void in
let json = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil)
println("JSON: \(json)")
})
But it prints out the error:
JSON: Optional({
error = {
code = 403;
errors = (
{
domain = usageLimits;
message = "Access Not Configured. Please use Google Developers Console to activate the API for your project.";
reason = accessNotConfigured;
}
);
message = "Access Not Configured. Please use Google Developers Console to activate the API for your project.";
};
})
What exactly am I doing wrong?
There is a known problem about Bundle id in the console. If you can just remove that restriction, it should just work fine.
You can track the original issue from here: https://code.google.com/p/gdata-issues/issues/detail?id=5770
Here's what you need, YouTube has a service API via web to consult this types of things. I'm using this URL to consult all videos from a user (getting every videos: URL, Thumbnail, views, duration, etc). I'm sure you'll find thumbnails for a particular video. Its a JSON response so you'll have to take a good look to the structure but can't get simpler than this.
http://gdata.youtube.com/feeds/api/users/USER_NAME/uploads?v=2&alt=json&#&start-index=1&max-results=10