Podio API - Invalid token during project tasks sync - podio

We're currently receiving this 400 error when trying to fetch new tasks:
{"error_parameters":{},"error_detail":null,"error_propagate":false,"request":{"url":"http:\/\/api.podio.com\/task","query_string":"completed=true&completed_on=-5d&fields=completed_on&limit=100&offset=0&sort_by=rank&sort_desc=false&space=3798819","method":"GET"},"error_description":"Invalid token '(files,tags,votes)'","error":"invalid_value"}
Just so you know we don't use this for our internal purposes, instead we have an integration set up that allows tasks sync'ing and completion.
We're doing a loop to paginate through all the space tasks:
get('/task', { space: project_link.remote_id, sort_by: 'rank', limit: limit, offset: offset, sort_desc: false, completed: completed, fields: 'completed_on' })
EDIT:
def sync_project(project_link)
existing_remote_ids = _synced_remote_task_ids(project_link.link_id)
synced_project_ids = []
[{completed: false}, {completed: true}].each do |params|
offset = 0
loop do
tasks, next_offset = tasks_page_for_project(project_link: project_link, offset: offset, **params)
tasks.each do |task|
remote_task = map_podio_task(task, project_link.link_id)
_process_task(remote_task)
synced_project_ids << remote_task[:id].to_s
end
offset = next_offset
break unless next_offset
end
end
_mark_tasks_deleted(existing_remote_ids - synced_project_ids)
end
def tasks_page_for_project(project_link:, offset:, completed: false)
next_offset = nil
limit = 100
params = { space: project_link.remote_id, sort_by: 'rank', limit: limit, offset: offset, sort_desc: false, completed: completed, fields: 'completed_on' }
params[:completed_on] = '-5d' if completed
tasks = get('/task', params)
if tasks.size == limit
next_offset = offset + limit
end
return tasks, next_offset
rescue TaskSync::ProjectRemovedError => ex
raise TaskSync::ProjectRemovedError.new(self, project_link.remote_id), ex.message
rescue TaskSync::TemporaryNetworkError => ex
ex.project_id = project_link.remote_id
raise ex
end
def service
check_token
#service ||= build_client(href, 'Authorization' => "OAuth2 #{token[:token]}")
end
def authorization
params = {
grant_type: 'refresh_token',
client_id: TaskSync.config[:podio][:client_id],
client_secret: TaskSync.config[:podio][:client_secret],
refresh_token: token[:refresh_token]
}
build_client 'https://podio.com/oauth/token', { 'Content-Type' => 'application/x-www-form-urlencoded' }, params
end
def href
'https://api.podio.com'
end
And this error only occurs for a single client.
Can you tell us what this error means? Is it OAuth related or does it have to do with something else?
Thanks!

Thanks for reporting spotted issue in Podio documentation. It was misleading here (updated docs are already published).
Format for completed_on field is YYYY-MM-DD-YYYY-MM-DD.
E.g. for all tasks completed in Jun 2017: 2017-06-01-2017-06-30

you did not mention what programming language you are using here is an example I wrote on PHP :
require_once 'podio/PodioAPI.php'; //podio library
error_log("validate triggerd");
$client_id = 'your client Id';
$client_secret = 'your client secret';
$app_id = 'your app id';
$app_token = 'your app token';
Podio::setup($client_id, $client_secret);
// Turn on debugging
Podio::$debug = true;
// Authenticate the app
Podio::authenticate('app', array('app_id' => $app_id, 'app_token' => $app_token));
and get your item:
$tasks = PodioTask::get_all( $attributes = array() );

Related

Telegram bot: loop on database query

I have a simple bot (I am using webhook) that responds to a command and goes to the database and sends a sticker and a simple html message for every record found.
If there are many records (20 or more AND took more than 2 minutes to finish the while bucle) bot goes crazy and display the results 4 times (finish one time and then starts again 3 more times), I tried to add a sleep() timer to avoid the loop but have no luck. Not sure what I am missing or doing wrong.
Here's my code:
$update = json_decode(file_get_contents('php://input'));
if (isset($update->message)){
//Fetching update
$message = $update->message;
$message_id = $update->message->message_id;
$text = $message->text;
$chat_id = $message->chat->id;
switch($text){
case "read":
$age = 18;
read_fields($age, $chat_id);
break;
default:
bot('SendMessage',[
'chat_id' => $chat_id,
'text' => "This is a test"
]);
}
}
function read_fields($age, $chat_id){
include("conexion.inc");
$i = 0;
$sticker = "";
$id = "";
$name = "";
$sql = "SELECT id, name, sticker FROM Persons WHERE age = ".$age;
$php = mysql_query($sql, $con);
while($row=mysql_fetch_assoc($php)){
$sticker = $row['id_sticker'];
$id = $row['id'];
$name = $row['name'];
bot('sendSticker',[
'chat_id' => $chat_id,
'sticker' => $id_sticker
]);
$message = $id."-<b>".$name."</b>";
bot('SendMessage',[
'chat_id' => $chat_id,
'parse_mode' => "HTML",
'text' => $mensaje
]);
sleep(3);
$i++;
}
bot('SendMessage',[
'chat_id' => $chat_id,
'text' => "### ".$i." total ### "
]);
}
Telegram Bot API will retry webhook request when server-side consider there are dropped, so you need to reduce response time.
One solution is process them quickly, but it seems not easy.
If you know how to close HTTP connection before timeout, just do that, since it's implement is different from your HTTP server, try to search like NginX fastcgi close upstream connection.

Phoenix API: How do I test a POST / create when I don't know the ID of the new resource?

I have an a POST /api/v1/users endpoint for creating a user. This is my failing test for it:
test "success" do
user_params = %{
user: %{
email: "eric#spaghetti.com",
image_url: "https://www.google.com/images/spaghetti",
}
}
conn = build_conn(:post, "/api/v1/users", user_params)
response = Router.call(conn, #opts)
assert response.status == 201
assert Repo.get_by(User, %{email: user_params.user.email})
assert response.resp_body == %{
id: "how would I know this??", #<---------this would fail since I have no way of knowing what this value would be
email: user.email,
image_url: user.image_url,
} |> Poison.encode!
end
My endpoint returns 3 fields: email, image_url, and id. I am currently unable to get this test to pass because there's no way I can tell what the ID of the newly created resource will be. Is there a better way to test this?
I normally skip checking for the exact value id in such cases, instead checking only if it exists:
%{email: email, image_url: image_url} = user
assert %{
"id" => _,
"email" => ^email,
"image_url" => ^image_url,
} = Poison.decode!(response.resp_body)
You can also assert that id is an integer:
assert %{
"id" => id,
"email" => ^email,
"image_url" => ^image_url,
} = Poison.decode!(response.resp_body)
assert is_integer(id)

Ruby integration with mailchimp-api gem

I'm trying to subscribe a single email to multiple lists with RoR and the official mailchimp-api gem. It works, but the last four values (double_optin, update_existing, replace_interests, and send_welcome) are not updating and I get an error that the email "already exists" even though I'm trying to pass the update_existing as true. I've written Mailchimp several times and they feel they've reached the end of their assistance. They have said they are not experts in the wrapper--even if it is the "official" gem--and cannot help me further. My code looks like this:
responses << mailchimp_lists.each do |ml|
mailchimp.lists.subscribe(
ml,
{ "email" => order.customer_email,
"euid" => order.customer_id,
"leid" => ""
},
{ "FNAME" => order.customer_first_name,
"LNAME" => order.customer_last_name,
"COMPANY" => order.company_name,
"ADDRESS1" => order.billing_address_1,
"ADDRESS2" => order.billing_address_2,
"CITY" => order.billing_city,
"STATE" => order.billing_state,
"POSTALCODE" => order.billing_zip,
"SALUTATION" => ""
},
"html",
false,
true,
false,
false
)
end
I've tried sending the last four params in several different ways such as:
"email_type" => "html",
"double_optin" => false,
Or:
{"email_type" => "html"},
{"double_optin" => false}
At times, Mailchimp can see the params arrive in such a way that it seems it should not be triggering an "email already exists" error, but it just won't work. Any help is appreciated.
The mailchimp-api gem's documentation describes the subscribe method as:
#subscribe(id, email, merge_vars = nil, email_type = 'html', double_optin = true, update_existing = false, replace_interests = true, send_welcome = false)
While the batch_subscribe shows:
#batch_subscribe(id, batch, double_optin = true, update_existing = false, replace_interests = true)
Note that the batch method does not include a "send_welcome" param. When I removed it from my list of params for the subscribe method--essentially sending three booleans instead of four as suggested, the update_existing worked perfectly. Seems like an error in the documentation here: http://www.rubydoc.info/gems/mailchimp-api/2.0.4/Mailchimp/Lists#subscribe-instance_method
Hopefully this helps someone else!

How do conditionally add or remove members from Rails 3.2 Arel method chain?

I am duplicating my includes, where, order, and paginate methods because I don't know if there is a block for Arel chains or better way to make this DRY. Is there something that makes it easy to test for the specialty_id or facility_id in params without using a long where string with ternary operators?
class << self
def list(options = {})
facility_id = options[:facility_id] || nil
keywords = options[:keywords] || nil
page = options[:page] || nil
specialty_id = options[:specialty_id] || nil
jobs = self.arel_table
unless keywords.nil?
keywords = keywords.downcase.tr_s('^a-z0-9 ', '').tr_s(' ', '\%')
end
if !specialty_id.blank?
approved.
includes(:facility, :specialties, :videos).
where(jobs[:name].matches("%#{keywords}%")).
where(specialties: {id: specialty_id}).
order(jobs[:name]).
paginate(page: page, per_page: 20)
elsif !facility_id.blank?
approved.
includes(:facility, :specialties, :videos).
where(jobs[:name].matches("%#{keywords}%")).
where(facilities: {id: facility_id}).
order(jobs[:name]).
paginate(page: page, per_page: 20)
else
approved.
includes(:facility, :specialties, :videos).
where(jobs[:name].matches("%#{keywords}%")).
order(jobs[:name]).
paginate(page: page, per_page: 20)
end
end
end
query = approved
query = query.includes(:facility, :specialties, :videos)
query = query.where(jobs[:name].matches("%#{keywords}%")) if jobs[:name].present?
query = query. ...
query = query.paginate(page: page, per_page: 20)
query.to_a
You should be able to chain these together to build it up prior to execution.
Something like this should be possible:
scoped.tap do |query|
query.
approved.
includes(:facility, :specialties, :videos).
where(jobs[:name].matches("%#{keywords}%"))
query.where(specialties: { id: specialty_id }) if specialty_id.present?
query.where(facilities: { id: facility_id }) if facility_id.present?
query.order(jobs[:name]).paginate(page: page, per_page: 20)
end
For more info on scoped see here.

Is there a Facebook Credits Ruby On Rails gem out there yet? Or ruby version of their Facebook Credits sample app?

I am wanting to implement Facebook Credits in my Facebook app. Does anyone know of a version of the Facebook Credits sample app available in Ruby on Rails? Has anybody made a gem for this yet? If I find one I'll link below...
Here is my code taking the FB example and RORing it:
require 'facebook_signed_request.rb'
class FacebookCreditsController < ApplicationController
skip_before_filter :verify_authenticity_token
layout nil
def index
facebook_request = FacebookSignedRequest.new(request.params['signed_request'])
data = { "content" => {} }
# handle invalid request
if !facebook_request.valid?
return
end
signed_request = facebook_request.signed_request
# handle invalid signed request
if signed_request.nil?
return
end
method = request.params['method']
order_id = request.params['order_id']
# second state response from facebook
if method == 'payments_status_update'
status = request.params['status']
if status == 'placed'
next_state = 'settled'
data['content']['status'] = next_state
elsif status == 'settled'
redirect_to '/lots'
return
end
# compose returning data array_change_key_case
data['content']['order_id'] = order_id
# first stage response from facebook
elsif method == 'payments_get_items'
order_info = request.params['order_info']
item = JSON.parse(order_info)
item['price'] = item['price'].to_i
# for url fields, if not prefixed by http://, prefix them
url_key = [ 'product_url', 'image_url' ]
url_key.each do |key|
if item[key][0..6] != 'http://'
item[key] = "http://#{item[key]}"
end
end
# if payload['test_mode']
if request.params['test_mode']
update_keys = ['title', 'description']
update_keys.each do |key|
item[key] = '[Test Mode] ' + item[key]
end
end
data['content'] = [item]
end
data['method'] = method
render :json => data
end
end
Then in addition to this there is:
require 'base64'
require 'json'
require 'openssl'
class FacebookSignedRequest
attr_reader :signed_request
def initialize(signed_request)
#signed_request = signed_request
end
def base64_url_decode str
encoded_str = str.gsub('-','+').gsub('_','/')
encoded_str += '=' while !(encoded_str.size % 4).zero?
Base64.decode64(encoded_str)
end
def valid?
# TODO: move it to some configuration
secret = " << my secret is here >>"
# decode data
encoded_sig, payload = signed_request.split('.')
sig = base64_url_decode(encoded_sig).unpack("H*")[0]
data = JSON.parse base64_url_decode(payload)
if data['algorithm'].to_s.upcase != 'HMAC-SHA256'
# Rails.logger.error 'Unknown algorithm. Expected HMAC-SHA256'
return false
end
#check sig
expected_sig = OpenSSL::HMAC.hexdigest('sha256', secret, payload)
if expected_sig != sig
# Rails.logger.error 'Bad Signed JSON signature!'
return false
end
data
end
I don't know if this helps anyone else but it's all working for me. Sorry for taking so long to remember to come back and post my working code...
View related code as requested:
#view
<%= javascript_include_tag "premium_signup" %>
<script type="text/javascript">
$(document).ready(function() {
$('#premium_signup_button').click(function() {
signupAsPremiumMember('Premium Membership', 'Create unlimited auctions with no extra charge at all for 1 year.', "1", '', '');
});
});
</script>
...
<button id="premium_signup_button">Signup as a premium member</button>
#premium_signup.js
function signupAsPremiumMember(title, desc, price, imageURL, productURL) {
var order_info = {
"title": title,
"description": desc,
"price": price,
"image_url": imageURL,
"product_url": productURL
};
var payload = {
"method": 'pay',
"order_info": order_info,
"purchase_type": 'item'
};
console.log(FB.ui(payload, facebookPurchaseCompletionCallback));
}
function facebookPurchaseCompletionCallback(data) {
if (data['order_id']) {
console.log(data['order_id']);
}
else if (data['error_code']) {
console.log(data['error_code']);
}
else {
console.log("failed");
}
}
#in the layout
#in head
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script src="http://connect.facebook.net/en_US/all.js"></script>
<%= javascript_include_tag 'application' %>
#in body
<div id="fb-root"></div>
<script>
FB.init({
appId : '############',
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
Now all of this is coming from a guy who sat down and learned to program in Ruby On Rails with as little supporting Javascript knowledge as I can get away with, in about 12 weeks last year with a few more weeks thrown in this year for good measure. I say that by way of caution - the code I've posted might be garbage... but it works :-)
And if anyone actually finds any of this useful a VOTE UP on the answer would be appreciated - just sayin' :-)