Facebook Graph API and Action Links - ruby

I'm trying to replicate Facebook action links with the Open Graph API. I have the following snippet:
HTTParty.post("https://graph.facebook.com/me/feed", query: { message: "...", picture: "...", access_token: "...", actions: [{ link: "http://google.com", name: "Example" }] })
However it is returning (and I'm not sure why):
{"error":{"type":"OAuthException","message":"(#100) The post's action links must be valid URLs."}}
Anyone have any experience with action links using the graph API?

Note that the actions array should be JSON encoded, HTTParty might not do this automatically / correctly. Try
HTTParty.post(
"https://graph.facebook.com/me/feed",
:query => {
:message => "...",
:picture => "...",
:access_token => "...",
:actions => [{ link: "http://google.com", name: "Example" }].to_json
}
)
(Assuming you have a library included that provides Array#to_json…)

Related

Why is an Array in my payload being flattened in Sinatra / Rack::Test?

I'm trying to test a small Sinatra app using rspec. I want to pass a rather complex payload and am running into issues i do not understand: my payload contains an array of hashes. When I run the actual application this will work as expected, yet when I use the post helper to run my tests, the array will contain a merged hash:
post(
"/#{bot}/webhook",
sessionId: "test-session-#{session_counter}",
result: {
contexts: [
{ some: 'fixture' },
{ name: 'generic', parameters: { facebook_sender_id: 'zuck-so-cool' } }
]
}
)
In the sinatra handler I use params to access this payload:
post '/:bot/webhook' do |bot|
do_something_with(params)
end
When I now look at the structure of params when running the test suite, I will see the following structure:
[{"some" => "fixture", "name" => "generic", "parameters" => {"facebook_sender_id" => "zuck-so-cool"}}]
which I do not really understand. Is this a syntax issue (me being a ruby noob), am I using params wrong, or is this a bug?
EDIT: So i found out this is an "issue" with the way that Rack::Test will serialize the given payload when not specifying how to (i.e. as form data). If I pass JSON and pass the correct headers it will do what I expect it to do:
post(
"/#{bot}/webhook",
{
sessionId: "test-session-#{session_counter}",
result: {
contexts: [
{ some: 'fixture' },
{ name: 'generic', parameters: { facebook_sender_id: 'zuck-so-cool' } }
]
}
}.to_json,
{ 'HTTP_ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' }
)
Still I am unsure of this is an issue with the passed data structure not being possible to be serialized into form data or if this is a bug in the way that Rack::Test serializes data.
Looking at the relevant portion of the specs it looks like this is is expected behavior.

Mandrill template merge fail

I'm using mandrill to send emails from my API (in ruby with the mandrill-api gem), like signup confirmation email.
I have a merge tag in the template to put the username :
Hello *|USERNAME|*,
Thank you very much for installing the app! ...
...
My ruby code looks like that :
m = Mandrill::API.new ENV['MANDRILL_KEY']
template_name = "app-registration-welcome-email"
template_content = [{}]
message = {
:from_name=> "From Name",
:to=>[
{
:email => user.email,
:name => user.name,
}
],
:global_merge_vars => [{
:name => "username",
:content => user.name
}],
:merge_language => "mailchimp",
:merge => true,
:merge_vars => [{
:rcpt => user.email,
:vars => [{
:name => "username",
:content => user.name
}],
}],
:track_opens => true,
}
m.messages.send_template template_name, template_content, message
Unfortunately, when i receive the email, all is fine (to, name, from, ...) but the merge tag isn't replaced in the body and i still have *|USERNAME|* displayed.
What am I missing here?
You should only need to set USERNAME once, either in :global_merge_vars or :merge_vars.
If you're sending to just one recipient, it doesn't matter which you do.
If there are multiple recipients, use :merge_vars.
Try building message and then puts message.to_json and drop it into the debugger at https://mandrillapp.com/api/docs/messages.JSON.html#method=send-template (Click the 'Try it' button.) See if that gives you any clues.
You might also try using "USERNAME" instead of "username" as your variable name. The docs say merge vars are case-insensitive, but it's worth removing one more possible mismatch.

Confluence REST API create page with HTML content

I need to create a confluence page via the REST API. Creating a simple page is working, however if I try to add content to an existing HTML page I get http_response 400 (bad request).
Code snippet:
confluence_page_content = File.open("local_html_report", "r").read
json_data = {
"body" => {
"storage" => {
"representation" => "storage",
"value" => "#{confluence_page_content}"
}
},
"space" => {
"key" => "#{test_parameters["confluence_space"]}"
},
"title" => "TestPageFromChef",
"type" => "page"
}.to_json
Hy, solved it :)
Code snippet:
confluence_page_content = "<ac:structured-macro ac:name=\"html\">
<ac:plain-text-body><![CDATA[
#{confluence_page_content}
]]></ac:plain-text-body>
</ac:structured-macro>
"

Saving Point to a Google Fitness API (fitness.body.write)

Im trying to save a Point with float value into fitness.body.
Getting value is not a problem, while saving a new point causes 403. No permission to modify data for this source.
Im using DataSetId derived:com.google.weight:com.google.android.gms:merge_weight to find point and read value, and raw:com.google.weight:com.google.android.apps.fitness:user_input to insert data.
.
Here is a workflow using Ruby and google-api-ruby-client:
require 'google/api_client'
require 'google/api_client/client_secrets'
require 'google/api_client/auth/installed_app'
require 'pry'
# Initialize the client.
client = Google::APIClient.new(
:application_name => 'Example Ruby application',
:application_version => '1.0.0'
)
fitness = client.discovered_api('fitness')
# Load client secrets from your client_secrets.json.
client_secrets = Google::APIClient::ClientSecrets.load
flow = Google::APIClient::InstalledAppFlow.new(
:client_id => client_secrets.client_id,
:client_secret => client_secrets.client_secret,
:scope => ['https://www.googleapis.com/auth/fitness.body.write',
'https://www.googleapis.com/auth/fitness.activity.write',
'https://www.googleapis.com/auth/fitness.location.write']
)
client.authorization = flow.authorize
Forming my new data Point:
dataSourceId = 'raw:com.google.weight:com.google.android.apps.fitness:user_input'
startTime = (Time.now-1).to_i # 1 Second ago
endTime = (Time.now).to_i
metadata = {
dataSourceId: dataSourceId,
maxEndTimeNs: "#{startTime}000000000", # Faking nanoseconds with tailing zeros
minStartTimeNs: "#{endTime}000000000",
point: [
{
endTimeNanos: "#{endTime}000000000",
startTimeNanos: "#{startTime}000000000",
value: [
{ fpVal: 80 }
]
}
]
}
Attempting to save the point:
result = client.execute(
:api_method => fitness.users.data_sources.datasets.patch,
:body_object => metadata,
:parameters => {
'userId' => "me",
'dataSourceId' => dataSourceId,
'datasetId' => "#{Time.now.to_i-1}000000000-#{(Time.now).to_i}000000000"
}
)
And as I indicated previously im getting 403. No permission to modify data for this source
#<Google::APIClient::Schema::Fitness::V1::Dataset:0x3fe78c258f60 DATA:{"error"=>{"er
rors"=>[{"domain"=>"global", "reason"=>"forbidden", "message"=>"No permission to modif
y data for this source."}], "code"=>403, "message"=>"No permission to modify data for
this source."}}>
I believe, I selected all required permissions in the scope. I tried submitting the point to both accessible datasetid's for fitness.body.
Please let me know if im doing anything wrong here.
Thank you!
I encountered the same situation, turns out you can NOT insert data points directly into the datasource "raw:com.google.weight:com.google.android.apps.fitness:user_input". From the name, one might guess out this datasource is reserved. So the workaround is to add your own datasource, note should with dataType.name="com.google.weight", like this:
{
"dataStreamName": "xxxx.body.weight",
"dataType": {
"field": [
{
"name": "weight",
"format": "floatPoint"
}
],
"name": "com.google.weight"
},
"dataQualityStandard": [],
"application": {
"version": "1",
"name": "Foo Example App",
"detailsUrl": "http://example.com"
},
"device": {
"model": "xxxmodel",
"version": "1",
"type": "scale",
"uid": "xxx#yyy",
"manufacturer": "xxxxManufacturer"
},
"type": "derived"
}
then after the successful creation, you can use this datasource(datastream id) to insert your own data points, and then the inserted data points will also be included in the datasource "derived:com.google.weight:com.google.android.gms:merge_weight" when you do the querying with suffix "dataPointChanges".
Try adding an Authorization header:
result = client.execute(
:api_method => fitness.users.data_sources.datasets.patch,
:headers => {'Authorization' => 'Bearer YOUR_AUTH_TOKEN'},
:body_object => metadata,
:parameters => {
'userId' => "me",
'dataSourceId' => dataSourceId,
'datasetId' => "#{Time.now.to_i-1}000000000-#{(Time.now).to_i}000000000"
}
)

The merge tags in mandrill don't work in codeigniter

I use Mandrill plugin for Codeigniter.
I created HTML template through Mandrill account, named fess1 with merge tag FNAME, after I published it.
Example:
...
<p>
<span>Hi *|FNAME|*,<br></span>
</p>
....
Now I try to send mail from codeigniter like:
private function sendMailMandrill($owner_name,$business_name,$owner_email){
$message = array('dest_mail' => $owner_email);
$message['to'] = array(array('email' => 'mim#wefi.com'));
$mergeVars[] = array(
'rcpt' => array(array('email' => 'mim#wefi.com')),
'vars' => array(
array(
'name' => 'FNAME',
'content' => 'Fessy'
)
)
);
$message['merge'] = true;
$template_name = 'fess1';
$template_content = array( // I don't know what I need to provide here, left it empty
array(
'name' => 'example name',
'content' => 'example content'
)
);
$message['merge_vars'] = $mergeVars;
return $this->mandrill->messages_send_template($template_name, $template_content, $message);
}
The result:
I get the mail, based on fess1 template, but with the tag *|FNAME|*.
Sounds like Mandrill didn't recognize the merge tag.
I used mandrill->messages_send_template but since my template stored into Mandrill account I have no clue what I need to provide for $template_content.
So I wrote dummy info there.
Did I miss something?
Thank you,
[EDIT]
From logs this is what I send:
{
"template_name": "fess1",
"template_content": [
{
"name": "example name",
"content": "example content"
}
],
"message": {
"owner_name": "עידו",
"business_name": "פלאפל מוסקו",
"dest_mail": "maxim#wifi.com",
"to": [
{
"email": "maxim#wifi.com"
}
],
"merge": "true",
"merge_vars": [
{
"rcpt": [
{
"email": "maxim#wifi.com"
}
],
"vars": [
{
"name": "FNAME",
"content": "Fessy"
}
]
}
]
},
"key": "xxxxxxxxxxxxxxxx"
}
You can provide blank information for the template_content parameter. That parameter allows you to use mc:edit regions in your template. It is a required parameter, but a blank array will suffice if all of the content is in your template in Mandrill.
As for whether the merge_vars were recognized, the first thing we recommend is inspecting the API Logs for your account (Settings > API Logs) since that will show you the JSON that Mandrill received. You can then compare that to the expected JSON format from the Mandrill API docs: https://mandrillapp.com/api/docs/messages.JSON.html#method=send-template
It looks like your arrays may not be nested as expected. Once you view the JSON that's being generated as compared with the expected format, you can also view the PHP documentation for the Mandrill PHP client. It may not be identical to the CodeIgniter plugin, but should give you an idea of how the merge_vars parameter would be structured in PHP: https://mandrillapp.com/api/docs/messages.php.html
In mergeVars you created array instead key:value. Change it to:
'rcpt' => 'mim#wefi.com',

Resources