How to update address of a facebook page through API - ruby

I am trying to update address/location of a facebook business page through API using koala ruby gem, so far no working solution.
page_access_token = "gw4t3434"
page_api = Koala::Facebook::API.new(page_access_token)
page_api.graph_call('me', {:location => {:street => "my street"}}, 'post') #error. Koala::Facebook::APIError: OAuthException: (#100) Parameters do not match any fields that can be updated
page_api.graph_call('me', {:location => {:address => "my street"}}, 'post') #error. Koala::Facebook::APIError: OAuthException: (#100) Parameters do not match any fields that can be updated
page_api.graph_call('me', {:address => "my street"}}, 'post')# not raise error but not working
page_api.graph_call('me', {:street => "my street"}}, 'post')# not raise error but not working
I can not find clear explanation either in facebook api reference regarding updating address in a page. I may missing something...

You can't write to the location object, only read. See "Updating Page Attributes" in the API. Also, there is no permission to request for writing to a location object.
An alternative is that you write to the Page's about section - this is allowed. Perhaps you can place an address reference here to meet the requirement of making address changes visible to the end user.

Related

How to integrate Google Picker with new Google Identity Services JavaScript library

Because of the known issue described in here (https://developers.google.com/identity/sign-in/web/troubleshooting) I want to update my application to be using the new gsi sign-in that uses less cookies than the previous versions and therefore might have the solution for the mentioned error...
My problem is that there's little to no documentation on how to integrate google picker with the new gsi.
I used to use gapi for some picker-related code like even loading the library gapi.load('picker', () => {}). The migration doc says to replace the apis.google.com/js/api.js with the new gsi url, and a lot of other methods such as googleAuth.signIn or gapi.client.init are now to be deprecated by 2023. But then:
How to load picker without gapi available? Or gapi still needs to be imported but will not contain any sign-in related methods?
How will I pass apiKey and scopes to be able to init googlePicker?
For methods such as GoogleAuth.isSignedIn docs simply states "Remove. A user's current sign-in status on Google is unavailable. Users must be signed-in to Google for consent and sign-in moments." what does that even mean? I need to check if user is signed in in order to not show again the popup every time they want to upload a file from gPicker...
Before, we used to have a access_token on the callback of a reloadAuthResponse or a signIn, now how do we get the token?
Sorry for the question being confusing, I'm very confused with everything. Any input helps, thanks!
I came across https://developers.google.com/identity/oauth2/web/guides/use-token-model through: How to use scoped APIs with (GSI) Google Identity Services
I changed our code to load this script: https://accounts.google.com/gsi/client, and then modified the our "authorize" function (see below) to use window.google.accounts.oauth2.initTokenClient instead of window.gapi.auth2.authorize to get the access_token.
Note that the callback has moved from the second argument of the window.gapi.auth2.authorize function to the callback property of the first argument of the window.google.accounts.oauth2.initTokenClient function.
After calling tokenClient.requestAccessToken() (see below), the callback passed to window.gapi.auth2.authorize is called with an object containing access_token.
const authorize = () =>
- new Promise(res => window.gapi.auth2.authorize({
- client_id: GOOGLE_CLIENT_ID,
- scope: GOOGLE_DRIVE_SCOPE
- }, res));
+ new Promise(res => {
+ const tokenClient = window.google.accounts.oauth2.initTokenClient({
+ client_id: GOOGLE_CLIENT_ID,
+ scope: GOOGLE_DRIVE_SCOPE,
+ callback: res,
+ });
+ tokenClient.requestAccessToken();
+ });
The way access_token is used was not changed:
new window.google.picker.PickerBuilder().setOAuthToken(access_token)
#piannone is correct, adding to their answer:
You'll still need to load 'client' code, as you're using authentication. That means you'll still include https://apis.google.com/js/api.js in your list of scripts. Only don't load 'auth2'. So, while you won't do:
gapi.load('auth2', onAuthApiLoad);
gapi.load('picker', onPickerApiLoad);
you will need to:
gapi.load('client', onAuthApiLoad);
gapi.load('picker', onPickerApiLoad);
(this is instead of directly loading https://accounts.google.com/gsi/client.js I guess.)

How to send to multiple recipients (WITHOUT LOOPING) while using variable alphanumeric sender ID?

I was wondering if there is a way to set multiple recipients WITHOUT looping over the list of recipients at my end?! Also most importantly while using variable alphanumeric sender ID and NOT buying a twilio number?
I can do all this for single recipient like this:
$twilio_client->messages->create(
'+64*******', //to
[
'from'=> 'foo',
'body' => 'bar'
]);
Works perfectly fine. However, doesnt work with multiple receivers.
Also note, it was bloody-1-step easy to implement smsbroadcast.com.au and pass all this in a simple call (simple call, quick fast, super easy documentation - unlike twilio which has like a billion lines of confusing documentation, 200 similar products and YET no direct api to check balance, or do a simple thing such as multiple recipients!!)
After a lot of back and through with the support, plus reading all the over-written-essay (so-called documentations), finally I found a way to get all that done.
[Step 1: Configuration]
You have to implement Notify product which is a separate product than the Message product.
So from left menu Notify> Service> add New. Here you need to add a Messaging Service and have it selected here for Notify.
On the Messaging Services page, it will ask you to buy a twilio number. Instead just click on Configure from the left menu and put in all the details you need.
Specifically and importantly, make sure you have Alpha Sender ID checked and a default Alpha Sender text entered there. This will be the default fallback in case if your api call fails to accept the from param.
.
[Step 2: API Call]
//$notify_service_SID = the SID from the Notify Service you added in step 1
$client = new Client($this->Account_SID, $this->auth_token);
$notify_obj = $client->notify->services($notify_service_SID);
//you need receivers in a JSON object such as the following, plus make sure numbers are starting with country code to ensure alpha sender works correctly
$receivers_json = [0=>'{"binding_type":"sms","address":"+614********"}']+[1=>'{"binding_type":"sms","address":"+614*******"}']
$call_ret = $notify_obj->notifications->create([
'toBinding'=> $receivers_json,
'body' => $msg, //actual message goes here
'sms' => [
'from'=> $sender //alphanumeric variable sender
],
]);
.
[Step 3: Check for errors]
There is no direct way to check all errors in twilio when implementing Notify. Here is my mixed approach.
Exception handling to the notifications->create call
$call_ret will have err if the Notify fails, but not when the Message fails. because Notify just passes the call to Message and there is no direct way to check Message errors over Notify call. So you would check for $call_ret['err']
Call the Alerts API; fetch all recent alerts, and match against the Notification SID you received from the last call.
--
Here is how to do the Alerts check:
$alerts = #$client->monitor->v1->alerts->read();
if(is_array($alerts))
foreach($alerts as $av)
{
$t = #$av->toArray();
#parse_str($t['alertText'], $alert_details);
if(isset($alert_details['notificationSid']) && $alert_details['notificationSid'] == $call_retx['sid'])
{
$alert_err = $alert_details['description'];
break;
}
}
$alert_err will carry an error if there was an error. Apart from this there is no direct way to do it. You can fetch these Alerts via crons or you can setup a webhook for them to do a call back. Or simply implement a one call simple api that does it all in super simple way such assmsbroadcast.

Ruby Rest-Client for writing invoice API

I'm new to Ruby and trying to use the Ruby gem 'rest-client' to access the REST API of my accounting system, e-conomic.com. I am able to connect via tokens and e.g. fetch customer details - so far, so good.
However, I'm struggling to figure out how to POST and thus create a new customer entry with e.g. address, name, mail etc.. In particular, I'm looking to get the code to both include my authentication token details (i.e. content of hHeader below), while also including a payload of customer details.
Details about the customer creation via the REST API:
https://restdocs.e-conomic.com/#post-customer-groups
Details about the rest-client ruby gem:
https://github.com/rest-client/rest-client
I'm running Ruby 2.3.3 on Windows 7 in the Atom editor.
My code is as below:
Dir.chdir 'C:\Ruby23\bin'
require 'rest-client'
require 'rconomic'
require 'json'
hHeader = {"X-AppSecretToken" => 'tokenID1_sanitized', "X-AgreementGrantToken" => 'tokenID2_sanitized', "Content-Type" => 'application/json'}
hCustomer = RestClient.get("https://restapi.e-conomic.com/customers/5", hHeader) # => creates a response showing customer 5 (shown for example of GET)
Your input would be much appreciated!
Martin
You put the wrong api doc, it's POST customer, not POST customer-groups. You should send the post with:
body = {'address' => 'Example Street', 'name' => 'John Doe'}.to_json
RestClient.post "https://restapi.e-conomic.com/customers/", body, hHeader)

How to check if Instagram image has been removed

I've been trying to detect if Instagram image has been removed to hide those photos in my DB.
Right now I'm storing Instagram image short codes. And accessing images with "https://instagram.com/p/#{shortcode}"
And if you access for example legit url with (Ruby):
open "https://instagram.com/p/1" then it returns 200 OK,
on the other hand random not existing page throws exception 404.
But sometimes it seems to throw 404 on legitimate page, thats why my code does things which it shouldn't do on them.
begin
link = "https://instagram.com/p/#{submission.image}"
submission.visible = true
open link, :allow_redirections => :all
rescue OpenURI::HTTPError => e
if e.message.include? '404 NOT FOUND'
submission.visible = false
end
end
Do you have any ideas?
You might need to use the API. Please check the media endpoints of Instagram's API if it helps:
https://instagram.com/developer/endpoints/media/#get_media

How to access Google Contacts API in ruby

I'm struggling to access the Google Contacts API.First I tried the google-api-ruby-client gem but it turned out that it does not support the Contacts API.
Next shot was the google_contacts_api gem. I used oauth2 to access the authentication key(Getting authentication token guide question). But after passing the token correctly to the api it is producing an error.
`<main>': undefined method `[]' for #<GoogleContactsApi::GroupSet:0x000000039fcad8>` (NoMethodError).
Here is my code.
# get token using oauth2 gem, and use it below in the google_contacts_api.
google_contacts_user = GoogleContactsApi::User.new(token)
contacts = google_contacts_user.contacts
groups = google_contacts_user.groups
# group methods
group = groups[0]
group.contacts
puts group.contacts
# contact methods
puts contacts.count
puts groups.count
contact = contacts[0]
contact.primary_email
contact.emails
What am I doing wrong?
UPDATE:
As #alvin suggested it is working now. But the group contacts are not being printed out. Instead it is printing #<GoogleContactsApi::ContactSet:0x000000020e49d8>.Example: here is what is printed by this code
groups = google_contacts_user.groups
# group methods
groups.each do |group|
group_contacts = group.contacts
puts group_contacts
end
Output:
#<GoogleContactsApi::ContactSet:0x000000020e49d8>
#<GoogleContactsApi::ContactSet:0x0000000504aec0>
#<GoogleContactsApi::ContactSet:0x0000000518dfd0>
#<GoogleContactsApi::ContactSet:0x000000052d9290>
#<GoogleContactsApi::ContactSet:0x000000054280d8>
#<GoogleContactsApi::ContactSet:0x0000000558c2f8>
#<GoogleContactsApi::ContactSet:0x00000005746eb8>
#<GoogleContactsApi::ContactSet:0x000000058a3ea0>
How can I print the group contacts?
Edited to add info about the Enumerable implementation
(I wrote the gem.)
There was a bug in the documentation. groups and contacts are instances of classes that implement Enumerable, which doesn't provide the [] method, but does provide the first method.
So, try groups.first instead of groups[0]. Likewise, use contacts.first instead of contacts[0]. My bad! (I probably did a to_a in my head.)
Response to Update
To answer the second half of the question, it looks like you found the relevant convenience methods for Contact and Group, in particular the Contact.primary_email method. See more methods in the (somewhat incomplete, sorry) YARD docs.
To get all the emails, you basically need to iterate over the returned contacts. As I mentioned in the updated response to the first part of your question, groups and contacts have all the methods of Enumerable. (Enumerable documentation). Here are some examples:
# What are all the groups called?
user.groups.map(&:title)
# Find group by title. (Returns nil if no such group.)
group = user.groups.select { |g| g.title = "Group Name" }
# Get all primary emails from a group
group.contacts.map(&:primary_email)
# Get all primary emails from all contacts regardless of group
user.contacts.map(&:primary_email)
You only need to use the Hashie::Mash methods to access data when no convenience accessor is provided (for example, if Google starts returning extra data the gem hasn't accounted for yet). The use case you described doesn't require this.
P.S. In the future, you might want to open a new question instead of editing your existing question.

Resources