Google geocode format issue. Receiving undefined offset error - google-api

I get this PHP Notice: Undefined offset: 0 on line 9. It is regarding the Google Geocode API in the code provided below.
An undefined offset error occurs when you try to reference an array value at position 0 but that position doesnt exist. I am assuming the Google geocode API has changed within the last year. As it must be returning a different result structure then the one originally programmed with. However, although I know this, I cannot find anything wrong with the code. Does anyone know if the format of my code is incorrect?
The code below pulls the country and town fields from an input form. The Google Geocode works out the lat and lng of the town, then feeds this to the timezone API to calculate the timezone. I have hidden my API key for security purposes. Any help is appreciated. Thank you.
<?php
$town = urldecode($_GET['town']);
$country = urldecode($_GET['country']);
if(!empty($_GET['state'])){
$state = urldecode($_GET['state']);
}
$location = json_decode(#file_get_contents('https://maps.googleapis.com/maps/api/geocode/json?key=API_KEY_HERE&address='.urlencode($town.', '.(!empty($state) ? $state.', ' : '').$country)), true)['results'][0]['geometry']['location'];
$timezone = json_decode(#file_get_contents('https://maps.googleapis.com/maps/api/timezone/json?key=API_KEY_HERE&location='.$location['lat'].','.$location['lng'].'&timestamp='.date('U')), true);
$time = $timezone['rawOffset'] / 60 / 60;
echo $time;
?>

This part of your code is where the problem is:
)['results'][0]['geometry']['location']
You're assuming that there will always be a result at position 0 (the first item). In the case of an error the results array will be empty, and thus no result at position 0.
The API result structure hasn't changed. Google wouldn't do that, as it would break a LOT of applications. It's more likely that a particular set of inputs, such as an invalid address, are giving an error response.
Take a look at the documentation here. Pay attention to the "status" field, which contains a variety of status codes. You should modify your code to only try to get the item from the result if the status is "OK".
On the time zone side of things, you should check the status code there as well. (Here are the docs.) Then in most cases, you should take the timeZoneId rather than the rawOffset. You can use that ID with PHP's built-in time zone functionality (DateTime, DateTimeZone classes, etc.).

Related

How to get an event ID from the HitID returned by a Microsoft Graph search query?

I am trying to patch a calendar event with the Microsoft Graph API (from a Node express app).
I create a new event with client.api('/me/events').post(myEvent) and it works just fine (I see it appear in my calendar). The return value has an ID which is:
AAMkADc0Yjg2ODdmLTlkNDQtNGQ0Yi1iNjBmLTE1MDdmYzI4MGJkOABGAAAAAADt0ZJy6xMCRq23C8icFGeqBwAOM3XMH4d2SYMQ5psbvFytAAAAAAENAAAOM3XMH4d2SYMQ5psbvFytAAJ_B-B7AAA=
I then use client.api('/search/query').post(myQuery) to find the event based on some criteria, and this works fine. I receive an array of hits, with only one hit (which actually is the freshly created event, looking at the subject and body), and with a hitId equal to:
AAMkADc0Yjg2ODdmLTlkNDQtNGQ0Yi1iNjBmLTE1MDdmYzI4MGJkOABGAAAAAADt0ZJy6xMCRq23C8icFGeqBwAOM3XMH4d2SYMQ5psbvFytAAAAAAENAAAOM3XMH4d2SYMQ5psbvFytAAJ+B/B7AAA=
For some reason I don't understand why the 2 IDs are not fully identical: the _ is changed to +and -changed to /.
I now want to modify the event, and try to update it with
let newVal = hits[0].resource // hits is coming from the result returned by the search query
newVal.id = hits[0].hitId // needed because the 'resource' does not contain the id
client.api('/me/events/'+hitId).patch(newVal)
But I get an error: Resource not found for the segment 'B7AAA='.
Could you please tell me how to make the patch work (and explain why the ID from the search is not strictly like the one created). I have read several examples in the documentation (such as https://learn.microsoft.com/en-us/graph/search-concept-events) but I could not find a solution.
Many thanks!
So what is happening here is, PATCH /me/events/{hitId} is being resolved by Graph API such that the forward slash in the hitId denotes a path and Graph ends up using B7AAA= as a resource id hence the error Resource not found for the segment 'B7AAA='.
A work around that might work is to replace / in hitId(s) with %252F. You can do it like this.
client.api(`/me/events/${hitId.replace('/', '%252F')}`).patch(patch)
There is already this Issue on GitHub for documentation on how to handled these base64 encoded resource ids with /
As for the two IDs being non identical, Graph API will accept both of them and resolve to the same resource. I have no idea why they are different though.

Web Scrape returns N/A, not sure how to keep the data returning

totally new here & figured you guys will know the answer before I can even come near figuring this out.
I have a google form, feeding a live google sheet which users submit car reg numbers.
My goal is to have the reg number display the make, model besides the reg.
I have implemented an importXML function & the cell I expect to see the data loads up for a few minutes, then reverts to "N/A" or sometimes doesn't pull the data at all, but manually visiting the URL does return the data.
The import XML function uses a cell, made up of URL string, then adds the Reg/VIN input by form submission. That cell looks something like this "basicvehicledetails.com/reg" and returns the Class on the webpage relevant for Make/Model in separate cells.
I need the data to stay once it is returned, but don't know how to do that.
Another option is a car check website that requires a login, and then the reg to be input & searched before a webpage returns in-depth data on the car, is this something I can get to export to google sheet/excel spreadsheet?
I'm really stuck for this one, and would really appreciate any help as updating each car manually is painful.
try like:
=REGEXREPLACE(QUERY(ARRAY_CONSTRAIN(IMPORTDATA(
"https://www.motorcheck.ie/free-car-check/?vrm=152D1234"),5000,1),
"where Col1 contains 'dark-left'", 0), "</?\S+[^<>]*>", )
UPDATE:
=IMPORTHTML("https://www.cartell.ie/ssl/servlet/beginStarLookup?registration=152D1234",
"table", 1)

Cant get facebook date range working for events in ruby/koala

I am using ruby koala facebook graph API gem to retrieve events but cant restrict the events using a date range. I seem to be getting all events (even ones which have happened). What I am trying to do is get events is the next 200 days. I am using the following (ruby) code:
Koala.config.api_version = 'v2.10'
oauth = Koala::Facebook::OAuth.new app_id, app_secret
graph = Koala::Facebook::API.new oauth.get_app_access_token
from_date = Date.today
to_date = from_date + 200
fb_events = graph.get_object( fb_venue["url_listings"] + "?time_range={\"since\":#{from_date}, \"until\":#{to_date}" )
I am then getting the events 25 at once (the facebook default limit) using 'fb_events.next_page' to get them all.
I seem to get getting all events, including ones is the past.
Are you sure that the #get_object method wants a query string like that? Based on the docs[1], it seems that you should pass your object ID (which I assume is in fb_venue['url_listings'] for you as a first arg, and then metadata in a subsequent arg as a Hash. So I'd try something like:
fb_events = graph.get_object(fb_venue['url_listings'],
{since: from_date, until: to_date})
...according to the key/nesting structure FB expects.
Edit: forgot link to docs.
[1] -
http://www.rubydoc.info/github/arsduo/koala/Koala%2FFacebook%2FGraphAPIMethods%3Aget_object
According to the doc I don't think that you can request all the events, You can only select an event by using /{event-id} like this example or you can get user's events but you will need to ask him for the permission according to
permissions.
add user_events to the list of scope that you are permitting from user.
By this when user sign up using Facebook to your application it will take a permission for his events.
After that by using graph.get_object({facebook-user-id} + '/events') you will get 25 of his events as a default value and you can add {limit: 5} as a second parameter to the get_object function, You can use until and since but they should be in A Unix timestamp look at this to see the needed date format, hope this would help.

Lat/Lng Coordinate variables not recognized in ActiveRecord, forced to hard code

Hey guys I'm having the WEIRDEST issue while pairing on this rails app. We're using google maps api to grab lat and lng to do an ActiveRecord look up. For some odd reason the SomeModel.where("lat <=?", neLat) will not work BUT when I print neLat to the console and then copy the number and then hard code it to that query it works perfectly! I'm so stumped. Has anyone had any issues like this before?
This is an example of what I'm currently doing which doesn't work:
data = request.parameters
neLat = data['neLat'].to_f
#props = SomeModel.where("lat <=?", neLat)
47.6090933689332 is the number I see in my console/ActiveRecord query. One troubleshooting step I've taken was hard coding the number into a variable like this:
neLat = 47.6090933689332
#props = SomeModel.where("lat <=?", neLat)
I get the results I'm looking for this way, but I don't want to be hardcoding these coordinates. Another troubleshooting step I've taken was to make sure there wasn't a conflict with the float value so I went with this:
temp = "47.6090933689332"
neLat = temp.to_f
#props = SomeModel.where("lat <=?", neLat)
This didn't work either as it gave me the same results as the example just above.
EDIT:
I've provided more details as requested in the comments. Also, I realized I wasn't as clear as I could've been in my initial question. When I query I'm able to get my desired results back in the console, but the problem lies in the rendering of the results in my view. Any form of hardcoding will render correctly in my view, but when I use the values from my request.parameters is where the rendering fails. It will either render everything in the table or nothing in the table. So in the example below I can see that I'm getting 3 different properties from my properties table, but my view will render EVERYTHING in my table, which is like 7 properties.
Here is the raw sql query that ActiveRecord generates (this is the result of all 3 ways as I've done above):
SELECT `properties`.* FROM `properties` WHERE (lat >= 47.609093368933195)
#<Property:0x007fa333ac1880>
#<Property:0x007fa333ac1718>
#<Property:0x007fa333ac15b0>
As for the schema, it's just one table that I'm using and no joins.

Get all members from the mailing list using MailChimp API 3.0

http://kb.mailchimp.com/api/resources/lists/members/lists-members-collection
Using this resource we can obtain only first 10 members. How to get all?
The answer is quite simple - use offset and count parameters in URL query:
https://us10.api.mailchimp.com/3.0/lists/b5b5fdc2fa/members?offset=150&count=10
Finally I found PHP API client for MailChimp API v3:
https://github.com/pacely/mailchimp-api-v3
And official docs about pagination.. I missed it before :(
http://kb.mailchimp.com/api/article/api-3-overview
I stumbled on this one while researching a way to get all list members in MC API 3.0 as well. I noticed that there were some comments on the API timing out when trying to get all list members on one page. I also encountered this at first but was able to overcome it by limiting the fields in the result by using the 'fields' param. My code is for a mass deleter so all I really needed was the ID of each member to put together a batch delete request. Here's how my fetch request looks (psuedo-code):
$total_members = $result['total_items'];//get number of members in list via previous request
https://usXX.api.mailchimp.com/3.0/lists/foobarx/members?fields=members.id&count=total_members
This way I'm able to fetch over 15,000 subscribers on one page without error.
offset and count is the official way on the docs, but the problem is that has linear slowdown. It appears to be an n^2 solution, so if you have 20,000 items, you're in trouble. Their docs http://developer.mailchimp.com/documentation/mailchimp/reference/lists/members/#read-get_lists_list_id_members warn you against using offset.
If you're scenario permits you to use other filters (like since_last_changed), then you can do it quickly. See What is the right syntax for "timeframe" in MailChimp API 3.0 for format for datetime.
Using offset and count parameters are correct as mentioned in some of the other answers, but becomes tedious for large lists.
A more efficient way, is to use a client for the MailChimp API. I used mailchimp3 for python. Using this, it's pretty easy to get all members on your list because it handles the pagination. Here's how you would do it.
from mailchimp3 import MailChimp
client = MailChimp('YOUR_USERNAME', 'YOUR_SECRET_KEY')
client.lists.members.all('YOUR_LIST_ID', get_all=True, fields="members.email_address")
You can do it just with count, making an API call to the list root so in the next API call you include the count parameter and you have all your list members.
I ran into issues with this because I had a moderate list with 2600 members and MailChimp was throwing an error, but it worked with 1500 people.
So for a list bigger than 1500 members I use MailChimp export API bare in mind that this is going to get discontinued but I could not find any other acceptable solutions.
Alternatively for bigger lists (>1500) you could get the total of members and then make multiple api calls to the Member endpoint but I really dislike that :(
If anyone has a better alternative I would be really glad to hear it.
With MailChimp.Net.
Use the offset value.
List<Member> listMembers = new List<Member>();
IMailChimpManager manager = new MailChimpManager(MailChimpApiKey);
bool moreAvailable = true;
int offset = 0;
while (moreAvailable)
{
var listMembers = manager.Members.GetAllAsync(yourListId, new MemberRequest
{
Status = Status.Subscribed,
Limit = 250,
Offset = offset
}).ConfigureAwait(false);
var Allmembers = listMembers.GetAwaiter().GetResult();
foreach(Member member in Allmembers)
{
listMembers.Add(member);
}
if (Allmembers.Count() == 250)
//if the count is < of 250 then it means that there aren't more results
offset += 250;
else
moreAvailable = false;
}

Resources