Getting nil values when request ride details Uber - swift

I'm trying to fetch details of rides that didn't originate in my app but keep getting nil values.
I first login using the Uber iOS SDK and request history / all-trip scopes. I then fetch the ride history. Using request-ids from ride history, I fetch ride details.
In every ride object returned, all values except status, requestID and ProductID are always nil.
I'm aware this is a privileged scope, and haven't requested full access yet. My user should work as it's on the dev dashboard though.
Any idea? Thanks!
let ridesClient = RidesClient()
//Fetch history of most recent rides
ridesClient.fetchTripHistory(offset: 0, limit: 20) { (history, response) in
if (response.error == nil){ //Success
if let history = history {
//Loop into trips
for trip in history.history {
//Fetch trip details
ridesClient.fetchRideDetails(requestID: trip.requestID, completion: { (ride, response) in
//Ride object is valid but everything in it is nil
})
}
}
}
else { //Error
print(response.error?.description as Any)
}
}
Screenshot to trip object

You are getting a valid response back from the /v1.2/requests/51c4db1d-2f3d-4c8a-8577-e02490c30e22 endpoint call. This trip is completed - so you will be able to get only trip status. If you are getting "null" values when you call this endpoint - there are no any issues with the call and response you are getting back - it is intentionally made to be "null".

Related

Why User Logs In But is Not Authenticating Sporadically In Firebase?

So I have a weird bug that I can't seem to track down. I'm using firebase functions on the backend and SwiftUI. My login flow goes like this:
User logs in from loginView. The loginView then uses a callback to pass a user to move on to the next View after a user logs in.
After this a user is passed to the View where it calls the firebase functions.
The problem is that every once in a while a user fails authentication. This doesn't happen every time and usually happens when a user has not logged in for 12 hours or more. I thought it may have been a race condition at first but after further investigation decided that it wasn't given the fact that it's using a callback.
Has anyone else experienced anything similar? If so is there any way to fix this?
I have tried making my firebase function stay warm by setting minimum instances to 1 because I initially thought it may be a cold start issue but this hasn't helped.
Any help would be greatly appreciated. Thanks.
On the frontend the code is pulling like so:
FirebaseAuthService().signIn(email: email, password: password) { result, error in
if (error?.occurred) != nil {
self.errorMessage = error!.details
self.state = .failed
self.showErrorAlert = true
return
}
if (localAuthEnabled) {
...... This piece of code works
FirebaseFirestoreService().fetchUser(userID: result?.user.uid ?? "", completion: { user, error
....... This piece of code works.
}
})
}
User is then taken to another view AFTER logging in
This view pulls from 5 or so firebase functions asynchronously (but the user is already logged in by this point). The function that it fails at is as follows
self.function.httpsCallable("api-report").call() { (result, error) in
... It is at times it gives me an auth error inside of this function.
}
I am using this to log out whenever a user put the app in the background or hits the log out button:
func signOut() -> Bool {
do {
try Auth.auth().signOut()
self.session = nil
return true
} catch let err as NSError {
print("Error signing out: %#", err)
return false
}
}
on the backend the report call does the following with the report. This is a large function. I have only added the call to show whats going on.
exports.handler = async (data, context) => {
if (!context.auth) {
console.log("report error context");
console.log(context);
throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' +
'by authenticated users.', 'User must be authenticated');
}
}
It seems the call to your backend may be happening just as/after the user is logged out, or their token is being refreshed. If it's the token being refreshed, the client should just retry the call in cases such as this.
You could also check whether the token is about to expire, and force a refresh when that is the case, or delay calling the Cloud Function until the token has refreshed.

GetStream add activity fails due 403

Trying out GetStream for Swift, I am not able to add an activity.
class MyActivity : Activity {}
...
let client = Client(apiKey: <MyApiKey>, appId: <MyApiKey>, token: <Token>)
let ericFeed = client.flatFeed(feedSlug: "user", userId: "eric")
let activity = MyActivity(actor: "eric", verb: "waves", object: "picture:10", foreignId: "picture:10")
ericFeed.add(activity) { result in
print("!result!")
print(result)
}
The token is generated server-side, is in form eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiZXJpYyJ9.AAAAAAAAAAAAAAAAA-AAAAAAAAAAAAAAAA-AAAAAAAA and:
client.currentUserId returns eric (So, the token is correct?)
The Callback of ericFeed.add(activity) is not called
On my app's dashboard log, I see the attempt of adding the activity as failed, with error 403
I tried different ids (with different tokens), both actor: "eric" and actor: "user:eric". What could have gone wrong?
The code to generate the token (php server) is:
$userId = "eric";
$client = new GetStream\Stream\Client(<MyApiKey>, <MyAppSecret>);
$userToken = $client->createUserSessionToken($userId);
And I receive to logs on my dashboard:
There is a couple things that needs to keep in mind.
First of all, probably your client was deallocated when the request was ended and that's why the callback wasn't called, but logs could show you that the request was done. I suggest you to use a shared Client instance and it would be easy to use. To setup a shared Client you need to write this:
Client.config = .init(apiKey: "<MyApiKey>", appId: "<MyApiKey>", token: "<Token>")
More about the Client setup in wiki page.
The second important thing, that you have to create/update your Stream user. From the server side you are getting your Token with the Stream userId and can request the Stream user. The easiest way is to call Client.shared.create(user:) where user would be created/updated. So, it's still a part of the Stream Client setup:
Client.shared.create(user: GetStream.User(id: Client.shared.currentUserId!)) { result in
// Update the client with the current user.
Client.shared.currentUser = try? result.get()
// Do all your requests from here. Reload feeds and etc.
}
More info in docs.
I suggest you to create feeds with only feedSlug parameter and the Stream userId would be taken from the Token. But it would be Optional, because the currentUserId is optional. For example:
let ericFeed = Client.shared.flatFeed(feedSlug: "user")
ericFeed?.add(activity)
And for your activities, Stream clients should always use the current Stream user as an actor. So, we need to update the definition of your MyActivity.
Finally, here is your code that should works:
// Define your activity.
class MyActivity: EnrichedActivity<GetStream.User, String, DefaultReaction> {
// ...
}
// Setup Stream Client.
Client.config = .init(apiKey: <MyApiKey>, appId: <MyApiKey>, token: <Token>)
// Setup the current user.
Client.shared.getCurrentUser {
let ericFeed = Client.shared.flatFeed(feedSlug: "user")
let activity = MyActivity(actor: Client.shared.currentUser!, verb: "waves", object: "picture:10", foreignId: "picture:10")
ericFeed?.add(activity) { result in
print("!result!")
print(result)
}
}

How to decorate Siesta request with an asynchronous task

What is the correct way to alter a Request performing an asynchronous task before the Request happens?
So any request Rn need to become transparently Tn then Rn.
A little of background here: The Task is a 3rd party SDK that dispatch a Token I need to use as Header for the original request.
My idea is to decorate the Rn, but in doing this I need to convert my Tn task into a Siesta Request I can chain then.
So I wrapped the Asynchronous Task and chained to my original request.
Thus any Rn will turn into Tn.chained { .passTo(Rn) }
In that way, this new behaviour is entirely transparent for the whole application.
The problem
Doing this my code end up crashing in a Siesta internal precondition:
precondition(completedValue == nil, "notifyOfCompletion() already called")
In my custom AsyncTaskRequest I collect the callbacks for success, failure, progress etc, in order to trigger them on the main queue when the SDK deliver the Token.
I noticed that removing all the stored callback once they are executed, the crash disappear, but honestly I didn't found the reason why.
I hope there are enough informations for some hints or suggests.
Thank you in advance.
Yes, implementing Siesta’s Request interface is no picnic. Others have had exactly the same problem — and luckily Siesta version 1.4 includes a solution.
Documentation for the new feature is still thin. To use the new API, you’ll implement the new RequestDelegate protocol, and pass your implementation to Resource.prepareRequest(using:). That will return a request that you can use in a standard Siesta request chain. The result will look something like this (WARNING – untested code):
struct MyTokenHandlerThingy: RequestDelegate {
// 3rd party SDK glue goes here
}
...
service.configure(…) {
if let authToken = self.authToken {
$0.headers["X-Auth-Token"] = authToken // authToken is an instance var or something
}
$0.decorateRequests {
self.refreshTokenOnAuthFailure(request: $1)
}
}
func refreshTokenOnAuthFailure(request: Request) -> Request {
return request.chained {
guard case .failure(let error) = $0.response, // Did request fail…
error.httpStatusCode == 401 else { // …because of expired token?
return .useThisResponse // If not, use the response we got.
}
return .passTo(
self.refreshAuthToken().chained { // If so, first request a new token, then:
if case .failure = $0.response { // If token request failed…
return .useThisResponse // …report that error.
} else {
return .passTo(request.repeated()) // We have a new token! Repeat the original request.
}
}
)
}
}
func refreshAuthToken() -> Request {
return Request.prepareRequest(using: MyTokenHandlerThingy())
.onSuccess {
self.authToken = $0.jsonDict["token"] as? String // Store the new token, then…
self.invalidateConfiguration() // …make future requests use it
}
}
}
To understand how to implement RequestDelegate, you best bet for now is to look at the new API docs directly in the code.
Since this is a brand new feature not yet released, I’d greatly appreciate a report on how it works for you and any troubles you encounter.

Facebook Graph API Ad Report Run - Message: Unsupported get request

I'm making an async batch request with 50 report post request on it.
The first batch request returns me the Report Ids
1st Step
dynamic report_ids = await fb.PostTaskAsync(new
{
batch = batch,
access_token = token
});
Next I'm getting the reports info, to get the async status to see if they are ready to be downloaded.
2st Step
var tListBatchInfo = new List<DataTypes.Request.Batch>();
foreach (var report in report_ids)
{
if (report != null)
tListBatchInfo.Add(new DataTypes.Request.Batch
{
name = !ReferenceEquals(report.report_run_id, null) ? report.report_run_id.ToString() : report.id,
method = "GET",
relative_url = !ReferenceEquals(report.report_run_id, null) ? report.report_run_id.ToString() : report.id,
});
}
dynamic reports_info = await fb.PostTaskAsync(new
//dynamic results = fb.Post(new
{
batch = JsonConvert.SerializeObject(tListBatchInfo),
access_token = token
});
Some of the ids generated in the first step are returning this error, once I call them in the second step
Message: Unsupported get request. Object with ID '6057XXXXXX'
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
I know the id is correct because I can see it in using facebook api explorer. What am I doing wrong?
This may be caused by Facebook's replication lag. That typically happens when your POST request is routed to server A, returning report ID, but query to that ID gets routed to server B, which doesn't know about the report existence yet.
If you try to query the ID later and it works, then it's the lag. Official FB advice for this is to simply wait a bit longer before querying the report.
https://developers.facebook.com/bugs/250454108686614/

Facebook get number of sent requests and accepted request

i need to make a page that will have a request dialog for a facebook page or a facebook app.
I need to get the number of friends the user sent the request to and at the end of the day the number of request that got accpeted from the specific user.
The scenario is for giving awards , the user that sent the most request to freinds gets an award and the user that had the most requests accepted also gets an award.
I dont know if the seccond is possible , but i think it should be , couse games on FB give u points for sent request and also u get new missions when friends accept your request , so there mut be a way.
--
I will record the number of invites sent.
Return Data
request_ids
A comma-separated list of the request_ids that were created. To learn who the requests were sent to, you should loop through the information for each request object identified by a request id.
FB.ui({
method: 'apprequests',
title:'Suggest '+fbAppName+' to your friends',
message: 'I thought you would dig this app!',
data: 'gameID=96'
}, onInviteFriend);
//jquery required for ajax function
onInviteFriend = function(response) {
if (response && response.request_ids) {
var idsLength = response.request_ids.length;
var idList = "";
var data = {};
var ajaxSettings = {};
for (var i = 0; i < idsLength; i++){
idList += response.request_ids[i];
if (i < idsLength-1){
idList += ",";
}
}
if (idsLength > 0){
data.idList = idList;
ajaxSettings = {
type: "GET",
url: sketchnpass.root+"/ajax/log-invite-sent/",
data: data,
success: sketchnpass.onSaveInvites
};
$.ajax(ajaxSettings);
}
//was published
} else {
//was not published
}
}
i think using the code above i can get the number of sent requests.
But when some1 accepts the request how will i know that happened , does the accepted request send the user to my app along with some data?
The Facebook requests dialog documentation basically walks you through how to do this.
When requests are sent, request_ids is returned as return data so you would want to log this information in your system to track who sent how many requests.
To track accepted invitations, the documentation says that this url is called: http://apps.facebook.com/[app_name]/?request_ids=012345678910 so you would just need to parse the request id and look that request id up in your system and mark it as accepted.