Koala and Omniauth-twitter don't go together - ruby

I posted the same in github of Koala but noone answered to me so I put here.
So when I try to login with Twitter with Omniauth:
I, [2013-11-15T18:57:12.371006 #28412] INFO -- omniauth: (twitter) Request phase initiated.
127.0.0.1 - - [15/Nov/2013 18:57:13] "GET /auth/twitter HTTP/1.1" 500 144366 0.9355
I have also a Koala login to facebook I don't use Omniauth for Facebook I just use Omniauth for twitter, If I don't require Koala is ok, but if I have both it generates:
undefined method `[]=' for #<Koala::Facebook::OAuth:0x00000001b03348>
~>In oauth.rb line 31
I'm using 1.6.0 version of Koala and Sinatra.
My code is:
#Facebook
get '/loginfb' do
session['oauth'] = Koala::Facebook::OAuth.new($APP_ID, $APP_SECRET, "#{request.base_url}/callbackfb")
redirect session['oauth'].url_for_oauth_code(:permissions => ["publish_stream"])
end
get '/callbackfb' do
session['access_token'] = session['oauth'].get_access_token(params[:code])
registerUserFB() #Just register the user function
redirect '/accounts'
end
#Twitter
#By defualt logs in with /auth/twitter
get '/auth/twitter/callback' do
erb "<h1>#{params[:provider]}</h1><pre>#{JSON.pretty_generate(request.env['omniauth.auth'])}</pre>"
p auth['credentials']['token']
end
get '/auth/failure' do
erb "<h1>Authentication Failed:</h1><h3>message:<h3> <pre>#{params}</pre>"
end
Thanks guys in advance.

I used another gem for logging with twitter called twitter_oauth yo can find here
For use with sinatra is quite simple:
#Sinatra stuff
require 'twitter_oauth'
#more sinatra stuff
$CONSUMER_KEY = '32423...'
$CONSUMER_SECRET = '...adads...'
$CALLBACK_URL = 'http://....'
tw_client = TwitterOAuth::Client.new(
:consumer_key => $CONSUMER_KEY,
:consumer_secret => $CONSUMER_SECRET
)
$request_token = tw_client.request_token(:oauth_callback => $CALLBACK_URL)
#sinatra routes
get '/logintw' do
redirect $request_token.authorize_url
end
get '/callbacktw' do
#access_token = $request_token.get_access_token :oauth_verifier => params[:oauth_verifier]
p #access_token.params[:oauth_token]
p #access_token.params[:oauth_token_secret]
p #access_token.params[:screen_name]
p #access_token.params[:user_id]
redirect '/accounts'
end
#more sinatra routes
Is not the best solution but is one and for me works!
Thanks anyway.

Related

Customize Instagram widget on a Dashing.io dashboard

I have set up a dashboard using dashing with a number of (mostly) existing widgets. That worked so far - see production dashboard here (work in progress).
Now I would like to have an Instagram widget that displays the n lastest images taken by username.
I have found a widget that will display images by long and lat and also was able to get my tokens configured, so I can talk to the Instagram API.
Here's the code of my current widget originally from #mjamieson's gist on github.
require 'instagram'
require 'rest-client'
require 'json'
# Instagram Client ID from http://instagram.com/developer
Instagram.configure do |config|
config.client_id = ENV['INSTAGRAM_CLIENT_ID']
config.client_secret = ENV['INSTAGRAM_CLIENT_SECRET']
end
# Latitude, Longitude for location
instadash_location_lat = '45.429522'
instadash_location_long = '-75.689613'
SCHEDULER.every '10m', :first_in => 0 do |job|
photos = Instagram.media_search(instadash_location_lat,instadash_location_long)
if photos
photos.map do |photo|
{ photo: "#{photo.images.low_resolution.url}" }
end
end
send_event('instadash', photos: photos)
end
I got this to work, but would like to modify the given API call to only display images taken by me / a user of my choice. Unfortunately I don't understand ruby or json enough to figure out what the Instagram API documentation wants me to do.
I found the following url
https://api.instagram.com/v1/users/{user-id}/media/recent/?access_token={acces-token}
and tried it (with my credentials filled in). It returned json data correctly including my images (among other data).
How can I modify the given code to display images by username instead of location?
Any help is greatly appreciated.
You'll need an access_token to get content from some user. Take a look at sample application on gem page.
It seems you need something like this:
# here we take access token from session, assuming you already got it
# sometime before and stored it there for future use
client = Instagram.client(:access_token => session[:access_token])
photos = client.user_recent_media
And this example how to get this access_token using OAuth2 browser authorization and sinatra app:
require "sinatra"
require "instagram"
enable :sessions
CALLBACK_URL = "http://localhost:4567/oauth/callback"
Instagram.configure do |config|
config.client_id = "YOUR_CLIENT_ID"
config.client_secret = "YOUR_CLIENT_SECRET"
# For secured endpoints only
#config.client_ips = '<Comma separated list of IPs>'
end
get "/" do
'Connect with Instagram'
end
get "/oauth/connect" do
redirect Instagram.authorize_url(:redirect_uri => CALLBACK_URL)
end
get "/oauth/callback" do
response = Instagram.get_access_token(params[:code], :redirect_uri => CALLBACK_URL)
session[:access_token] = response.access_token
redirect "/nav"
end
Solution
require 'sinatra'
require 'instagram'
# Instagram Client ID from http://instagram.com/developer
Instagram.configure do |config|
config.client_id = ENV['INSTAGRAM_CLIENT_ID']
config.client_secret = ENV['INSTAGRAM_CLIENT_SECRET']
config.access_token = ENV['INSTAGRAM_ACCESS_TOKEN']
end
user_id = ENV['INSTAGRAM_USER_ID']
SCHEDULER.every '2m', :first_in => 0 do |job|
photos = Instagram.user_recent_media("#{user_id}")
if photos
photos.map! do |photo|
{ photo: "#{photo.images.low_resolution.url}" }
end
end
send_event('instadash', photos: photos)
end
Explaination
1.) In addition to the client_id and client_secret I had defined before, I just needed to add my access_token to the Instagram.configure section.
2.) The SCHEDULER was correctly working, but needed to call Instagram.user_recent_media("#{user_id}") instead of Instagram.media_search(instadash_location_lat,instadash_location_long)
3.) To do that I had to set a second missing variable for user_id
Now the call gets recent media filtered by user ID and outputs it into the dashing widget.
Thanks for the participation and hints! That pointed me into the right direction of the documentation and helped me to figure it out myself.

how RestClient gem work in ruby

I'm using Rest-client gem in ruby.My code is as follows..,
require 'rest_client'
puts RestClient.get 'http://localhost:3000/articles'
puts RestClient.put 'http://localhost:3000/', {:params => {:Bat => 'ball'}}
RestClient.post 'http://localhost:3000/articles', {:params => {:Name => 'list1', 'Content' => 'Article1'}}
I refer the URL which runs in rails application, the user can can create, delete, edit,list the articles using the above url.For put,delete,post,get methods it produces the html code of the URL in my prompt.But it cannnot able to insert the post/delete an item from the list via ruby code.
It is possible in RestClient?
I think the problem here is that you need to be authenticated. You can do that with RestClient but you will need to chain your calls. See the rest_client Readme how to do that.

[Twitter4R]Twitter::ForbiddenError

I'm new to Twitter4R and Ruby on Rails. I'm using Ruby 1.9.2, Rails 3.1 and Twitter4R v0.7.0.
I'm trying to get my friends list from Twitter.
twitter = Twitter::Client.new(oauth_access: { key: token, secret: token_secret})
#these lines works fine.
twitter.status(:post, "POST TEST!!!")
twitter.friend(:add, "xxxx_jp")
#this line will cause ForbiddenError
friends = twitter.my(:friends)
I've checked the following site for information.
http://twitter4r.rubyforge.org/rdoc/Twitter/Client.html
Update
I now added config/initializers/twitter4r.rb:
require 'twitter'
Twitter::Client.configure do |config|
config.oauth_consumer_token = consumer_key
config.oauth_consumer_secret = consumer_secret
end
When debugging, I see the consumer_key and consumer_secret in Twitter::Consumer on debug window. But methods that require authentication like my(:friends) do not work.
How do I avoid the ForbiddenError?
That looks like the authentication in Twitter::Client.new didn't actually work. Here's a presentation on OAuth by Twitter4R's creator Susan Potter:
http://www.slideshare.net/mbbx6spp/twitter4r-oauth

Ruby rest_client and windows LIVE connect OAUTH Wrap

Hi all I am trying to get my rails app to talk to Windows LIVE (through OAuth Wrap) so I can retrieve a list of contacts. I am using the rest_client gem to do this. Here is the action code for it:
def hotmail
app_id = 'some_id'
app_sec = 'some_secret'
app_callback = 'http://my.callback.com/same/as/getting/verification_code'
app_var = params[:wrap_verification_code]
encoded = "wrap_client_id=#{app_id}&wrap_client_secret=#{app_sec}&wrap_verification_code=#{app_var}&wrap_callback=#{app_callback}".encode!('UTF-8')
begin
r = RestClient.post("https://consent.live.com/AccessToken.aspx", encoded.bytes.to_a, {:content_type => 'application/x-www-form-urlencoded', :content_length => encoded.bytesize})
rescue => e
puts e.message
end
render :text => 'hello'
end
I base this on a c# example http://msdn.microsoft.com/en-us/library/ff750952.aspx (note: http://www.goatly.net/2010/12/23/401-unauthorized-when-acquiring-an-access-token-windows-live-sdk.aspx shows the correct payload)
However I keep getting 401 Unauthorized, so I am thinking is the way I am using rest_client incorrectly? During a form post is there somthing else I need to do?
ANy hints will be really helpful :) thanks in advance.
Found the problem. The C# code says it post the byte array but thats not true just post the encoded st direct is enough.

How can I persistently overwrite an attribute initialized by Rack::Builder?

I am trying to use OmniAuth to handle the OAuth flow for a small-ish Sinatra app. I can get 37signals Oauth to work perfectly, however I'm trying to create a strategy for Freshbooks Oauth as well.
Unfortunately Freshbooks require OAuth requests to go to a user specific subdomain. I'm acquiring the subdomain as an input and I then need to persistently use the customer specific site URL for all requests.
Here's what I've tried up to now. The problem is that the new site value doesn't persist past the first request.
There's to to be a simple way to achieve this but I'm stumped.
#Here's the setup -
def initialize(app, consumer_key, consumer_secret, subdomain='api')
super(app, :freshbooks, consumer_key, consumer_secret,
:site => "https://"+subdomain+".freshbooks.com",
:signature_method => 'PLAINTEXT',
:request_token_path => "/oauth/oauth_request.php",
:access_token_path => "/oauth/oauth_access.php",
:authorize_path => "/oauth/oauth_authorize.php"
)
end
def request_phase
#Here's the overwrite -
consumer.options[:site] = "https://"+request.env["rack.request.form_hash"]["subdomain"]+".freshbooks.com"
request_token = consumer.get_request_token(:oauth_callback => callback_url)
(session[:oauth]||={})[name.to_sym] = {:callback_confirmed => request_token.callback_confirmed?,
:request_token => request_token.token,
:request_secret => request_token.secret}
r = Rack::Response.new
r.redirect request_token.authorize_url
r.finish
end
Ok, here's a summary of what I did for anyone who comes across this via Google.
I didn't solve the problem in the way I asked it, instead I pushed the subdomain into the session and then I overwrite it whenever the site value needs to be used.
Here's the code:
#Monkeypatching to inject user subdomain
def request_phase
#Subdomain is expected to be submitted as <input name="subdomain">
session[:subdomain] = request.env["rack.request.form_hash"]["subdomain"]
consumer.options[:site] = "https://"+session[:subdomain]+".freshbooks.com"
super
end
#Monkeypatching to inject subdomain again
def callback_phase
consumer.options[:site] = "https://"+session[:subdomain]+".freshbooks.com"
super
end
Note that you still have to set something as the site when it's initialised, otherwise you will get errors due to OAuth not using SSL to make the requests.
If you want to see the actual code I'm using it's at: https://github.com/joeharris76/omniauth I'll push the fork up to the main project once I've battle tested this solution a bit more.

Resources