tweetlr 0.1.17pre → 0.1.17

Sign up to get free protection for your applications and to get access to all the features.
data/bin/tweetlr CHANGED
@@ -21,11 +21,14 @@ begin
21
21
  CONFIG['start_at_tweet_id'] = start_at_tweet_id || CONFIG['start_at_tweet_id'] || CONFIG['twitter_timestamp'] #check the latter for backwards compability
22
22
 
23
23
  UPDATE_PERIOD = CONFIG['update_period']
24
-
24
+
25
25
  @tweetlr_config = {
26
- :tumblr_email => CONFIG['tumblr_username'],
27
- :tumblr_password => CONFIG['tumblr_password'],
28
- :group => CONFIG['group'],
26
+ :tumblr_blog_hostname => CONFIG['tumblr_blog_hostname'] || CONFIG['group'],
27
+ :tumblr_oauth_api_key => CONFIG['tumblr_oauth_api_key'],
28
+ :tumblr_oauth_api_secret => CONFIG['tumblr_oauth_api_secret'],
29
+ :tumblr_blog_hostname => CONFIG['tumblr_blog_hostname'],
30
+ :tumblr_oauth_access_token_key => CONFIG['tumblr_oauth_access_token_key'],
31
+ :tumblr_oauth_access_token_secret => CONFIG['tumblr_oauth_access_token_secret'],
29
32
  :whitelist => CONFIG['whitelist'],
30
33
  :shouts => CONFIG['shouts'],
31
34
  :since_id => CONFIG['start_at_tweet_id'] ,
@@ -46,7 +49,7 @@ end
46
49
  Daemons.run_proc('tweetlr', :dir_mode => :script, :dir => './', :backtrace => true, :log_output => true) do
47
50
  @log = Logger.new(STDOUT)
48
51
  @log.info "starting tweetlr daemon..."
49
- @log.info "creating a new tweetlr instance using this config: #{CONFIG.inspect}"
52
+ @log.info "creating a new tweetlr instance using this config: #{@tweetlr_config.inspect}"
50
53
  EventMachine::run do
51
54
  EventMachine::add_periodic_timer( UPDATE_PERIOD ) do
52
55
  response = Tweetlr.crawl(@tweetlr_config)
data/config/tweetlr.yml CHANGED
@@ -4,8 +4,11 @@ search_term: 'cat+dog+unicorn' #find tweets containing any of these terms
4
4
  start_at_tweet_id: 61847783463854082 # the tweet id to start searching at
5
5
  api_endpoint_twitter: 'http://search.twitter.com/search.json'
6
6
  api_endpoint_tumblr: 'http://www.tumblr.com'
7
- tumblr_username: YOUR_TUMBLR_EMAIL
8
- tumblr_password: YOUR_TUMBLR_PW
7
+ tumblr_oauth_api_key: YOUR APPS TUMBLR API TOKEN
8
+ tumblr_oauth_api_secret: YOUR APPS TUMBLR API SECRET
9
+ tumblr_oauth_access_token_key: YOUR BLOGS OAUTH ACCESS TOKEN KEY
10
+ tumblr_oauth_access_token_secret: YOUR BLOGS OAUTH ACCESS TOKEN SECRE
11
+ group: TUMBLR_GROUP_TO_POST_TO #e.g. mysubblog.tumblr.com
9
12
  embedly_key: '' #tweetlr uses http://embedly.com for link processing. a free plan containing an api key is available & recommended to use in order to ensure full support
10
13
  update_period: 300 #check for updates every 300 secs = 5 minutes
11
14
  shouts: 'says' # will be concatenated after the username, before the message: @mr_x says: awesome things on a photo!
@@ -32,7 +32,7 @@ module Combinators
32
32
  if !Processors::Twitter::retweet? message
33
33
  log.debug "tweet: #{tweet}"
34
34
  tumblr_post = {}
35
- tumblr_post[:group] = options[:group]
35
+ tumblr_post[:tumblr_blog_hostname] = options[:tumblr_blog_hostname] || options[:group]
36
36
  tumblr_post[:type] = 'photo'
37
37
  tumblr_post[:date] = tweet['created_at']
38
38
  tumblr_post[:source] = extract_image_url tweet, options[:embedly_key]
@@ -1,4 +1,5 @@
1
1
  require 'log_aware'
2
+ require 'oauth'
2
3
 
3
4
  module Processors
4
5
  #utilities for handling tumblr
@@ -11,38 +12,40 @@ module Processors
11
12
  end
12
13
  #post a tumblr photo entry.
13
14
  #
14
- #required arguments are :email, :password, :type, :date, :source, :caption, :state, :source
15
+ #required arguments are :tumblr_blog_hostname, :tumblr_blog_hostname, :tumblr_oauth_api_secret, :tumblr_oauth_access_token_secret, :source, :caption, :state
15
16
  #
16
- #optional arguments: :api_endpoint_tumblr, :tags, :group
17
+ #optional arguments: :tags, :type (default: 'photo')
17
18
  #
18
19
  def self.post(options={})
19
- tries = 3
20
- tags = options[:tags] || ''
21
- group = options[:group] || ''
22
- begin
23
- response = Curl::Easy.http_post("#{options[:api_endpoint_tumblr] || API_ENDPOINT_TUMBLR}/api/write",
24
- Curl::PostField.content('generator', GENERATOR),
25
- Curl::PostField.content('email', options[:email]),
26
- Curl::PostField.content('password', options[:password]),
27
- Curl::PostField.content('type', options[:type]),
28
- Curl::PostField.content('date', options[:date]),
29
- Curl::PostField.content('source', options[:source]),
30
- Curl::PostField.content('caption', options[:caption]),
31
- Curl::PostField.content('state', options[:state]),
32
- Curl::PostField.content('tags', tags),
33
- Curl::PostField.content('group', group)
34
- )
35
- rescue Curl::Err::CurlError => err
36
- log.error "Failure in Curl call: #{err}"
37
- tries -= 1
38
- sleep 3
39
- if tries > 0
40
- retry
41
- else
42
- response = nil
43
- end
44
- end
45
- response
20
+ base_hostname = options[:tumblr_blog_hostname] || options[:group]
21
+ tumblr_oauth_api_key= options[:tumblr_oauth_api_key]
22
+ tumblr_oauth_api_secret= options[:tumblr_oauth_api_secret]
23
+ access_token_key = options[:tumblr_oauth_access_token_key]
24
+ access_token_secret = options[:tumblr_oauth_access_token_secret]
25
+ type = options[:type] || 'photo'
26
+ tags = options[:tags] || ''
27
+
28
+ consumer = OAuth::Consumer.new(tumblr_oauth_api_key, tumblr_oauth_api_secret,
29
+ { :site => 'http://www.tumblr.com',
30
+ :request_token_path => '/oauth/request_token',
31
+ :authorize_path => '/oauth/authorize',
32
+ :access_token_path => '/oauth/access_token',
33
+ :http_method => :post } )
34
+
35
+ access_token = OAuth::AccessToken.new(consumer, access_token_key, access_token_secret)
36
+
37
+ post_response = access_token.post(
38
+ "http://api.tumblr.com/v2/blog/#{base_hostname}/post", {
39
+ :type => type,
40
+ :source => options[:source],
41
+ :caption => options[:caption],
42
+ :date => options[:date],
43
+ :tags => tags,
44
+ :state => options[:state],
45
+ :generator => GENERATOR
46
+ }
47
+ )
48
+ post_response
46
49
  end
47
50
  end
48
51
  end
data/lib/tweetlr.rb CHANGED
@@ -9,7 +9,7 @@ require 'uri'
9
9
 
10
10
  class Tweetlr
11
11
 
12
- VERSION = '0.1.17pre'
12
+ VERSION = '0.1.17'
13
13
 
14
14
  API_ENDPOINT_TWITTER = 'http://search.twitter.com/search.json'
15
15
  API_ENDPOINT_TUMBLR = 'http://www.tumblr.com'
@@ -53,6 +53,13 @@ class Tweetlr
53
53
  :result_type => config[:result_type] || TWITTER_RESULTS_TYPE,
54
54
  :api_endpoint_twitter => config[:api_endpoint_twitter] || API_ENDPOINT_TWITTER
55
55
  }
56
+ tumblr_config = { :tumblr_oauth_access_token_key => config[:tumblr_oauth_access_token_key],
57
+ :tumblr_oauth_access_token_secret => config[:tumblr_oauth_access_token_secret],
58
+ :tumblr_oauth_api_key => config[:tumblr_oauth_api_key],
59
+ :tumblr_oauth_api_secret => config[:tumblr_oauth_api_secret],
60
+ :tumblr_blog_hostname => config[:tumblr_blog_hostname] || config[:group]
61
+ }
62
+
56
63
  twitter_config[:search_term] = URI::escape(twitter_config[:search_term]) if twitter_config[:search_term]
57
64
  log.info "starting tweetlr crawl..."
58
65
  response = {}
@@ -66,8 +73,8 @@ class Tweetlr
66
73
  log.warn "could not get image source: tweet: #{tweet} --- tumblr post: #{tumblr_post.inspect}"
67
74
  else
68
75
  log.debug "tumblr post: #{tumblr_post}"
69
- res = Processors::Tumblr.post tumblr_post.merge({:password => config[:tumblr_password], :email => config[:tumblr_email]})
70
- log.warn "tumblr response: #{res.header_str} #{res.body_str}" unless res.response_code == 201
76
+ res = Processors::Tumblr.post tumblr_post.merge(tumblr_config)
77
+ log.warn "tumblr response: #{res.header} #{res.body}" unless res.code == "201"
71
78
  end
72
79
  end
73
80
  # store the highest tweet id
@@ -96,16 +96,17 @@ describe Combinators::TwitterTumblr do
96
96
  end
97
97
  end
98
98
  context "copes with different tumblelogs namely" do
99
- it "uses the main blog as default" do
99
+ it "uses a given blog via group option to post to" do
100
100
  stub_instagram
101
- tumblr_post = Combinators::TwitterTumblr.generate_photo_post_from_tweet @twitter_response, :whitelist => @whitelist
102
- tumblr_post[:group].should_not be
101
+ desired_group = 'mygroup.tumblr.com'
102
+ tumblr_post = Combinators::TwitterTumblr.generate_photo_post_from_tweet @twitter_response, {:whitelist => @whitelist, :group => desired_group}
103
+ tumblr_post[:tumblr_blog_hostname].should eq desired_group
103
104
  end
104
- it "uses a given sub-log (aka group)" do
105
+ it "uses a given blog via tumblr_blog_hostname to post to" do
105
106
  stub_instagram
106
107
  desired_group = 'mygroup.tumblr.com'
107
- tumblr_post = Combinators::TwitterTumblr.generate_photo_post_from_tweet @twitter_response, {:whitelist => @whitelist, :group => desired_group}
108
- tumblr_post[:group].should eq desired_group
108
+ tumblr_post = Combinators::TwitterTumblr.generate_photo_post_from_tweet @twitter_response, {:whitelist => @whitelist, :tumblr_blog_hostname => desired_group}
109
+ tumblr_post[:tumblr_blog_hostname].should eq desired_group
109
110
  end
110
111
  end
111
112
  end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Processors::Tumblr do
4
+ before :all do
5
+ config_file = File.join( Dir.pwd, 'config', 'tweetlr.yml')
6
+ config = YAML.load_file(config_file)
7
+ @twitter_response = {"from_user_id_str"=>"1915714", "profile_image_url"=>"http://a0.twimg.com/profile_images/386000279/2_normal.jpg", "created_at"=>"Sun, 17 Apr 2011 16:48:42 +0000", "from_user"=>"whitey_Mc_whIteLIst", "id_str"=>"59659561224765440", "metadata"=>{"result_type"=>"recent"}, "to_user_id"=>nil, "text"=>"Rigaer #wirsounterwegs #{@first_link} @ Augenarzt Dr. Lierow #{@second_link} #{@third_link}", "id"=>59659561224765440, "from_user_id"=>1915714, "geo"=>{"type"=>"Point", "coordinates"=>[52.5182, 13.454]}, "iso_language_code"=>"de", "place"=>{"id"=>"3078869807f9dd36", "type"=>"city", "full_name"=>"Berlin, Berlin"}, "to_user_id_str"=>nil, "source"=>"<a href="http://instagr.am" rel="nofollow">instagram</a>"}
8
+ @tweetlr_config = {
9
+ :since_id => 0,
10
+ :search_term => 'moped',
11
+ :results_per_page => 100,
12
+ :result_type => 'recent',
13
+ :api_endpoint_twitter => Tweetlr::API_ENDPOINT_TWITTER,
14
+ :tumblr_oauth_api_key => config['tumblr_oauth_api_key'],
15
+ :tumblr_oauth_api_secret => config['tumblr_oauth_api_secret'],
16
+ :tumblr_blog_hostname => config['tumblr_blog_hostname'],
17
+ :tumblr_oauth_access_token_key => config['tumblr_oauth_access_token_key'],
18
+ :tumblr_oauth_access_token_secret => config['tumblr_oauth_access_token_secret']
19
+ }
20
+ end
21
+ it "posts to tumblr" do
22
+ stub_tumblr
23
+ stub_oauth
24
+ tumblr_post = Combinators::TwitterTumblr::generate_photo_post_from_tweet @twitter_response, @tweetlr_config
25
+ tumblr_post[:date] = Time.now.to_s
26
+ tumblr_post[:source] = 'http://distilleryimage6.instagram.com/db72627effde11e1b3f322000a1e8899_7.jpg'
27
+ response = Processors::Tumblr::post @tweetlr_config.merge(tumblr_post)
28
+ response.should be
29
+ response.code.should == "201"
30
+ end
31
+ end
data/spec/spec_helper.rb CHANGED
@@ -12,6 +12,10 @@ def check_pic_url_extraction(service)
12
12
  image_url.should =~ Processors::PhotoService::PIC_REGEXP
13
13
  end
14
14
 
15
+ def stub_oauth
16
+ OAuth::AccessToken.any_instance.stub(:post).and_return(Net::HTTPCreated.new("Created.", "201", nil))
17
+ end
18
+
15
19
  def stub_tumblr
16
20
  Curl::Easy.any_instance.stub(:response_code).and_return 201
17
21
  Curl::Easy.any_instance.stub(:header_str).and_return %|HTTP/1.1 201 Created
data/spec/tweetlr_spec.rb CHANGED
@@ -4,8 +4,6 @@ describe Tweetlr do
4
4
 
5
5
  config_file = File.join( Dir.pwd, 'config', 'tweetlr.yml')
6
6
  config = YAML.load_file(config_file)
7
- USER = config['tumblr_username']
8
- PW = config['tumblr_password']
9
7
  TIMESTAMP = config['twitter_timestamp']
10
8
  WHITELIST = config['whitelist']
11
9
 
@@ -15,9 +13,6 @@ describe Tweetlr do
15
13
  @third_link = "https://imageurl.com"
16
14
  @twitter_response = {"from_user_id_str"=>"1915714", "profile_image_url"=>"http://a0.twimg.com/profile_images/386000279/2_normal.jpg", "created_at"=>"Sun, 17 Apr 2011 16:48:42 +0000", "from_user"=>"whitey_Mc_whIteLIst", "id_str"=>"59659561224765440", "metadata"=>{"result_type"=>"recent"}, "to_user_id"=>nil, "text"=>"Rigaer #wirsounterwegs #{@first_link} @ Augenarzt Dr. Lierow #{@second_link} #{@third_link}", "id"=>59659561224765440, "from_user_id"=>1915714, "geo"=>{"type"=>"Point", "coordinates"=>[52.5182, 13.454]}, "iso_language_code"=>"de", "place"=>{"id"=>"3078869807f9dd36", "type"=>"city", "full_name"=>"Berlin, Berlin"}, "to_user_id_str"=>nil, "source"=>"<a href="http://instagr.am" rel="nofollow">instagram</a>"}
17
15
  @tweetlr_config = {
18
- :tumblr_email => USER,
19
- :tumblr_pw => PW,
20
- :whitelist => WHITELIST,
21
16
  :since_id => 0,
22
17
  :search_term => 'moped',
23
18
  :results_per_page => 100,
@@ -25,19 +20,9 @@ describe Tweetlr do
25
20
  :api_endpoint_twitter => Tweetlr::API_ENDPOINT_TWITTER
26
21
  }
27
22
  end
28
- it "should post to tumblr" do
29
- stub_tumblr
30
- tumblr_post = Combinators::TwitterTumblr::generate_photo_post_from_tweet @twitter_response
31
- tumblr_post[:date] = Time.now.to_s
32
- response = Processors::Tumblr::post tumblr_post.merge({:email => USER, :password => PW})
33
- response.should be
34
- response.response_code.should be 201
35
- end
36
23
  it "crawls twitter and posts to tumblr" do
37
24
  stub_tumblr
38
25
  stub_twitter
39
26
  Tweetlr.crawl(@tweetlr_config)
40
27
  end
41
-
42
-
43
28
  end
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.17pre"
3
+ s.version = "0.1.17"
4
4
  s.author = "Sven Kraeuter"
5
5
  s.email = "sven.kraeuter@gmail.com"
6
6
  s.homepage = "http://tweetlr.5v3n.com"
@@ -15,6 +15,7 @@ Gem::Specification.new do |s|
15
15
  s.add_dependency "curb"
16
16
  s.add_dependency "json"
17
17
  s.add_dependency "nokogiri"
18
+ s.add_dependency "oauth"
18
19
 
19
20
  s.add_development_dependency "rake"
20
21
  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.17pre
5
- prerelease: 6
4
+ version: 0.1.17
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: 2012-09-10 00:00:00.000000000 Z
12
+ date: 2012-09-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: daemons
16
- requirement: &2152750420 !ruby/object:Gem::Requirement
16
+ requirement: &2160430840 !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: *2152750420
24
+ version_requirements: *2160430840
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: eventmachine
27
- requirement: &2152749860 !ruby/object:Gem::Requirement
27
+ requirement: &2160430180 !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: *2152749860
35
+ version_requirements: *2160430180
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: curb
38
- requirement: &2152749440 !ruby/object:Gem::Requirement
38
+ requirement: &2160429480 !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: *2152749440
46
+ version_requirements: *2160429480
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: json
49
- requirement: &2152748880 !ruby/object:Gem::Requirement
49
+ requirement: &2160429020 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *2152748880
57
+ version_requirements: *2160429020
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: nokogiri
60
- requirement: &2152748460 !ruby/object:Gem::Requirement
60
+ requirement: &2160428580 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,21 @@ dependencies:
65
65
  version: '0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *2152748460
68
+ version_requirements: *2160428580
69
+ - !ruby/object:Gem::Dependency
70
+ name: oauth
71
+ requirement: &2160428140 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: *2160428140
69
80
  - !ruby/object:Gem::Dependency
70
81
  name: rake
71
- requirement: &2152748040 !ruby/object:Gem::Requirement
82
+ requirement: &2160427720 !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: *2152748040
90
+ version_requirements: *2160427720
80
91
  - !ruby/object:Gem::Dependency
81
92
  name: rspec
82
- requirement: &2152747620 !ruby/object:Gem::Requirement
93
+ requirement: &2160427240 !ruby/object:Gem::Requirement
83
94
  none: false
84
95
  requirements:
85
96
  - - ! '>='
@@ -87,10 +98,10 @@ dependencies:
87
98
  version: '0'
88
99
  type: :development
89
100
  prerelease: false
90
- version_requirements: *2152747620
101
+ version_requirements: *2160427240
91
102
  - !ruby/object:Gem::Dependency
92
103
  name: rdoc
93
- requirement: &2152747180 !ruby/object:Gem::Requirement
104
+ requirement: &2160426820 !ruby/object:Gem::Requirement
94
105
  none: false
95
106
  requirements:
96
107
  - - ! '>='
@@ -98,7 +109,7 @@ dependencies:
98
109
  version: '0'
99
110
  type: :development
100
111
  prerelease: false
101
- version_requirements: *2152747180
112
+ version_requirements: *2160426820
102
113
  description: tweetlr crawls twitter for a given term, extracts photos out of the collected
103
114
  tweets' short urls and posts the images to tumblr.
104
115
  email: sven.kraeuter@gmail.com
@@ -128,6 +139,7 @@ files:
128
139
  - lib/tweetlr.rb
129
140
  - spec/combinators/twitter_tumblr_combinator_spec.rb
130
141
  - spec/processors/photo_services_processor_spec.rb
142
+ - spec/processors/tumblr_processor_spec.rb
131
143
  - spec/processors/twitter_processor_spec.rb
132
144
  - spec/spec_helper.rb
133
145
  - spec/tweetlr_spec.rb
@@ -147,9 +159,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
147
159
  required_rubygems_version: !ruby/object:Gem::Requirement
148
160
  none: false
149
161
  requirements:
150
- - - ! '>'
162
+ - - ! '>='
151
163
  - !ruby/object:Gem::Version
152
- version: 1.3.1
164
+ version: '0'
153
165
  requirements: []
154
166
  rubyforge_project: tweetlr
155
167
  rubygems_version: 1.8.16
@@ -160,6 +172,7 @@ summary: tweetlr crawls twitter for a given term, extracts photos out of the col
160
172
  test_files:
161
173
  - spec/combinators/twitter_tumblr_combinator_spec.rb
162
174
  - spec/processors/photo_services_processor_spec.rb
175
+ - spec/processors/tumblr_processor_spec.rb
163
176
  - spec/processors/twitter_processor_spec.rb
164
177
  - spec/spec_helper.rb
165
178
  - spec/tweetlr_spec.rb