tweetlr 0.1.20 → 0.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -1,9 +1,10 @@
1
1
  *.swp
2
+ log/
2
3
  *.log
3
4
  pkg
4
5
  *.pid
5
6
  *.output
6
- .rvmrc
7
+ .ruby-version
7
8
  Gemfile.lock
8
9
  tweetlr.tid
9
10
  tweetlr.yml.dev
data/.travis.yml CHANGED
@@ -5,6 +5,7 @@ bundler_args: --binstubs
5
5
  rvm:
6
6
  - 1.9.2
7
7
  - 1.9.3
8
+ - 2.0.0
8
9
  #- 1.8.7 # (current default)
9
10
 
10
11
  # Define how to run your tests (defaults to `bundle exec rake` or `rake` depending on whether you have a `Gemfile`)
data/Gemfile CHANGED
@@ -1,2 +1,2 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
  gemspec
data/README.md CHANGED
@@ -10,17 +10,16 @@ There is a new [tweetlr "as-a-service"](http://tweetlr.5v3n.com) where you can e
10
10
 
11
11
  tweetlr supports
12
12
 
13
- - eyeem.com
13
+ - instagram
14
14
  - twitter
15
15
  - photobucket
16
16
  - twimg
17
17
  - foursquare
18
18
  - path.com
19
- - picplz
20
19
  - twitpic
21
20
  - yfrog
22
21
  - imgly
23
- - instagram
22
+ - eyeem.com
24
23
  - t.co shortened links to pictures
25
24
  - every photo service accessible via embed.ly (see [photo providers](http://embed.ly/providers))
26
25
 
data/lib/tweetlr/core.rb CHANGED
@@ -15,24 +15,8 @@ class Tweetlr::Core
15
15
  end
16
16
 
17
17
  def initialize(args)
18
- log = Logger.new(STDOUT)
19
- if (Logger::DEBUG..Logger::UNKNOWN).to_a.index(args[:loglevel])
20
- log.level = args[:loglevel]
21
- else
22
- log.level = Logger::INFO
23
- end
24
- log.debug "log level set to #{log.level}"
25
- Tweetlr::LogAware.log=log
26
-
27
- @email = args[:tumblr_email]
28
- @password = args[:tumblr_password]
29
- @cookie = args[:cookie]
30
- @api_endpoint_twitter = args[:api_endpoint_twitter] || Tweetlr::API_ENDPOINT_TWITTER
31
- @api_endpoint_tumblr = args[:api_endpoint_tumblr] || Tweetlr::API_ENDPOINT_TUMBLR
32
- @whitelist = args[:whitelist]
33
- @shouts = args[:shouts]
34
- @update_period = args[:update_period] || Tweetlr::UPDATE_PERIOD
35
- @whitelist.each {|entry| entry.downcase!} if @whitelist
18
+ initialize_logging(args[:loglevel])
19
+ initialize_attributes(args)
36
20
  log.info "Tweetlr #{Tweetlr::VERSION} initialized. Ready to roll."
37
21
  end
38
22
 
@@ -55,26 +39,51 @@ class Tweetlr::Core
55
39
  return config
56
40
  end
57
41
  private
42
+ def initialize_attributes(args)
43
+ @email = args[:tumblr_email]
44
+ @password = args[:tumblr_password]
45
+ @cookie = args[:cookie]
46
+ @api_endpoint_twitter = args[:api_endpoint_twitter] || Tweetlr::API_ENDPOINT_TWITTER
47
+ @api_endpoint_tumblr = args[:api_endpoint_tumblr] || Tweetlr::API_ENDPOINT_TUMBLR
48
+ @whitelist = args[:whitelist]
49
+ @shouts = args[:shouts]
50
+ @update_period = args[:update_period] || Tweetlr::UPDATE_PERIOD
51
+ @whitelist.each {|entry| entry.downcase!} if @whitelist
52
+ end
53
+ def initialize_logging(loglevel)
54
+ log = Logger.new(STDOUT)
55
+ if (Logger::DEBUG..Logger::UNKNOWN).to_a.index(loglevel)
56
+ log.level = loglevel
57
+ else
58
+ log.level = Logger::INFO
59
+ end
60
+ log.debug "log level set to #{log.level}"
61
+ Tweetlr::LogAware.log=log
62
+ end
58
63
  def self.process_response(response, config, tumblr_config)
59
64
  tweets = response['results']
60
- if tweets
61
- tweets.each do |tweet|
62
- tumblr_post = Tweetlr::Combinators::TwitterTumblr::generate_photo_post_from_tweet(tweet, {:whitelist => config[:whitelist], :embedly_key => config[:embedly_key], :group => config[:group]})
63
- if tumblr_post.nil? || tumblr_post[:source].nil?
64
- log.warn "could not get image source: tweet: #{tweet} --- tumblr post: #{tumblr_post.inspect}"
65
- else
66
- log.debug "tumblr post: #{tumblr_post}"
67
- res = Tweetlr::Processors::Tumblr.post tumblr_post.merge(tumblr_config)
68
- log.debug "tumblr response: #{res}"
69
- if res && res.code == "201"
70
- log.info "tumblr post created (tumblr response: #{res.header} #{res.body}"
71
- elsif res
72
- log.warn "tumblr response: #{res.header} #{res.body}"
73
- else
74
- log.warn "there was no tumblr post response - most probably due to a missing oauth authorization"
75
- end
76
- end
65
+ process_and_post tweets, config, tumblr_config if tweets
66
+ end
67
+ def self.process_and_post(tweets, config, tumblr_config)
68
+ tweets.each do |tweet|
69
+ tumblr_post = Tweetlr::Combinators::TwitterTumblr::generate_photo_post_from_tweet(tweet, {:whitelist => config[:whitelist], :embedly_key => config[:embedly_key], :group => config[:group]})
70
+ if tumblr_post.nil? || tumblr_post[:source].nil?
71
+ log.warn "could not get image source: tweet: #{tweet} --- tumblr post: #{tumblr_post.inspect}"
72
+ else
73
+ post_to_tumblr
77
74
  end
75
+ end
76
+ end
77
+ def self.post_to_tumblr(tumblr_post, tumblr_config)
78
+ log.debug "tumblr post: #{tumblr_post}"
79
+ res = Tweetlr::Processors::Tumblr.post tumblr_post.merge(tumblr_config)
80
+ log.debug "tumblr response: #{res}"
81
+ if res && res.code == "201"
82
+ log.info "tumblr post created (tumblr response: #{res.header} #{res.body}"
83
+ elsif res
84
+ log.warn "tumblr response: #{res.header} #{res.body}"
85
+ else
86
+ log.warn "there was no tumblr post response - most probably due to a missing oauth authorization"
78
87
  end
79
88
  end
80
89
  def self.prepare_twitter_config(config)
@@ -22,15 +22,13 @@ module Tweetlr::Processors
22
22
  if link && !(photo? link)
23
23
  url = image_url_eyeem link if link.index 'eyeem.com'
24
24
  url = image_url_instagram link if (link.index('instagr.am') || link.index('instagram.com'))
25
- url = image_url_picplz link if link.index 'picplz'
26
25
  url = image_url_twitpic link if link.index 'twitpic'
27
26
  url = image_url_yfrog link if link.index 'yfrog'
28
- url = image_url_imgly link if link.index 'img.ly'
27
+ url = image_url_imgly link, embedly_key if link.index 'img.ly'
29
28
  url = image_url_tco link, embedly_key if link.index 't.co'
30
29
  url = image_url_twimg link if link.index 'twitter.com'
31
- url = image_url_lockerz link if link.index 'lockerz.com'
32
30
  url = image_url_path link if link.index 'path.com'
33
- url = image_url_foursqaure link if link.index '4sq.com'
31
+ url = image_url_foursqaure link if (link.index('4sq.com') || link.index('foursquare.com'))
34
32
  url = image_url_embedly link, embedly_key if url.nil? #just try embed.ly for anything else. could do all image url processing w/ embedly, but there's probably some kind of rate limit invovled.
35
33
  elsif photo? link
36
34
  url = link
@@ -42,7 +40,7 @@ module Tweetlr::Processors
42
40
  link =~ PIC_REGEXP
43
41
  end
44
42
  def self.image_url_twimg(link_url)
45
- retrieve_image_url_by_css link_url, '.twimg img'
43
+ retrieve_image_url_by_css link_url, '.media img'
46
44
  end
47
45
  #extract the image of an eyeem.com pic
48
46
  def self.image_url_eyeem(link_url)
@@ -50,7 +48,9 @@ module Tweetlr::Processors
50
48
  end
51
49
  #extract the image of a foursquare.com pic
52
50
  def self.image_url_foursqaure(link_url)
53
- retrieve_image_url_by_css link_url, '.commentPhoto img'
51
+ link_url = follow_redirect(link_url)
52
+ image_url = retrieve_image_url_by_css link_url, 'meta[property="og:image"]', 'content'
53
+ image_url
54
54
  end
55
55
  #extract the image of a path.com pic
56
56
  def self.image_url_path(link_url)
@@ -59,18 +59,14 @@ module Tweetlr::Processors
59
59
 
60
60
  #find the image's url via embed.ly
61
61
  def self.image_url_embedly(link_url, key)
62
- response = Tweetlr::Processors::Http::http_get_json "http://api.embed.ly/1/oembed?key=#{key}&url=#{link_url}"
62
+ link_url = follow_redirect(link_url)
63
63
  log.debug "embedly call: http://api.embed.ly/1/oembed?key=#{key}&url=#{link_url}"
64
- if response && response['type'] == 'photo'
64
+ response = Tweetlr::Processors::Http::http_get_json "http://api.embed.ly/1/oembed?key=#{key}&url=#{link_url}"
65
+ if response && (response['type'] == 'photo' || response['type'] == 'image')
65
66
  image_url = response['url']
66
67
  end
67
68
  image_url
68
69
  end
69
- #find the image's url for a lockerz link
70
- def self.image_url_lockerz(link_url)
71
- response = Tweetlr::Processors::Http::http_get_json "http://api.plixi.com/api/tpapi.svc/json/metadatafromurl?details=false&url=#{link_url}"
72
- response["BigImageUrl"] if response
73
- end
74
70
  #find the image's url for an twitter shortened link
75
71
  def self.image_url_tco(link_url, embedly_key = nil)
76
72
  service_url = link_url_redirect link_url
@@ -82,33 +78,17 @@ module Tweetlr::Processors
82
78
  response = Tweetlr::Processors::Http::http_get_json "http://api.instagram.com/oembed?url=#{link_url}"
83
79
  response['url'] if response
84
80
  end
85
-
86
- #find the image's url for a picplz short/longlink
87
- def self.image_url_picplz(link_url)
88
- id = extract_id link_url
89
- #try short url
90
- response = Tweetlr::Processors::Http::http_get_json "http://picplz.com/api/v2/pic.json?shorturl_ids=#{id}"
91
- #if short url fails, try long url
92
- #response = HTTParty.get "http://picplz.com/api/v2/pic.json?longurl_ids=#{id}"
93
- #extract url
94
- if response && response['value'] && response['value']['pics'] && response['value']['pics'].first && response['value']['pics'].first['pic_files'] && response['value']['pics'].first['pic_files']['640r']
95
- response['value']['pics'].first['pic_files']['640r']['img_url']
96
- else
97
- nil
98
- end
99
- end
100
81
  #find the image's url for a twitpic link
101
82
  def self.image_url_twitpic(link_url)
102
83
  image_url_redirect link_url, "http://twitpic.com/show/full/"
103
84
  end
104
85
  #find the image'S url for a yfrog link
105
86
  def self.image_url_yfrog(link_url)
106
- response = Tweetlr::Processors::Http::http_get_json("http://www.yfrog.com/api/oembed?url=#{link_url}")
107
- response['url'] if response
87
+ retrieve_image_url_by_css link_url, '#input-direct', 'value'
108
88
  end
109
89
  #find the image's url for a img.ly link
110
- def self.image_url_imgly(link_url)
111
- image_url_redirect link_url, "http://img.ly/show/full/", "\r\n"
90
+ def self.image_url_imgly(link_url, embedly_key)
91
+ retrieve_image_url_by_css link_url, '#the-image'
112
92
  end
113
93
 
114
94
  # extract image url from services like twitpic & img.ly that do not offer oembed interfaces
@@ -121,22 +101,12 @@ module Tweetlr::Processors
121
101
  begin
122
102
  resp = Curl::Easy.http_get(short_url) { |res| res.follow_location = true }
123
103
  rescue Curl::Err::CurlError => err
124
- log.error "Curl::Easy.http_get failed: #{err}"
125
- tries -= 1
126
- sleep 3
127
- if tries > 0
128
- retry
129
- else
130
- return nil
131
- end
132
- end
133
- if(resp && resp.header_str && resp.header_str.index(LOCATION_START_INDICATOR) && resp.header_str.index(stop_indicator))
134
- start = resp.header_str.index(LOCATION_START_INDICATOR) + LOCATION_START_INDICATOR.size
135
- stop = resp.header_str.index(stop_indicator, start)
136
- resp.header_str[start...stop]
137
- else
138
- nil
104
+ log.error "Curl::Easy.http_get failed: #{err}"
105
+ tries -= 1
106
+ sleep 3
107
+ (tries > 0) ? retry : return
139
108
  end
109
+ process_reponse_header resp, stop_indicator
140
110
  end
141
111
 
142
112
  #extract the pic id from a given <code>link</code>
@@ -144,22 +114,36 @@ module Tweetlr::Processors
144
114
  link.split('/').last if link.split('/')
145
115
  end
146
116
  #parse html doc for element signature
147
- def self.parse_html_for(element_signature, html_doc)
117
+ def self.parse_html_for(element_signature, html_doc, identifier="src")
148
118
  image_url= nil
149
119
  if html_doc
150
120
  photo_container_div = html_doc.css(element_signature)
151
- if photo_container_div && photo_container_div.first && photo_container_div.first.attributes["src"]
152
- image_url = photo_container_div.first.attributes["src"].value
121
+ if photo_container_div && photo_container_div.first && photo_container_div.first.attributes[identifier]
122
+ image_url = photo_container_div.first.attributes[identifier].value
153
123
  end
154
124
  end
155
125
  image_url
156
126
  end
157
- def self.retrieve_image_url_by_css link_url, css_path
127
+ def self.retrieve_image_url_by_css(link_url, css_path, selector='src')
128
+ link_url = follow_redirect link_url
129
+ response = Tweetlr::Processors::Http::http_get link_url
130
+ image_url = parse_html_for css_path, Nokogiri::HTML.parse(response.body_str), selector
131
+ return image_url
132
+ end
133
+ private
134
+ def self.process_reponse_header(resp, stop_indicator)
135
+ if(resp && resp.header_str && resp.header_str.index(LOCATION_START_INDICATOR) && resp.header_str.index(stop_indicator))
136
+ start = resp.header_str.index(LOCATION_START_INDICATOR) + LOCATION_START_INDICATOR.size
137
+ stop = resp.header_str.index(stop_indicator, start)
138
+ resp.header_str[start...stop]
139
+ else
140
+ nil
141
+ end
142
+ end
143
+ def self.follow_redirect(link_url)
158
144
  service_url = link_url_redirect link_url #follow possible redirects
159
- link_url = service_url if service_url #if there's no redirect, service_url will be nil
160
- response = Tweetlr::Processors::Http::http_get link_url
161
- image_url = parse_html_for css_path, Nokogiri::HTML.parse(response.body_str)
162
- return image_url
145
+ link_url = service_url if service_url #if there's no redirect, service_url will be nil
146
+ link_url
163
147
  end
164
148
  end
165
149
  end
data/lib/tweetlr.rb CHANGED
@@ -2,7 +2,7 @@ require 'tweetlr/log_aware'
2
2
  require 'tweetlr/core'
3
3
 
4
4
  module Tweetlr
5
- VERSION = '0.1.20'
5
+ VERSION = '0.1.21'
6
6
 
7
7
  API_ENDPOINT_TWITTER = 'http://search.twitter.com/search.json'
8
8
  API_ENDPOINT_TUMBLR = 'http://www.tumblr.com'
@@ -15,10 +15,8 @@ describe Tweetlr::Combinators::TwitterTumblr do
15
15
  :instagram => {'text' => "jadda jadda http://instagr.am/p/DzCWn/"},
16
16
  :twitpic => {'text' => "jadda jadda http://twitpic.com/449o2x"},
17
17
  :yfrog => {'text' => "jadda jadda http://yfrog.com/h4vlfp"},
18
- :picplz => {'text' => "jadda jadda http://picplz.com/2hWv"},
19
18
  :imgly => {'text' => "jadda jadda http://img.ly/3M1o"},
20
19
  :tco => {'text' => "jadda jadda http://t.co/MUGNayA"},
21
- :lockerz => {'text' => "jadda jadda http://lockerz.com/s/100269159"},
22
20
  :embedly => {'text' => "jadda jadda http://flic.kr/p/973hTv"},
23
21
  :twitter_pics => {'text' => "jadda jadda http://t.co/FmyBGfyY"}
24
22
  }
@@ -26,10 +24,8 @@ describe Tweetlr::Combinators::TwitterTumblr do
26
24
  :instagram => "http://instagr.am/p/DzCWn/",
27
25
  :twitpic => "http://twitpic.com/449o2x",
28
26
  :yfrog => "http://yfrog.com/h4vlfp",
29
- :picplz => "http://picplz.com/2hWv",
30
27
  :imgly => "http://img.ly/3M1o",
31
28
  :tco => 'http://t.co/MUGNayA',
32
- :lockerz => 'http://lockerz.com/s/100269159',
33
29
  :embedly => 'http://flic.kr/p/973hTv',
34
30
  :twitter_pics => 'http://t.co/FmyBGfyY'
35
31
  }
@@ -3,28 +3,35 @@ require 'spec_helper'
3
3
  describe Tweetlr::Processors::PhotoService do
4
4
  before :each do
5
5
  @links = {
6
- :twimg => 'http://twitter.com/KSilbereisen/status/228035435237097472',
7
- :eyeem => 'http://www.eyeem.com/p/326629',
8
6
  :foursquare => 'http://4sq.com/x4p87N',
7
+ :eyeem => 'http://www.eyeem.com/p/326629',
9
8
  :path => 'http://path.com/p/KQd57',
10
9
  :instagram => "http://instagr.am/p/DzCWn/",
11
10
  :twitpic => "http://twitpic.com/449o2x",
12
11
  :yfrog => "http://yfrog.com/h4vlfp",
13
- :picplz => "http://picplz.com/2hWv",
14
- :imgly => "http://img.ly/3M1o",
15
12
  :tco => 'http://t.co/MUGNayA',
16
- :lockerz => 'http://lockerz.com/s/100269159',
17
13
  :embedly => 'http://flic.kr/p/973hTv',
18
- :twitter_pics => 'http://t.co/FmyBGfyY'
14
+ :twitter_pics => 'http://t.co/FmyBGfyY',
15
+ :twimg => 'http://twitter.com/KSilbereisen/status/228035435237097472',
16
+ :imgly => "http://img.ly/3M1o"
19
17
  }
20
18
  end
19
+ it "finds a picture's url from the supported services" do
20
+ @links.each do |service,link|
21
+ send "stub_#{service}"
22
+ #puts "checking #{service}"
23
+ url = Tweetlr::Processors::PhotoService::find_image_url link
24
+ url.should be, "service #{service} not working!"
25
+ check_pic_url_extraction service if [:twimg, :instagram,:yfrog,:imgly,:foursqaure,:not_listed].index service
26
+ end
27
+ end
21
28
  it "extracts images from eye em" do
22
29
  stub_eyeem
23
30
  link = Tweetlr::Processors::PhotoService::find_image_url @links[:eyeem]
24
31
  link.should be
25
32
  link.should == "http://www.eyeem.com/thumb/h/1024/e35db836c5d3f02498ef60fc3d53837fbe621561-1334126483"
26
33
  end
27
- it "doesnt find images in embedly results that are not explicitly marked as 'Photo' via the response's 'thumbnail_url' attribute" do
34
+ it "doesnt find images in embedly results that are not explicitly marked as 'Photo' or 'Image' via the response's 'thumbnail_url' attribute" do
28
35
  stub_embedly_no_photo
29
36
  link = Tweetlr::Processors::PhotoService::find_image_url 'http://makersand.co/'
30
37
  link.should be_nil
@@ -32,16 +39,9 @@ describe Tweetlr::Processors::PhotoService do
32
39
  it "does find an image for foursquare that is not he profile pic" do
33
40
  stub_foursquare
34
41
  link = Tweetlr::Processors::PhotoService::find_image_url @links[:foursquare]
42
+ link.should be
35
43
  link.index('userpix_thumbs').should_not be
36
44
  end
37
- it "should find a picture's url from the supported services" do
38
- @links.each do |service,link|
39
- send "stub_#{service}"
40
- url = Tweetlr::Processors::PhotoService::find_image_url link
41
- url.should be, "service #{service} not working!"
42
- check_pic_url_extraction service if [:twimg, :instagram,:picplz,:yfrog,:imgly,:foursqaure,:not_listed].index service
43
- end
44
- end
45
45
  it "finds path images for redirected moments as well" do
46
46
  stub_path_redirected
47
47
  url = Tweetlr::Processors::PhotoService::find_image_url @links[:path]