tweetlr 0.1.7pre4 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -14,6 +14,7 @@ tweetlr supports
14
14
  - yfrog
15
15
  - imgly
16
16
  - twitter / photobucket
17
+ - path.com
17
18
  - t.co shortened links to pictures
18
19
  - every service accessible via embed.ly (see [photo providers](http://embed.ly/providers))
19
20
 
@@ -11,35 +11,38 @@ module Processors
11
11
  def self.log
12
12
  LogAware.log #TODO why doesn't the include make the log method accessible?
13
13
  end
14
-
15
- #convenience method for curl http get calls and parsing them to json.
14
+ #convenience method for curl http get calls
16
15
  def self.http_get(request)
17
16
  tries = 3
17
+ curl = nil
18
18
  begin
19
19
  curl = Curl::Easy.new request
20
20
  curl.useragent = USER_AGENT
21
21
  curl.perform
22
- begin
23
- JSON.parse curl.body_str
24
- rescue JSON::ParserError => err
25
- begin
26
- log.warn "#{err}: Could not parse response for #{request} - this is probably not a json response: #{curl.body_str}"
27
- return nil
28
- rescue Encoding::CompatibilityError => err
29
- log.error "Trying to rescue a JSON::ParserError for '#{request}' we got stuck in a Encoding::CompatibilityError."
30
- return nil
31
- end
32
- end
33
22
  rescue Curl::Err::CurlError => err
34
23
  log.error "Failure in Curl call: #{err}" if log
35
24
  tries -= 1
36
25
  sleep 3
37
26
  if tries > 0
38
- retry
39
- else
40
- nil
27
+ retry
28
+ end
29
+ end
30
+ return curl
31
+ end
32
+ #convenience method for curl http get calls and parsing them to json.
33
+ def self.http_get_json(request)
34
+ curl = self.http_get(request)
35
+ begin
36
+ JSON.parse curl.body_str
37
+ rescue JSON::ParserError => err
38
+ begin
39
+ log.warn "#{err}: Could not parse response for #{request} - this is probably not a json response: #{curl.body_str}"
40
+ return nil
41
+ rescue Encoding::CompatibilityError => err
42
+ log.error "Trying to rescue a JSON::ParserError for '#{request}' we got stuck in a Encoding::CompatibilityError."
43
+ return nil
41
44
  end
42
- end
45
+ end
43
46
  end
44
47
  end
45
48
  end
@@ -1,4 +1,5 @@
1
1
  require 'processors/http'
2
+ require 'nokogiri'
2
3
  require 'log_aware'
3
4
 
4
5
  module Processors
@@ -25,6 +26,7 @@ module Processors
25
26
  url = image_url_imgly link if link.index 'img.ly'
26
27
  url = image_url_tco link, embedly_key if link.index 't.co'
27
28
  url = image_url_lockerz link if link.index 'lockerz.com'
29
+ url = image_url_path link if link.index 'path.com'
28
30
  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.
29
31
  elsif photo? link
30
32
  url = link
@@ -35,10 +37,24 @@ module Processors
35
37
  def self.photo?(link)
36
38
  link =~ PIC_REGEXP
37
39
  end
40
+
41
+ #extract the image of a path.com pic
42
+ def self.image_url_path(link_url)
43
+ image_url=nil
44
+ html_response = Processors::Http::http_get link_url
45
+ html_doc = Nokogiri::HTML.parse(html_response.body_str)
46
+ if html_doc
47
+ photo_container_div = html_doc.css("img.photo-image")
48
+ if photo_container_div && photo_container_div.first && photo_container_div.first.attributes["src"]
49
+ image_url = photo_container_div.first.attributes["src"].value
50
+ end
51
+ end
52
+ return image_url
53
+ end
38
54
 
39
55
  #find the image's url via embed.ly
40
56
  def self.image_url_embedly(link_url, key)
41
- response = Processors::Http::http_get "http://api.embed.ly/1/oembed?key=#{key}&url=#{link_url}"
57
+ response = Processors::Http::http_get_json "http://api.embed.ly/1/oembed?key=#{key}&url=#{link_url}"
42
58
  log.debug "embedly call: http://api.embed.ly/1/oembed?key=#{key}&url=#{link_url}"
43
59
  if response && response['type'] == 'photo'
44
60
  image_url = response['url']
@@ -47,7 +63,7 @@ module Processors
47
63
  end
48
64
  #find the image's url for a lockerz link
49
65
  def self.image_url_lockerz(link_url)
50
- response = Processors::Http::http_get "http://api.plixi.com/api/tpapi.svc/json/metadatafromurl?details=false&url=#{link_url}"
66
+ response = Processors::Http::http_get_json "http://api.plixi.com/api/tpapi.svc/json/metadatafromurl?details=false&url=#{link_url}"
51
67
  response["BigImageUrl"] if response
52
68
  end
53
69
  #find the image's url for an twitter shortened link
@@ -58,7 +74,7 @@ module Processors
58
74
  #find the image's url for an instagram link
59
75
  def self.image_url_instagram(link_url)
60
76
  link_url['instagram.com'] = 'instagr.am' if link_url.index 'instagram.com' #instagram's oembed does not work for .com links
61
- response = Processors::Http::http_get "http://api.instagram.com/oembed?url=#{link_url}"
77
+ response = Processors::Http::http_get_json "http://api.instagram.com/oembed?url=#{link_url}"
62
78
  response['url'] if response
63
79
  end
64
80
 
@@ -66,7 +82,7 @@ module Processors
66
82
  def self.image_url_picplz(link_url)
67
83
  id = extract_id link_url
68
84
  #try short url
69
- response = Processors::Http::http_get "http://picplz.com/api/v2/pic.json?shorturl_ids=#{id}"
85
+ response = Processors::Http::http_get_json "http://picplz.com/api/v2/pic.json?shorturl_ids=#{id}"
70
86
  #if short url fails, try long url
71
87
  #response = HTTParty.get "http://picplz.com/api/v2/pic.json?longurl_ids=#{id}"
72
88
  #extract url
@@ -82,7 +98,7 @@ module Processors
82
98
  end
83
99
  #find the image'S url for a yfrog link
84
100
  def self.image_url_yfrog(link_url)
85
- response = Processors::Http::http_get("http://www.yfrog.com/api/oembed?url=#{link_url}")
101
+ response = Processors::Http::http_get_json("http://www.yfrog.com/api/oembed?url=#{link_url}")
86
102
  response['url'] if response
87
103
  end
88
104
  #find the image's url for a img.ly link
@@ -25,7 +25,7 @@ module Processors
25
25
  #fire a new search
26
26
  def self.search(config)
27
27
  search_call = "#{config[:api_endpoint_twitter]}?ors=#{config[:search_term]}&result_type=#{config[:result_type]}&rpp=#{config[:results_per_page]}"
28
- Processors::Http::http_get search_call
28
+ Processors::Http::http_get_json search_call
29
29
  end
30
30
 
31
31
  # lazy update - search for a term or refresh the search if a response is available already
@@ -34,7 +34,7 @@ module Processors
34
34
  if config
35
35
  search_url = "#{config[:api_endpoint_twitter]}?since_id=#{config[:since_id]}&ors=#{config[:search_term]}&result_type=#{config[:result_type]}&rpp=#{config[:results_per_page]}"
36
36
  log.info "lazy search using '#{search_url}'"
37
- response = Processors::Http::http_get search_url
37
+ response = Processors::Http::http_get_json search_url
38
38
  else
39
39
  log.error "#{self}.lazy_search: no config given!"
40
40
  end
data/lib/tweetlr.rb CHANGED
@@ -12,7 +12,7 @@ require 'log_aware'
12
12
 
13
13
  class Tweetlr
14
14
 
15
- VERSION = '0.1.7pre4'
15
+ VERSION = '0.1.7'
16
16
 
17
17
  API_ENDPOINT_TWITTER = 'http://search.twitter.com/search.json'
18
18
  API_ENDPOINT_TUMBLR = 'http://www.tumblr.com'
@@ -3,6 +3,7 @@ require 'spec_helper'
3
3
  describe Processors::PhotoService do
4
4
  before :each do
5
5
  @links = {
6
+ :path => 'https://path.com/p/1OKhLx',
6
7
  :instagram => "http://instagr.am/p/DzCWn/",
7
8
  :twitpic => "http://twitpic.com/449o2x",
8
9
  :yfrog => "http://yfrog.com/h4vlfp",
@@ -11,7 +12,7 @@ describe Processors::PhotoService do
11
12
  :tco => 'http://t.co/MUGNayA',
12
13
  :lockerz => 'http://lockerz.com/s/100269159',
13
14
  :embedly => 'http://flic.kr/p/973hTv',
14
- :twitter_pics => 'http://t.co/FmyBGfyY'
15
+ :twitter_pics => 'http://t.co/FmyBGfyY'
15
16
  }
16
17
  end
17
18
  it "should find a picture's url from the supported services" do
data/spec/spec_helper.rb CHANGED
@@ -11,6 +11,265 @@ def check_pic_url_extraction(service)
11
11
  image_url.should =~ Processors::PhotoService::PIC_REGEXP
12
12
  end
13
13
 
14
+ def stub_path
15
+ Curl::Easy.any_instance.stub(:perform).and_return Curl::Easy.new
16
+ Curl::Easy.any_instance.stub(:body_str).and_return %^
17
+
18
+ <div class="moments_photo moments_photo-landscape">
19
+ <div class="photo-container">
20
+ <img src="https://s3-us-west-1.amazonaws.com/images.path.com/photos2/f90fd831-43c3-48fd-84cb-5c3bae52957a/2x.jpg" width="480" height="358.5" class="moment-block photo-image" />
21
+ <b class="photo-border" style="width: 478px; height: 356.5px;"></b>
22
+ </div>
23
+ </div>
24
+
25
+
26
+ <div class="moment-block">
27
+
28
+
29
+
30
+
31
+ <div class="moments_feedback">
32
+
33
+ <div class="moment-description">
34
+
35
+ <div class="moment-tags">
36
+
37
+ <span class="moment-author">Sven Kräuter</span>
38
+
39
+
40
+
41
+ <span class="moment-timestamp">1 hour ago</span>
42
+ </div>
43
+
44
+ <div class="feedback-actions">
45
+ <div class="emotion-picker">
46
+ <div class="emotion-picker-box">
47
+ <ul class="emotion-icon-set">
48
+ <li class="emotion-icon happy">
49
+ <a href="#" class="emotion-icon-a" data-emotion-type="happy">Happy</a>
50
+ </li>
51
+ <li class="emotion-icon laugh">
52
+ <a href="#" class="emotion-icon-a" data-emotion-type="laugh">Laugh</a>
53
+ </li>
54
+ <li class="emotion-icon surprise">
55
+ <a href="#" class="emotion-icon-a" data-emotion-type="surprise">Surprise</a>
56
+ </li>
57
+ <li class="emotion-icon sad">
58
+ <a href="#" class="emotion-icon-a" data-emotion-type="sad">Sad</a>
59
+ </li>
60
+ <li class="emotion-icon love">
61
+ <a href="#" class="emotion-icon-a" data-emotion-type="love">Love</a>
62
+ </li>
63
+ </ul>
64
+ </div>
65
+ <a href="#" class="action action-emotion"><b class="None">Add Emotion</b></a>
66
+ </div>
67
+
68
+ <a href="#" class="action action-comment"><b>Add Comment</b></a>
69
+ </div>
70
+ </div>
71
+
72
+ <div class="seen-it-container">
73
+ <ul class="seen-it-set">
74
+
75
+ <li class="user user-small seen-it tooltip-target">
76
+
77
+ <img src="https://s3-us-west-1.amazonaws.com/images.path.com/profile_photos/4d973b511f60bf3eae6dc418a86e848653ad90ac/processed_80x80.jpg" class="user-photo" />
78
+ <div class="tooltip-block">
79
+ <div class="tooltip-container">
80
+ <b class="tooltip-text">Thies Arntzen</b>
81
+ <b class="tooltip-pointer"></b>
82
+ </div>
83
+ </div>
84
+
85
+ <b class="user-border"></b>
86
+
87
+ </li>
88
+
89
+ <li class="user user-small seen-it tooltip-target">
90
+
91
+ <img src="https://s3-us-west-1.amazonaws.com/images.path.com/profile_photos/34255fba4020523f71a25b05b89d86f80d19850b/processed_80x80.jpg" class="user-photo" />
92
+ <div class="tooltip-block">
93
+ <div class="tooltip-container">
94
+ <b class="tooltip-text">Sven Kräuter</b>
95
+ <b class="tooltip-pointer"></b>
96
+ </div>
97
+ </div>
98
+
99
+ <b class="user-border"></b>
100
+
101
+ </li>
102
+
103
+ <li class="user user-small seen-it seen-it-blank tooltip-target">
104
+
105
+ <b class="user-border"></b>
106
+
107
+ </li>
108
+
109
+ <li class="user user-small seen-it seen-it-blank tooltip-target">
110
+
111
+ <b class="user-border"></b>
112
+
113
+ </li>
114
+
115
+ <li class="user user-small seen-it seen-it-blank tooltip-target">
116
+
117
+ <b class="user-border"></b>
118
+
119
+ </li>
120
+
121
+ <li class="user user-small seen-it seen-it-blank tooltip-target">
122
+
123
+ <b class="user-border"></b>
124
+
125
+ </li>
126
+
127
+ <li class="user user-small seen-it seen-it-blank tooltip-target">
128
+
129
+ <b class="user-border"></b>
130
+
131
+ </li>
132
+
133
+ <li class="user user-small seen-it seen-it-blank tooltip-target">
134
+
135
+ <b class="user-border"></b>
136
+
137
+ </li>
138
+
139
+ <li class="user user-small seen-it seen-it-blank tooltip-target">
140
+
141
+ <b class="user-border"></b>
142
+
143
+ </li>
144
+
145
+ <li class="user user-small seen-it seen-it-blank tooltip-target">
146
+
147
+ <b class="user-border"></b>
148
+
149
+ </li>
150
+
151
+ <li class="clear"></li>
152
+ </ul>
153
+
154
+ </div>
155
+
156
+ <ul class="comment-set">
157
+
158
+ <li class="comment">
159
+ <div class="user comment-user">
160
+ <img src="https://s3-us-west-1.amazonaws.com/images.path.com/profile_photos/34255fba4020523f71a25b05b89d86f80d19850b/processed_80x80.jpg" class="user-photo" />
161
+ <b class="user-border"></b>
162
+ </div>
163
+ <h4 class="comment-author">Sven Kräuter</h4>
164
+ <div class="comment-body">#coffeediary usually not a big fan of industrial beans, I have to admit: the segafredo intermezzo is quite amazing</div>
165
+ <h5 class="comment-timestamp">
166
+ <span class="comment-date"><time class="timestamp" datetime="2011-12-10T17:49:54Z">December 10, 2011 at 17:49</time></span>
167
+
168
+ <span class="comment-location">from Hamburg, Germany</span>
169
+
170
+ </h5>
171
+
172
+
173
+ </li>
174
+
175
+ </ul>
176
+
177
+ <div class="comment-box">
178
+
179
+ <form action="/comments/create" method="POST" class="comment-form">
180
+ <div class="comment-sizer">And a comment!</div>
181
+ <input type="hidden" name="moment_id" value="4ee39bcf7c215078e9031249" />
182
+ <textarea class="comment-field" name="body" rows="1" placeholder="Add a comment..."></textarea>
183
+ </form>
184
+
185
+ <div class="comment-blocker">
186
+ <b>Login required</b>
187
+ </div>
188
+
189
+ </div>
190
+
191
+ </div><!-- // moments_feedback -->
192
+ <div class="timeline-arrow"></div>
193
+ </div>
194
+
195
+ </div>
196
+
197
+
198
+
199
+
200
+
201
+ </div>
202
+
203
+
204
+
205
+
206
+
207
+
208
+
209
+ <script src="/static/cache/javascripts/all.js?1323473167"></script>
210
+
211
+
212
+
213
+
214
+
215
+
216
+
217
+
218
+
219
+
220
+ <script type="text/javascript" charset="utf-8">
221
+ Ply.ui.register('shared', {
222
+ view: document.body
223
+ });
224
+
225
+ Ply.ui.register('moments_show');
226
+
227
+ </script>
228
+
229
+
230
+ <script type="text/javascript">
231
+ var _gaq = _gaq || [];
232
+ _gaq.push(['_setAccount', 'UA-9066780-2']);
233
+ _gaq.push(['_trackPageview']);
234
+
235
+ (function() {
236
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
237
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
238
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
239
+ })();
240
+ </script>
241
+
242
+
243
+ <script type="text/javascript">
244
+ var _sf_async_config={uid:28481,domain:"path.com"};
245
+ (function(){
246
+ function loadChartbeat() {
247
+ window._sf_endpt=(new Date()).getTime();
248
+ var e = document.createElement('script');
249
+ e.setAttribute('language', 'javascript');
250
+ e.setAttribute('type', 'text/javascript');
251
+ e.setAttribute('src', (("https:" == document.location.protocol) ? "https://a248.e.akamai.net/chartbeat.download.akamai.com/102508/" : "http://static.chartbeat.com/") + "js/chartbeat.js");
252
+ document.body.appendChild(e);
253
+ }
254
+ var oldonload = window.onload;
255
+ window.onload = (typeof window.onload != 'function') ? loadChartbeat : function() { oldonload(); loadChartbeat(); };
256
+ })();
257
+ </script>
258
+
259
+
260
+ <script type="text/javascript">var mpq=[];mpq.push(["init","8317b3b4f5a2a5fdba3c5a4782c7289f"]);(function(){var b,a,e,d,c;b=document.createElement("script");b.type="text/javascript";b.async=true;b.src=(document.location.protocol==="https:"?"https:":"http:")+"//api.mixpanel.com/site_media/js/api/mixpanel.js";a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(b,a);e=function(f){return function(){mpq.push([f].concat(Array.prototype.slice.call(arguments,0)))}};d=["init","track","track_links","track_forms","register","register_once","identify","name_tag","set_config"];for(c=0;c<d.length;c++){mpq[d[c]]=e(d[c])}})();
261
+
262
+ mpq.identify("687ad7fc-2360-11e1-8ff7-12313e006031");
263
+
264
+
265
+ </script>
266
+
267
+
268
+ <script src="https://cdn.optimizely.com/js/6548263.js"></script>
269
+ </body>
270
+ </html>^
271
+ end
272
+
14
273
  def stub_tumblr
15
274
  Curl::Easy.any_instance.stub(:response_code).and_return 201
16
275
  Curl::Easy.any_instance.stub(:header_str).and_return %|HTTP/1.1 201 Created
data/tweetlr.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "tweetlr"
3
- s.version = "0.1.7pre4"
3
+ s.version = "0.1.7"
4
4
  s.author = "Sven Kraeuter"
5
5
  s.email = "sven.kraeuter@gmail.com"
6
6
  s.homepage = "http://tweetlr.5v3n.com"
@@ -14,6 +14,7 @@ Gem::Specification.new do |s|
14
14
  s.add_dependency "eventmachine"
15
15
  s.add_dependency "curb"
16
16
  s.add_dependency "json"
17
+ s.add_dependency "nokogiri"
17
18
 
18
19
  s.add_development_dependency "rake"
19
20
  s.add_development_dependency "rspec"
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tweetlr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7pre4
5
- prerelease: 5
4
+ version: 0.1.7
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Sven Kraeuter
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-18 00:00:00.000000000Z
12
+ date: 2011-12-10 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: daemons
16
- requirement: &2153761960 !ruby/object:Gem::Requirement
16
+ requirement: &2161739880 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2153761960
24
+ version_requirements: *2161739880
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: eventmachine
27
- requirement: &2153761540 !ruby/object:Gem::Requirement
27
+ requirement: &2161739420 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2153761540
35
+ version_requirements: *2161739420
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: curb
38
- requirement: &2153761120 !ruby/object:Gem::Requirement
38
+ requirement: &2161738960 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *2153761120
46
+ version_requirements: *2161738960
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: json
49
- requirement: &2153760700 !ruby/object:Gem::Requirement
49
+ requirement: &2161738540 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,21 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *2153760700
57
+ version_requirements: *2161738540
58
+ - !ruby/object:Gem::Dependency
59
+ name: nokogiri
60
+ requirement: &2161726220 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *2161726220
58
69
  - !ruby/object:Gem::Dependency
59
70
  name: rake
60
- requirement: &2153760280 !ruby/object:Gem::Requirement
71
+ requirement: &2161725800 !ruby/object:Gem::Requirement
61
72
  none: false
62
73
  requirements:
63
74
  - - ! '>='
@@ -65,10 +76,10 @@ dependencies:
65
76
  version: '0'
66
77
  type: :development
67
78
  prerelease: false
68
- version_requirements: *2153760280
79
+ version_requirements: *2161725800
69
80
  - !ruby/object:Gem::Dependency
70
81
  name: rspec
71
- requirement: &2153759860 !ruby/object:Gem::Requirement
82
+ requirement: &2161725280 !ruby/object:Gem::Requirement
72
83
  none: false
73
84
  requirements:
74
85
  - - ! '>='
@@ -76,10 +87,10 @@ dependencies:
76
87
  version: '0'
77
88
  type: :development
78
89
  prerelease: false
79
- version_requirements: *2153759860
90
+ version_requirements: *2161725280
80
91
  - !ruby/object:Gem::Dependency
81
92
  name: rdoc
82
- requirement: &2153759440 !ruby/object:Gem::Requirement
93
+ requirement: &2161724740 !ruby/object:Gem::Requirement
83
94
  none: false
84
95
  requirements:
85
96
  - - ! '>='
@@ -87,7 +98,7 @@ dependencies:
87
98
  version: '0'
88
99
  type: :development
89
100
  prerelease: false
90
- version_requirements: *2153759440
101
+ version_requirements: *2161724740
91
102
  description: tweetlr crawls twitter for a given term, extracts photos out of the collected
92
103
  tweets' short urls and posts the images to tumblr.
93
104
  email: sven.kraeuter@gmail.com
@@ -136,9 +147,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
136
147
  required_rubygems_version: !ruby/object:Gem::Requirement
137
148
  none: false
138
149
  requirements:
139
- - - ! '>'
150
+ - - ! '>='
140
151
  - !ruby/object:Gem::Version
141
- version: 1.3.1
152
+ version: '0'
142
153
  requirements: []
143
154
  rubyforge_project: tweetlr
144
155
  rubygems_version: 1.8.10