Get facebook user's uploaded photos in swift/xcode 6 - facebook-graph-api

I've been able to login and get the first name, last name, email, and profile picture url in Xcode 6.1.1 with swift. I haven't been able to figure out how to get the urls or pull the images from a user, even though I have the user_photos Permission. Any help would be greatly appreciated.

You need to make request to graph api that will return you JSON in response to your request. For example if you want to get name, profile picture (it will give you url for profile picture) and id you can make request in your viewDidLoad() as follows
FBRequestConnection.startWithGraphPath("me?fields=id,name,picture", completionHandler: {(connection: FBRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
if (result? != nil) {
NSLog("error = \(error)")
println(result)
}
} as FBRequestHandler)
to set a label text to facebook name you can use
var resultdict = result as? NSDictionary
if let name = resultdict?["name"] as? String {
self.YOUR_LABEL.text = name //name is response object in "result" dictionary
}
Cheers!!!

Related

Fatal error: Session manager did not return a task: file

I am currently playing around with the Vimeo API and following the setup process and the guided readme found here:
(https://github.com/vimeo/VimeoNetworking)
All I am doing is pulling down publicly available videos from Vimeo except I have been receiving
Fatal error: Session manager did not return a task: file
everything else works and I am able to use my own token for authentication.
Here is the code I have right now that throws this error:
What am I doing wrong or missing?
let queryURL = URL(string: "/channels/staffpicks/videos")
let videoRequest = Request<[VIMVideo]>(path: queryURL!.absoluteString)
guard let sessionClient = _client else {
return []
}
let _ = sessionClient.request(videoRequest, completion: {
results in
switch results {
case .success(let response):
let videos: [VIMVideo] = response.model
for video in videos
{
print("retrieved video: \(video)")
}
vVideo = videos
break
case .failure(let error):
print(error.localizedDescription)
break
}
})
Sorry I am late but this worked for me (using Swift 4.2):
let appConfiguration = AppConfiguration(
clientIdentifier: Constants.VIMEO_CLIENT_IDENTIFIER,
clientSecret: Constants.VIMEO_CLIENT_SECRET,
scopes: [.Public], keychainService: "")
let vimeoSessionManager = VimeoSessionManager.defaultSessionManager(
baseUrl: VimeoBaseURL,
accessToken: Constants.VIMEO_ACCESS_TOKEN,
apiVersion: "3.4")
let vimeoClient = VimeoClient(
appConfiguration: appConfiguration,
sessionManager: vimeoSessionManager)
let videoRequest = Request<[VIMVideo]>(path: "/videos?query=dragon+ball")
vimeoClient.request(videoRequest) {
result in
switch result {
case .success(let response):
let videos: [VIMVideo] = response.model
print("\n\n retrieved videos: \(videos) \n\n")
case .failure(let error):
print("\n\n error retrieving videos: \(error) \n\n")
}
}
I'am almost sure you needed to add a session manager, but not 100% because haven't seen how you initialize the client and the other variables, so I am just adding this example.
Remember to get clientIndentifier, clientSecret and accessToken in [https://developer.vimeo.com/apps][1] (after you've created your app).
This is using a public accessToken, if you need authenticated access just add the .Private and .Interact scopes to the scopes array in appConfiguration, and to get an 'Authenticated' accessToken.
Also, please notice that I am using "/videos?query=dragon+ball" as an example.

Facebook Matching API - Returns empty data for any other user

I have a problem when I use the Facebook Checkbox Plugin in order to connect my users to a Facebook chatbot. When they click and the checkbox is checked, I get their user reference, and sending him/her a message, I get the user page-scoped id.
Using this user page-scoped id, I should be able to get the user app-scoped id, that I need to get more information from this user.
In order to to this, I use the facebook Matching API, and it works great for my administrator user, but as soon as I login using any other user, even if it is registered as a developer, the data that I get from the matching API is empty.
[https://developers.facebook.com/docs/messenger-platform/identity/id-matching]
Anybody has an idea about what could be happening here? My app is live (not approved), and I believe the permissions and tokens are right... If there is a problem, it should be about tokens, but I'm not sure about this.
Here, some of my code:
const accessToken = config.facebook.unlimitedPageAccessToken;
const clientSecret = config.facebook.clientSecret;
const appsecretProof = CryptoJS.HmacSHA256(accessToken, clientSecret).toString(CryptoJS.enc.Hex);
request({
url: 'https://graph.facebook.com/v2.10/'+ recipientId +'/ids_for_apps',
qs: { access_token: accessToken, appsecret_proof: appsecretProof }
}, function (error, response, body) {
if (!error && response.statusCode == 200) {
body = JSON.parse(body);
console.log("data --> " + JSON.stringify(body, null, 4));
const userAppId = body.data[0].id;
return userAppId;
} else {
console.error("Error trying to translate ID's.");
}
});
As I said, when I log in with any other user than the administrator, I get this:
{
"data": []
}
For every Facebook page, a user has a different psid. So until you get that page scoped id, you won't be able to send them a message. So may be what you can do is link the users to the page first to initialize the conversation.

swift3 webview with post request

I am running a school project and I am new from swift3.
By searching, I know how to pass a data from one view to anther:
Passing data from a tableview to webview
In the post above, he is using http get request to pass data to website, then reload the webivew:
let URL = NSURL(string: "https://www.example.com?data=\(passData)")
webView.loadRequest(NSURLRequest(url: URL! as URL) as URLRequest)
I see some useful links like about code with http post request in here:
HTTP Request in Swift with POST method. In a result, the code can print out the http response.
My question is that, how to implement a webview with sending a http post reuqest, like id, name, etc, instead of get method.
In anther words: I want to reload the webview(like example.com) and that website will contain the value I sent via http post request.
example.com:
$id = $_POST['id'];
echo $id;
Thanks.
Just create a URLRequest for POST as shown in the second link, and pass it to the webView:
var request = URLRequest(url: URL(string: "http://www.example.com/")!)
request.httpMethod = "POST"
let postString = "id=\(idString)"
request.httpBody = postString.data(using: .utf8)
webView.loadRequest(request) //if your `webView` is `UIWebView`
(Consider using WKWebView rather than UIWebView.)
You may need idString to be escaped if it contains some special characters.
By the way, the two line code:
let URL = NSURL(string: "https://www.example.com?data=\(passData)")
webView.loadRequest(NSURLRequest(url: URL! as URL) as URLRequest)
does not seem to be a good Swift 3 code. It can be written as:
let url = URL(string: "https://www.example.com?data=\(passData)")!
webView.loadRequest(URLRequest(url: url))

AWS Cognito integration swift3 Refresh provides ResourceNotFoundException

Following the answer here:
https://github.com/aws/aws-sdk-ios/issues/357
At the very bottom there is a mini guide on getting swift and cognito working.
I've made a AWSCustomIdentityProvider as such:
import Foundation
import AWSCognitoIdentityProvider
import AWSCognito
class AWSCustomIdentityProvider: NSObject, AWSIdentityProviderManager
{
private var dict = NSDictionary()
func addToken(value:NSString)
{
dict = ["graph.facebook.com":value]
}
public func logins() -> AWSTask<NSDictionary>
{
return AWSTask(result: dict)
}
}
And I have a login method from facebook:
public func loginButtonDidCompleteLogin(_ loginButton: FacebookLogin.LoginButton, result: FacebookLogin.LoginResult){
switch result {
case .failed(let error):
print("FACEBOOK LOGIN FAILED: \(error)")
case .cancelled:
print("User cancelled login.")
case .success(_, _, let accessToken):
let customIdentity = AWSCustomIdentityProvider()
let token = accessToken.authenticationToken
customIdentity.addToken(value: token as NSString)
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: REGIONTYPE, identityPoolId: "XXXXXXXXXXXXXXXXXXXXXXX", identityProviderManager:customIdentity)
credentialsProvider.clearKeychain()
credentialsProvider.clearCredentials()
let serviceConfiguration = AWSServiceConfiguration(region: REDIONTYPE, credentialsProvider: credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = serviceConfiguration;
credentialsProvider.getIdentityId().continue( { (task: AWSTask!) -> AnyObject! in
if (task.error != nil) {
print("Error: " + (task.error?.localizedDescription)!)// gets called
}
else {
print(task.result)//identityid
}
return nil
})
}
}
However I get the error:
Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=8 "(null)" UserInfo={__type=NotAuthorizedException, message=Logins don't match. Please include at least one valid login for this identity or identity pool.}
Please let me know if you have any idea on how to resolve my issue. I've tried also following the docs and setting the logins directly "credentialsProvider.logins = {"graph.facebook.com": mytoken}
and that produces a different exception upon invoking a lambda method but DOES retrieve the identityID properly. However doing it according to the docs makes a warning that the method I'm using is deprecated.
The error I get:
UserInfo={NSLocalizedDescription=serialized object is neither a valid json Object nor NSData object: }
However that only happens sometimes. If I retry then i can potentially get the identity id but upon invoking a lambda method, I get the same error. I'm assuming it is a cognito issue.
UPDATE
If I use AWSCognitoLoginProviderKey.facebook.rawValue instead of graph.facebook.com in the first part, then it gives me the cognito ID and then I invoke the lambda method. I'll include the lambda method just incase that's the part I'm getting wrong but I'm decently sure that it's cognito that is preventing me from calling the lambda method:
import AWSLambda
import Foundation
struct AWSHelper{
let lambda = AWSLambda.default()
let APPLICATION_NAME = "MYAPPLICATION"
init(){
}
func getFunctionName(funcName: String) -> String{
return "\(funcName)_\(APPLICATION_NAME)"
}
func login(facebookID: String, cognitoID:String, callback:#escaping (Bool) -> Void){
let req = AWSLambdaInvocationRequest();
req?.invocationType = AWSLambdaInvocationType.requestResponse
req?.payload = ["cognitoID" : cognitoID, "facebookID" : facebookID]
req?.functionName = getFunctionName(funcName: "MYFUNCNAME")
lambda.invoke(req!) { (response: AWSLambdaInvocationResponse?,error: Error?) in
print(error)
let payload = response?.payload
print(payload)
callback(true)
}
}
}
Update 2
I have found out that calling a refresh method like this:
credentialsProvider.credentials().continue({ (task: AWSTask!) -> Any? in
print(task.result)
})
Causes an error like this:
AWSiOSSDK v2.4.10 [Error] AWSCredentialsProvider.m line:577 | __44-[AWSCognitoCredentialsProvider credentials]_block_invoke.352 | Unable to refresh. Error is [Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=10 "(null)" UserInfo={__type=ResourceNotFoundException, message=Identity 'us-east-1:0db18266-1baa-4c59-9110-f9041dc92ead' not found.}]
I believe the big string that looks like an identitypoolID is actually the identityID for the given user that I have, so cognito has distributed an ID but is not able to query it?
the error:
Logins don't match. Please include at least one valid login for this identity or identity pool
Can also occur because you attempt to log in as another user without logging out, so the token in the logins dictionary is compared to the identityId for a different identity (and doesn't match). In this case the SDK usually recovers by retrying, clearing and reestablishing the identityId, and then it works.
But in your case since you are constructing your own logins dictionary, the issue is more likely that you have constructed a token that does not match. You can inspect tokens using https://jwt.io. (though I admit it works for google and cognito user pools, but not on facebook tokens (I don't know why this is)),
I think doesn't match means that the identityId records a different unique user than is specified in the token.
Are you sure the token is constructed correctly?
As you mentioned... the documentation.. well .. I find the documentation is not worth looking at, So I set up my projects so I can review working code and set breakpoints.
Here is a snippet of the code from Mobile Hub Helper's Facebook AWSSignInProvider, which shows what they use to get the token (token.tokenstring).
- (AWSTask<NSString *> *)token {
FBSDKAccessToken *token = [FBSDKAccessToken currentAccessToken];
NSString *tokenString = token.tokenString;
NSDate *idTokenExpirationDate = token.expirationDate;
if (tokenString
// If the cached token expires within 10 min, tries refreshing a token.
&& [idTokenExpirationDate compare:[NSDate dateWithTimeIntervalSinceNow:AWSFacebookSignInProviderTokenRefreshBuffer]] == NSOrderedDescending) {
return [AWSTask taskWithResult:tokenString];
}
AWSTaskCompletionSource *taskCompletionSource = [AWSTaskCompletionSource taskCompletionSource];
[FBSDKLoginManager renewSystemCredentials:^(ACAccountCredentialRenewResult result, NSError *error) {
if (result == ACAccountCredentialRenewResultRenewed) {
FBSDKAccessToken *token = [FBSDKAccessToken currentAccessToken];
NSString *tokenString = token.tokenString;
taskCompletionSource.result = tokenString;
} else {
taskCompletionSource.error = error;
}
}];
return taskCompletionSource.task;
}
Also... It bears mentioning. The AWSIdentityManager, and it's associated AWSSignInProviders is a nice architecture for getting signed in with Facebook and Google. Even if you don't use the rest of Mobile Hub Helper. Why re-invent the wheel, they did a very good job on the Identity portion of aws-mobilehub-helper-ios
I have a version of that library posted on github that adds an AWSSignInProvider for Cognito User Pools as well. SignIn-awsmhh it requires some fixes in the aws-mobilehub-helper-ios to use cognito user pools they are here aws-mobilehub-helper-ios (so if you clone do a clone --recursive and you will be set up for debugging using breakpoints in the library).
Few things that made it work I think.
I made the correct move by making my own identityprovidermanager and I think the main thing that was blocking me from executing a lambda method was actually the fact that I was using AWSLambda instead of AWSLambdaInvoker. After I switched it started making errors that made sense.

How to get Facebook User details in tvOS

i am using Facebook SDK in tvOS for Login. Currently i have used below code.
FBSDKDeviceLoginButton *button = [[FBSDKDeviceLoginButton alloc] initWithFrame:CGRectZero];
button.readPermissions = #[#"email"];
button.center = self.view.center;
[self.view addSubview:button];
first m confused at which Action can i use readPermissions = #[#"email"]; or publishPermissions = #[#"publish_actions"];
and then How to get user details like firstName, lastName, email, Birth date, and Id from facebook Responce
Getting details of the user can be accomplished by connecting to our Graph API once you have a valid token. For example, after a success login to get first name and last name:
if ([FBSDKAccessToken currentAccessToken]) {
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me?fields=first_name,last_name" parameters:nil]
startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error) {
NSLog(#"fetched user:%#", result);
}
}];
}
It is not same as mobile-sdk you should try graph api like how #chrispan is suggesting i've tried that & it is working perfectly. Just add as many fields you want in parameters and you'll get all the data which is set to public by user.
FBSDKGraphRequest.init(graphPath: "me", parameters: ["fields" : "email, gender, name, birthday"]).startWithCompletionHandler({ (
FBSDKGraphRequestConnection connection, id result, let error: NSError? ) -> Void in
if(error == nil)
{
print("fetched user: %#", result)
}
})
Now, your question about permission. When user is signing up(first time) at that particular point you ask for "Read permission" and "Publish permission" is used when you want to post something to his/her timeline.