I wrote code to display tweets from a public account on Twitter:
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(
"screen_name" => "CVecchioFX",
"count" => 10,
)
address = URI("#{baseurl}#{path}?#{query}")
request = Net::HTTP::Get.new address.request_uri
# Print data about a list of Tweets
def print_timeline(tweets)
# ADD CODE TO ITERATE THROUGH EACH TWEET AND PRINT ITS TEXT
tweets.each do |tweet|
puts "#{tweet["user"]["name"]} , #{tweet["text"]} , #{tweet["created_at"]} , # {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
if response.code == '200' then
tweets = JSON.parse(response.body)
print_timeline(tweets)
end
nil
The date is coming out as "Tue Jun 11 15:35:31 +0000 2013". What do I do to parse through the date and change it to a format such as "06.11.2013"?
Use Ruby's standard library Date:
require 'date'
d = DateTime.parse('Tue Jun 11 15:35:31 +0000 2013')
puts d.strftime('%m.%d.%y')
In your code, just update print_timeline method:
def print_timeline(tweets)
tweets.each do |tweet|
d = DateTime.new(tweet['created_at'])
puts "#{tweet['user']['name']} , #{tweet['text']} , #{d.strftime('%m.%d.%y')} , #{tweet['id']}"
end
end
Related
I would like to limit searching images using
"filter query parameters ( https://msdn.microsoft.com/en-us/library/dn760791.aspx )". But I always get photos whose size is around 250 - 300 pixel( both of width and height), although I want them, which is bigger than 500 x 500 pixel.
I know there is already similar question(Bing Image Search API filter by image size), but I couldn't solve the problem.
I'm using Ruby and the code is following.
What is the problem?
require "open-uri"
require "FileUtils"
require 'net/http'
require 'json'
#dirName = "/Users/hoge/img"
FileUtils.mkdir_p(#dirName) unless FileTest.exist?(#dirName)
def save_image(url, num)
filePath = "#{#dirName}/christ#{num.to_s}.jpg"
open(filePath, 'wb') do |output|
open(url) do |data|
output.write(data.read)
end
end
end
search_word = 'christ painting'
count = 5
size = 'Large'
uri = URI('https://api.cognitive.microsoft.com/bing/v5.0/images/search')
uri.query = URI.encode_www_form({
'q' => search_word,
'count' => count,
'size' => size
})
request = Net::HTTP::Post.new(uri.request_uri)
request['Content-Type'] = 'multipart/form-data'
request['Ocp-Apim-Subscription-Key'] = 'mykey' # Fix Me
request.body = "{body}"
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
http.request(request)
end
count.times do |i|
begin
image_url = JSON.parse(response.body)["value"][i]["thumbnailUrl"]
save_image(image_url, i)
rescue => e
puts "image#{i} is error!"
puts e
end
end
I am using net/http to send a bunch of request to some internal IP addresses.
Here's a snippet of the code:
File.open("internalcorpIPs", "r") do |f|
f.each_line do |line|
puts line
res = Net::HTTP.get_response(URI.parse(line))
getCode = res.code
end
end
I'm strictly just making a request to http://IP and https://IP but it seems like this method only works if every single IP/line address is live. How do I skip IP addresses with no webserver (or 80/443 ports)?
Is it possible to make it read the line, and move on to the next if no response code was returned?
Thanks!
You could simply wrap your request in begin/rescue block like this:
File.open("internalcorpIPs", "r") do |f|
f.each_line do |line|
puts line
begin
# strip and encode uri from the file
uri = URI.parse(URI.encode(line.strip))
res = Net::HTTP.get_response(uri)
getCode = res.code
rescue Timeout::Error => e
puts e
false
end
end
end
But you will wait for 60 seconds at least before going in timeout, so I suggest to decrease the timeout. Furthermore, you could introduce an additional guard clause to check if the uri contains the scheme http:// or https://, otherwise raise an exception (or something else).
require 'net/http'
File.open("internalcorpIPs", "r") do |f|
f.each do |line|
puts line
begin
# strip and encode uri from the file
uri = URI.parse(URI.encode(line.strip))
# if uri misses the schema (http:// or https://) -> raise error
raise URI::Error, "uri #{uri} miss the scheme" unless uri.scheme
http = Net::HTTP.new(uri.host, uri.port)
http.open_timeout = 2 # seconds
http.read_timeout = 2 # seconds
http.start do |conn|
response = conn.request_get(path = '/')
puts response.code
end
rescue Timeout::Error, URI::Error, SocketError => e
puts e
false
end
end
end
Additional notes:
Open Timeout
Number of seconds to wait for the connection to open. Any number may be used, including Floats for fractional seconds. If the HTTP object cannot open a connection in this many seconds, it raises a Net::OpenTimeout exception. The default value is 60 seconds.
Read Timeout
Number of seconds to wait for one block to be read (via one read(2) call). Any number may be used, including Floats for fractional seconds. If the HTTP object cannot read data in this many seconds, it raises a Net::ReadTimeout exception. The default value is 60 seconds.
URI Scheme
Difference between generic uri (URI::Generic) and http uri (URI::HTTP).
uri = URI.parse('1.1.1.1')
=> #<URI::Generic 1.1.1.1>
uri.scheme
=> nil
uri.host
=> nil
uri.port
=> nil
uri.path
=> "1.1.1.1"
uri = URI.parse('http://1.1.1.1')
=> #<URI::HTTP http://1.1.1.1>
uri.scheme
=> "http"
uri.host
=> "1.1.1.1"
uri.port
=> 80
uri.path
=> ""
references:
Net::HTTP Api
URI Module
hope it helps!
UPDATE
URI.parse accepts a string as argument and automatically set the port if not specified:
❯ irb
2.2.0 :001 > require 'net/http'
=> true
2.2.0 :002 > uri = URI.parse('http://1.1.1.1')
=> #<URI::HTTP http://1.1.1.1>
2.2.0 :003 > uri.host
=> "1.1.1.1"
2.2.0 :004 > uri.port
=> 80
2.2.0 :005 > uri2 = URI.parse('http://mydomain')
=> #<URI::HTTP http://mydomain>
2.2.0 :006 > uri2.host
=> "mydomain"
2.2.0 :007 > uri2.port
=> 80
2.2.0 :008 > uri3 = URI.parse('https://mydomain')
=> #<URI::HTTPS https://mydomain>
2.2.0 :009 > uri3.host
=> "mydomain"
2.2.0 :010 > uri3.port
=> 443
I am trying to pull campaign stats from Clickbank API in ruby. When I run the sample code Clickbank provided. I get the following error:
uninitialized constant Net::HTTPS (NameError). What am I missing?
Example Code.
require 'net/http'
require 'net/https'
http = Net::HTTPS.new('api.clickbank.com')
http.use_ssl = false
path = '/rest/1.3/orders/list'
headers = {
'Authorization' => '<< DEVKEY >>:<< APIKEY>>',
'Accept' => 'application/json'
}
resp, data = http.get(path, nil, headers)
puts 'Code = ' + resp.code
puts 'Message = ' + resp.message
resp.each {|key, val| puts key + ' = ' + val}
puts data
Yes I put my dev and api key into
In Ruby 2.4.1 enable ssl as a parameter of Net::HTTP.start
Net::HTTP.start(uri.host, uri.port, use_ssl: true)
https://ruby-doc.org/stdlib-2.4.1/libdoc/net/http/rdoc/Net/HTTP.html#class-Net::HTTP-label-HTTPS
Use Net:HTTP and enable SSL instead of using Net::HTTPS and disabling SSL.
Example:
http = Net::HTTP.new('api.clickbank.com')
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
You actually don't want to disable ssl as that API requires it. I was able to get it working like so based on the documentation for http found here: http://ruby-doc.org/stdlib-2.1.1/libdoc/net/http/rdoc/Net/HTTP.html
require 'net/http'
uri = URI('https://api.clickbank.com/rest/1.3/orders/list')
req = Net::HTTP::Get.new(uri)
# set headers on the request
req['Authorization'] = '<< DEVKEY >>:<< APIKEY>>'
req['Accept'] = 'application/json'
# perform the request
resp, data = Net::HTTP.start(uri.hostname, uri.port) {|http|
http.request(req)
}
puts 'Code = ' + resp.code
puts 'Message = ' + resp.message
resp.each {|key, val| puts key + ' = ' + val}
puts data
I am trying to use SAS authenticaion in a ruby script and i keep getting 401 (Access denied) response from the event hub, it seems I am generating the SAS token incorrectly.
Below is the code I have used, it is based on https://azure.microsoft.com/en-us/documentation/articles/service-bus-sas-overview/ Javascript example that i have rewritten as ruby (please note it might be not idiomatic)
require "optparse"
require "CGI"
require 'openssl'
require "base64"
require "Faraday"
require 'Digest'
def generateToken(url,keyname,keyvalue)
encoded = CGI::escape(url)
ttl = (Time.now + 60*5).to_i
signature = "#{encoded}\n#{ttl}".encode('utf-8')
# puts signature
key = Base64.strict_decode64(keyvalue)
dig = OpenSSL::HMAC.digest('sha256', key, signature)
# dig = Digest::HMAC.digest(signature, key, Digest::SHA256)
hash = CGI.escape(Base64.strict_encode64(dig))
# puts hash
return "SharedAccessSignature sig=#{hash}&se=#{ttl}&skn=#{keyname}&sr=#{encoded}"
end
def build_connection(url,token)
conn = Faraday.new(:url => url) do |faraday|
faraday.request :url_encoded # form-encode POST params
faraday.response :logger # log requests to STDOUT
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
end
conn.headers['Content-Type'] = 'application/json'
conn.headers['Authorization'] = token
return conn
end
if __FILE__ == $0
ARGV << '-h' if ARGV.empty?
options = {}
OptionParser.new do |opts|
opts.banner = "Usage: generateSasToken.rb [options]"
opts.on('-u URL', '--url URL', 'url for access') { |v| options[:url] = v }
opts.on('--keyname NAME','set key name') { |v| options[:keyname] = v }
opts.on('--key KEY','set key value') { |v| options[:keyvalue] = v }
opts.on_tail("-h", "--help", "Show this message") do
puts opts
exit
end
end.parse!
token = generateToken(options[:url],options[:keyname],options[:keyvalue])
puts token
conn = build_connection(options[:url],token)
puts conn.headers
response = conn.post do |req|
req.body = '{"temprature":50}'
req.headers['content-length'] = req.body.length.to_s
end
puts response
end
any help in understanding why the token is incorrect would be great
After comparing my code against the python sdk this is the correct way to generate the token:
require "optparse"
require "CGI"
require 'openssl'
require "base64"
require "Faraday"
require 'Digest'
def generateToken(url,keyname,keyvalue)
encoded = CGI::escape(url)
ttl = (Time.now + 60*5).to_i
signature = "#{encoded}\n#{ttl}"
# puts signature
key = keyvalue
#dig = OpenSSL::HMAC.digest('sha256', key, signature)
dig = Digest::HMAC.digest(signature, key, Digest::SHA256)
hash = CGI.escape(Base64.strict_encode64(dig))
# puts hash
return "SharedAccessSignature sig=#{hash}&se=#{ttl}&skn=#{keyname}&sr=#{encoded}"
end
def build_connection(url,token)
conn = Faraday.new(:url => url) do |faraday|
faraday.request :url_encoded # form-encode POST params
faraday.response :logger # log requests to STDOUT
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
end
conn.headers['Content-Type'] = 'application/json'
conn.headers['Authorization'] = token
return conn
end
if __FILE__ == $0
ARGV << '-h' if ARGV.empty?
options = {}
OptionParser.new do |opts|
opts.banner = "Usage: generateSasToken.rb [options]"
opts.on('-u URL', '--url URL', 'url for access') { |v| options[:url] = v }
opts.on('--keyname NAME','set key name') { |v| options[:keyname] = v }
opts.on('--key KEY','set key value') { |v| options[:keyvalue] = v }
opts.on_tail("-h", "--help", "Show this message") do
puts opts
exit
end
end.parse!
token = generateToken(options[:url],options[:keyname],options[:keyvalue])
conn = build_connection(options[:url],token)
puts conn.headers
response = conn.post do |req|
req.body = '{"temprature":50}'
req.headers['content-length'] = req.body.length.to_s
end
puts response
end
this was much simpler than expected no need to encode to utf8 or to decode the key.
For example, to get response 200 OK from "example.com", necessary:
require 'net/http'
uri = URI('http://example.com/index.html')
res = Net::HTTP.get_response(uri)
puts res.code # => '200'
puts res.message # => 'OK'
How to make similar for pop.gmail.com?
Try this:
require "net/pop"
Net::POP3.enable_ssl(OpenSSL::SSL::VERIFY_NONE)
conn = Net::POP3.new("pop.gmail.com", 995)
conn.start(user_name, password)
conn.started?