Twitter ruby gem .search request multiple responses - ruby

In the following code I specify that I want to make 1 request to the twitter api, but when I puts the output to terminal I continue to receive many responses until I kill the program. How can I limit it to only the specified amount of requests? I am new to ruby so I may be missing something obviously here.
Docs to the twitter gem api
require 'twitter'
...
client = Twitter::REST::Client.new do |config|
config.consumer_key = credentials[:consumer_key]
config.consumer_secret = credentials[:consumer_secret]
config.access_token = credentials[:access_token]
config.access_token_secret = credentials[:access_token_secret]
end
search_results = client.search "China", {:count => 1, :lang => 'en', :result_type => 'recent'}
search_results.each do |value|
puts value.user.screen_name
end

As docs state,
:count (Integer) — The number of tweets to return per page, up to a
maximum of 100.
So, that is kinda reverse for what you're trying to achieve: the more count is, the less http requests you gonna make (as each of them would contain more tweets). Note that you can not set count to an amount more than 100, so the only way to restrict amount of requests in case there is a huge amount of tweets would be
search_results.take(requests_amount)
# => made requests_amount requests, returns requests_amount pages
# each of page should contain up to count tweets, with max of 100

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.

Why am I hitting the Twitter API rate limit?

I'm working with the Twitter API using the code below and I'm hitting the API rate limit inside the loop.
My question is: how am I hitting the rate limit? I believe that I'm only making one API call when I'm assigning myFollowers and in the loop I'm just looking through the location value of each object in myFollwers which should just be server side processing.
require 'twitter'
client = Twitter::REST::Client.new do |config|
config.consumer_key = "xx"
config.consumer_secret = "xx"
config.access_token = "xx"
config.access_token_secret = "xx"
end
myFollowers = client.followers("mytwittername")
myFollowers.each do |follower|
if follower.location.include? 'New'
print Name: follower.name
puts Location: follower.location
end
end
I believe that by default, client.followers is not going load up the entire user entity for each follower, so when you iterate over the followers you are generating a new request and thus quickly hitting the rate limit.
Try setting :include_user_entities on the client.followers call to true and see what happens. See link to code/documentation below.
http://www.rubydoc.info/gems/twitter/Twitter/REST/FriendsAndFollowers#followers-instance_method
If that doesn't work, stop your script after your client.followers call and let us know what the myFollowers collection looks like.

Ruby gmail gem and storing credentials

I'm writing a very small program that I'd like to run on my RPI in a cron job. Every hour I want to check the status of a webpage. If the status meets a certain criteria I want it to email me.
In the past I have successfully used the gmail gem however I have always had to provide my credentials. I am nervous about storing my gmail credentials on file. Does anyone know how to accomplish this task more securely?
The end goal is I want an email in my inbox that tells me that a gate status has changed on the website I'm monitoring.
Here is what I have so far
#!/usr/bin/ruby
require 'open-uri'
require 'nokogiri'
def check_gates
doc = Nokogiri::HTML(open('http://www.summitatsnoqualmie.com/Mountains/Grooming-Report'))
gates = {}
table_rows = doc.xpath('//tr')
sections = []
sections.push({:gate => "Elevator", :data => table_rows.select { |tr| tr.inspect.include? "Lower Traverse" }.first})
sections.push({:gate => "Nash", :data => table_rows.select { |tr| tr.inspect.include? "Upper Traverse" }.first})
sections.each do |section|
status_text = section[:data].element_children.select { |child| child.inspect.include? "grooming_open_status" }.first.inspect
match = status_text.match(/background-position:\ (\d+)px\ (.\d)+px/)
gate_down = false
unless match.nil?
gate_down = match[1].to_i == 0 and match[2].to_i == 0
end
gates[section[:gate]] = gate_down ? "CLOSED" : "OPEN"
end
gates
end
Generate an application-specific password for your Google account, and store that password on the server.

How Do I search Twitter for a word with Ruby?

I have written code in Ruby that will display the timeline for a specific user. I would like to write code to be able to just search twitter to just find every user that has mentioned a word. My code is currently:
require 'rubygems'
require 'oauth'
require 'json'
# Now you will fetch /1.1/statuses/user_timeline.json,
# returns a list of public Tweets from the specified
# account.
baseurl = "https://api.twitter.com"
path = "/1.1/statuses/user_timeline.json"
query = URI.encode_www_form(
"q" => "Obama"
)
address = URI("#{baseurl}#{path}?#{query}")
request = Net::HTTP::Get.new address.request_uri
# Print data about a list of Tweets
def print_timeline(tweets)
tweets.each do |tweet|
require 'date'
d = DateTime.parse(tweet['created_at'])
puts " #{tweet['text'].delete ","} , #{d.strftime('%d.%m.%y')} , #{tweet['user']['name']}, #{tweet['id']}"
end
end
# Set up HTTP.
http = Net::HTTP.new address.host, address.port
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
# If you entered your credentials in the first
# exercise, no need to enter them again here. The
# ||= operator will only assign these values if
# they are not already set.
consumer_key = OAuth::Consumer.new(
"")
access_token = OAuth::Token.new(
"")
# Issue the request.
request.oauth! http, consumer_key, access_token
http.start
response = http.request request
# Parse and print the Tweet if the response code was 200
tweets = nil
puts "Text,Date,Name,id"
if response.code == '200' then
tweets = JSON.parse(response.body)
print_timeline(tweets)
end
nil
How would I possibly change this code to search all of twitter for a specific word?
The easiest approach would be to use 'Twitter' gem. Refer to this Link for more information and the result type of the search results. Once you have all the correct authorization attribute in place (oAuth-Token,oAuth-secret, etc) you should be able to search as
Twitter.search('Obama')
or
Twitter.search('Obama', options = {})
Let us know, if that worked for you or not.
p.s. - Please mark the post as answered if it helped you. Else put a comment back with what is missing.
The Twitter API suggests the URI your should be using for global search is https://api.twitter.com/1.1/search/tweets.json and this means:
Your base_url component would be https://api.twitter.com
Your path component would be /1.1/search/tweets.json
Your query component would be the text you are searching for.
The query part takes a lot of values depending upon the API spec. Refer to the specification and you can change it as per your requirement.
Tip: Try to use irb (I'd recommend pry) REPL which makes it a lot easier to explore APIs. Also, checkout the Faraday gem which can be easier to use than the default HTTP library in Ruby IMO.

How to specify the total number of image results for .media_search method from Instagram-ruby gem

I want to return 18 photos from the .media_search method provided by the Instagram-ruby gem. The source codes says to pass in an options hash with key :count => some_integer
The problem is that the gem returns what appears to be a random response number when I do add the options hash. Sometimes it will return 8 other times 4 etc.
What am I missing???
Thanks.
Here's my sample file I am working with
require 'instagram'
require 'faraday'
Instagram.configure do |config|
config.client_id = "CLIENT_ID"
config.client_secret = "CLIENT_SECRET"
end
result = Instagram.media_search("40.7143528", "-74.00597309999999", {:count => 18})
Although the media_search method within the instagram-ruby-gem does accept an options hash, the count parameter is not an allowed parameter for this particular endpoint as can be seen within Instagram's API documentation here

Resources