twuckoo 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ lines.txt
2
+ used_lines*.txt
3
+ todos.txt
4
+ pkg/
5
+ vendor/gems/ruby/**/gems
6
+ vendor/gems/ruby/**/specifications
7
+ vendor/gems/ruby/**/doc
8
+ vendor/gems/ruby/**/environment.rb
9
+ mail_proba.rb
data/CHANGELOG ADDED
@@ -0,0 +1,6 @@
1
+ v0.2.2 Minor modification because of changed Wikipedia TFA markup
2
+ v0.2 Wikipedia TFA module, command line argument decides which file to include
3
+ v0.1.3 Length of sleeping interval settable from config
4
+ v0.1.2 Sleeping interval set with duration-string
5
+ v0.1.1 Removing unnecessary gem requires and config files
6
+ v0.1 Initial release: can tweet from a file.
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ clear_sources
2
+ source "http://gemcutter.org"
3
+
4
+ gem "mail"
5
+ gem "twibot"
6
+ gem "hpricot"
7
+ gem "jeweler", ">= 1.3.0"
data/Manifest ADDED
@@ -0,0 +1,18 @@
1
+ bin/twuckoo
2
+ CHANGELOG
3
+ lib/duration_string.rb
4
+ lib/environments.rb
5
+ lib/modules/one_line_from_file.rb
6
+ lib/modules/wikipedia_tfa.rb
7
+ lib/twuckoo.rb
8
+ Manifest
9
+ Rakefile
10
+ README.markdown
11
+ spec/duration_string_spec.rb
12
+ spec/one_line_from_file_spec.rb
13
+ spec/spec.opts
14
+ spec/spec_helper.rb
15
+ spec/twuckoo_spec.rb
16
+ spec/wikipedia_tfa_spec.rb
17
+ tasks/spec.rake
18
+ twuckoo.gemspec
data/README.markdown ADDED
@@ -0,0 +1,102 @@
1
+ # Twuckoo
2
+
3
+ Need to tweet periodically and in an automated fashion? Then Twuckoo is for you. Still not convinced? :) Read on.
4
+
5
+ ## Abstract
6
+
7
+ Twuckoo fulfills the task of periodically fetching a message and tweeting it (Twuckoo = Twitter + Cuckoo). Since we all prefer code to words, I'll show you its main loop:
8
+
9
+ def run
10
+ setup
11
+ load_tweets
12
+ loop do
13
+ tweeted = tweet
14
+ quit if tweeted.nil?
15
+ relax
16
+ end
17
+ end
18
+
19
+ It is very simple in its design but opens vast possibilities due to its modular approach.
20
+
21
+ ## A simple API
22
+
23
+ Twuckoo takes a modular approach. It defines a very simple API and expects modules to implement these API methods. The methods are:
24
+
25
+ * load_tweets
26
+
27
+ Loads the possible tweets that twuckoo will use when selecting the next one. This could be reading all lines from a file, for example.
28
+
29
+ * next
30
+
31
+ Fetches the next message to be tweeted. Usually the bulk of the "business logic" is implemented here. This could be scraping a web page and extracting a specific snippet of html.
32
+
33
+ * store(tweet)
34
+
35
+ Hands the last tweeted message to be stored. In the case of the one\_line\_from_file module, this stores the tweet in a file so that no message is used multiple times.
36
+
37
+ Twuckoo needs to be passed the name of the module to be used. At the moment there are two provided modules:
38
+
39
+ * one\_line\_from\_file
40
+
41
+ Loads all the lines from a file (lines.txt) and tweets one line randomly each time.
42
+
43
+ * wikipedia_tfa
44
+
45
+ Scraps Wikipedia's main page and extracts the name and link of Today's Featured Article. This is not as general a module as one\_line\_from_file. I am thinking about how to best make a "web" module out of this.
46
+
47
+ ## Installation
48
+
49
+ gem install balinterdi-twuckoo --source http://gems.github.com
50
+
51
+ Twuckoo depends on twibot which will also get installed with the above command.
52
+
53
+ In order for twibot to be able to connect to your twitter account, a config/bot.yml file need to be present at where you launch twuckoo from. It has to contain the following lines at least:
54
+
55
+ login: my_login
56
+ password: my_password
57
+
58
+ For more options, see [twibot's README](http://github.com/cjohansen/twibot/tree/master "twibot's README")
59
+
60
+ ## Configuration
61
+
62
+ Currently the only thing you can set is the time to wait between tweets. By default, it is "1d", so the script will "relax" for 24 hours after tweeting. If you wish to change this value, just place the following in a config/cuckoo.yml:
63
+
64
+ time_to_sleep: 1h
65
+
66
+ The value should be given in a human-comprehensible form. You can use any combination of weeks, days, hours, minutes and seconds, so 1w3d13h27m19s will work, too, although you probably do not want to be this precise :)
67
+
68
+ ## Running
69
+
70
+ You have to indicate the module you wish to use:
71
+
72
+ $ twuckoo file
73
+
74
+ Will make use of the one_line_from_file module. There has to be a lines.txt file in the directory where you run twuckoo from that contains the possible tweets, one tweet per line. The tweeted lines will be stored in a file called used\_lines.txt so you should have write permission to the directory.
75
+
76
+ or
77
+
78
+ $ twuckoo wikipedia_tfa
79
+
80
+ (see above)
81
+
82
+ ## Examples out there
83
+
84
+ In the course of the development of this gem I "ate my own dogfood" so you'll find one twitter account for each of the modules:
85
+
86
+ * [Daily Oblique](http://twitter.com/daily_oblique)
87
+
88
+ Serves you an [Oblique Strategy](http://www.rtqe.net/ObliqueStrategies/) per day.
89
+
90
+ * [Wikipedia Today's Featured Article](http://twitter.com/wikipedia_tfa)
91
+
92
+ An interesting article from the English Wikipedia delivered right to your twitter feed.
93
+
94
+ If you set up something with twuckoo, I would like to know about it, so that I might include it here.
95
+
96
+ ## Credits & License
97
+
98
+ You can go ahead and play with the software as well as modify it, release it under another name, charge for someone that uses your service, etc. A link back to [this page](http://github.com/balinterdi/twuckoo/tree/master) would be appreciated if you release something based on it.
99
+
100
+ Any feedback (especially bug reports!) is highly appreciated, so please do not hesitate to contact me at <balint@bucionrails.com>
101
+
102
+ Original idea and development: [Balint Erdi](http://bucionrails.com)
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'rake'
2
+
3
+ begin
4
+ require 'jeweler'
5
+ Jeweler::Tasks.new do |gemspec|
6
+ gemspec.name = "twuckoo"
7
+ gemspec.summary = "Need to tweet periodically in an automated fashion? Then Twuckoo is for you!"
8
+ gemspec.description = <<-EOF
9
+ A simple yet elegant solution to tweet a message regularly from a file (from a webpage, a database, etc.)
10
+ EOF
11
+ gemspec.email = "balint.erdi@gmail.com"
12
+ gemspec.homepage = "http://github.com/balinterdi/twuckoo"
13
+ gemspec.authors = ["Balint Erdi"]
14
+ end
15
+ Jeweler::GemcutterTasks.new
16
+ rescue LoadError
17
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
18
+ end
19
+
20
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
21
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.0
data/bin/edit_json.rb ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/local/bin/ruby
2
+ require File.expand_path(File.join(File.dirname(__FILE__), "../vendor/gems/ruby/1.8/environment"))
3
+ load File.expand_path(File.join(File.dirname(__FILE__), "../vendor/gems/ruby/1.8/gems/json_pure-1.2.0/bin/edit_json.rb"))
data/bin/jeweler ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/local/bin/ruby
2
+ require File.expand_path(File.join(File.dirname(__FILE__), "../vendor/gems/ruby/1.8/environment"))
3
+ load File.expand_path(File.join(File.dirname(__FILE__), "../vendor/gems/ruby/1.8/gems/jeweler-1.4.0/bin/jeweler"))
@@ -0,0 +1,3 @@
1
+ #!/usr/local/bin/ruby
2
+ require File.expand_path(File.join(File.dirname(__FILE__), "../vendor/gems/ruby/1.8/environment"))
3
+ load File.expand_path(File.join(File.dirname(__FILE__), "../vendor/gems/ruby/1.8/gems/json_pure-1.2.0/bin/prettify_json.rb"))
data/bin/rubyforge ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/local/bin/ruby
2
+ require File.expand_path(File.join(File.dirname(__FILE__), "../vendor/gems/ruby/1.8/environment"))
3
+ load File.expand_path(File.join(File.dirname(__FILE__), "../vendor/gems/ruby/1.8/gems/rubyforge-2.0.3/bin/rubyforge"))
data/bin/t4rsh ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/local/bin/ruby
2
+ require File.expand_path(File.join(File.dirname(__FILE__), "../vendor/gems/ruby/1.8/environment"))
3
+ load File.expand_path(File.join(File.dirname(__FILE__), "../vendor/gems/ruby/1.8/gems/mbbx6spp-twitter4r-0.4.0/bin/t4rsh"))
data/bin/twuckoo ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ dir = File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ require File.join(dir, 'twuckoo')
6
+
7
+ Dir.glob(File.join(dir, 'modules', '*.rb')).each do |mod|
8
+ require mod
9
+ end
10
+
11
+ module_to_include = case ARGV.first.downcase
12
+ when "from_file"
13
+ OneLineFromFile
14
+ when "file"
15
+ OneLineFromFile
16
+ when "wikipedia_tfa"
17
+ WikipediaTFA
18
+ else
19
+ raise "No module to include was provided."
20
+ end
21
+
22
+ Twuckoo::Runner.send(:include, module_to_include)
23
+ @runner = Twuckoo::Runner.new
24
+ # @cuckoo.set_testing
25
+ @runner.run
@@ -0,0 +1,12 @@
1
+ module DurationString
2
+ class << self
3
+ MULTIPLIERS = { "s" => 1, "m" => 60, "h" => 60 * 60, "d" => 60 * 60 * 24, "w" => 60 * 60 * 24 * 7 }
4
+ def to_seconds(duration)
5
+ duration.scan(/(\d+)([smhdw])/).inject(0) do |seconds, match|
6
+ num, dur_chr = match
7
+ multiplier = MULTIPLIERS[dur_chr]
8
+ seconds + num.to_i * multiplier
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ module TwuckooEnvironment
2
+ def set_testing
3
+ ENV["CUCKOO_ENV"] = "testing"
4
+ end
5
+ def testing?
6
+ ENV["CUCKOO_ENV"] == "testing"
7
+ end
8
+ end
@@ -0,0 +1,70 @@
1
+ module OneLineFromFile
2
+ # read all lines from the file that contains the strategies
3
+ # select the strategies that are not used yet
4
+ # pick a random strategy
5
+
6
+ # store used strategies in a file with (store the md5 sum of the strategies' text)
7
+ attr_reader :lines
8
+
9
+ LINES_FILE = 'lines.txt'
10
+ USED_LINES_FILE = 'used_lines.txt'
11
+
12
+ def initialize
13
+ @lines = []
14
+ # load_lines
15
+ end
16
+
17
+ def load_tweets
18
+ load_lines
19
+ end
20
+
21
+ def get_lines_from_file
22
+ begin
23
+ IO::readlines(LINES_FILE).map { |line| line.chomp }
24
+ rescue Errno::ENOENT
25
+ []
26
+ end
27
+ end
28
+
29
+ def get_all_lines
30
+ @fresh_lines ||= get_lines_from_file
31
+ end
32
+
33
+ def get_used_lines_from_file
34
+ begin
35
+ IO::readlines(USED_LINES_FILE).map { |line| line.chomp }
36
+ rescue Errno::ENOENT
37
+ []
38
+ end
39
+ end
40
+
41
+ def get_used_lines
42
+ @used_lines ||= get_used_lines_from_file
43
+ end
44
+
45
+ def load_lines
46
+ used = get_used_lines
47
+ unused_lines = get_all_lines.select { |line| !used.include?(line) }
48
+ add_lines(*unused_lines)
49
+ end
50
+
51
+ def add_lines(*new_lines)
52
+ @lines.concat(new_lines)
53
+ end
54
+
55
+ def pick
56
+ rand(lines.length)
57
+ end
58
+
59
+ def store(line)
60
+ open(USED_LINES_FILE, "a") do |file|
61
+ file.write(line + "\n")
62
+ end
63
+ end
64
+
65
+ def next
66
+ @lines.delete_at(pick)
67
+ end
68
+
69
+ end
70
+
@@ -0,0 +1,37 @@
1
+ require "open-uri"
2
+ require "hpricot"
3
+
4
+ # Grabs the headline of Wikipedia's Today's Featured Article (TFA)
5
+ module WikipediaTFA
6
+
7
+ WIKIPEDIA_HOST = "http://en.wikipedia.org"
8
+
9
+ def load_tweets
10
+ end
11
+
12
+ def store(line)
13
+ end
14
+
15
+ def fetch_main_page
16
+ Hpricot(open("#{WIKIPEDIA_HOST}/wiki/Main_Page"))
17
+ end
18
+
19
+ def fetch_tfa
20
+ doc = fetch_main_page
21
+ tfa = doc.at("#mp-tfa b a")
22
+ tfa_link = WIKIPEDIA_HOST + tfa["href"]
23
+ "#{tfa.inner_html}: #{tfa_link}"
24
+ end
25
+
26
+ def next
27
+ prev_tweet = get_last_tweet
28
+ next_tweet = fetch_tfa
29
+ prev_tweet == next_tweet ? '' : next_tweet
30
+ end
31
+
32
+ private
33
+ def get_last_tweet
34
+ last_tweet = twitter.timeline_for(:me).first
35
+ last_tweet.text if last_tweet
36
+ end
37
+ end
data/lib/modules.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'modules/one_line_from_file'
2
+ require 'modules/wikipedia_tfa'
@@ -0,0 +1,5 @@
1
+ class Twuckoo::Config < Hash
2
+ def initialize
3
+ self[:time_to_sleep] = "1d"
4
+ end
5
+ end
@@ -0,0 +1,94 @@
1
+ class Twuckoo::Runner
2
+ # the idea is to include a module with a well-defined API with three methods:
3
+ # - load_tweets
4
+ # - next
5
+ # - store(tweet)
6
+
7
+ def run
8
+ setup_from_file
9
+ load_tweets
10
+ next_tweet = self.next
11
+ while next_tweet do
12
+ tweet(next_tweet)
13
+ wait if wait_between_tweets?
14
+ next_tweet = self.next
15
+ notify if next_tweet.nil?
16
+ end
17
+ end
18
+
19
+ def initialize
20
+ super
21
+ end
22
+
23
+ def wait_between_tweets?
24
+ config[:time_to_sleep] != "0"
25
+ end
26
+
27
+ def wait
28
+ seconds_to_sleep = DurationString.to_seconds(config[:time_to_sleep])
29
+ sleep(seconds_to_sleep)
30
+ end
31
+
32
+ def notify
33
+ send_email(config)
34
+ end
35
+
36
+ def config
37
+ @config ||= ::Twuckoo::Config.new
38
+ end
39
+
40
+ def tweet(message)
41
+ unless message.nil? or message.empty?
42
+ store(message)
43
+ send_tweet(message)
44
+ end
45
+ message
46
+ end
47
+
48
+ def get_config_values_from_file(file='config/cuckoo.yml')
49
+ begin
50
+ open(file, 'r') do |f|
51
+ YAML.load(f.read)
52
+ end
53
+ rescue
54
+ {}
55
+ end
56
+ end
57
+
58
+ def setup
59
+ yield config
60
+ end
61
+
62
+ def setup_from_file
63
+ setup do |config|
64
+ get_config_values_from_file.each_pair do |attr, value|
65
+ config[attr] = value
66
+ end
67
+ end
68
+ end
69
+
70
+ private
71
+ def send_tweet(message)
72
+ twitter.status(:post, message)
73
+ end
74
+
75
+ def send_email(config)
76
+ Net::SMTP.enable_tls(OpenSSL::SSL::VERIFY_NONE)
77
+ Mail.defaults do
78
+ smtp do
79
+ host "smtp.gmail.com"
80
+ port 25
81
+ user config[:user]
82
+ pass config[:password]
83
+ disable_tls
84
+ end
85
+ end
86
+
87
+ Mail.deliver do
88
+ from 'twuckoo@nowhere.com'
89
+ to config[:email]
90
+ subject "[twuckoo]: nothing more to tweet"
91
+ body "So please fill me up!"
92
+ end
93
+ end
94
+ end
data/lib/twuckoo.rb ADDED
@@ -0,0 +1,16 @@
1
+ $:.unshift File.expand_path(File.dirname(__FILE__))
2
+
3
+ require 'vendor/gems/environment'
4
+
5
+ module Twuckoo
6
+
7
+ end
8
+
9
+ require 'environments'
10
+ require 'duration_string'
11
+ require 'modules'
12
+
13
+ require 'twuckoo/config'
14
+ require 'twuckoo/runner'
15
+
16
+ Bundler.require_env
@@ -0,0 +1,28 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe DurationString do
4
+ it "gives back the number of seconds for seconds" do
5
+ DurationString.to_seconds("17s").should == 17
6
+ end
7
+
8
+ it "gives back the number of seconds for dur. strings with only minutes defined" do
9
+ DurationString.to_seconds("7m").should == 7 * 60
10
+ end
11
+
12
+ it "gives back the number of seconds for hours for dur. strings with only hours defined" do
13
+ DurationString.to_seconds("4h").should == 60 * 60 * 4
14
+ end
15
+
16
+ it "gives back the number of seconds for hours for dur. strings with only days defined" do
17
+ DurationString.to_seconds("2d").should == 60 * 60 * 24 * 2
18
+ end
19
+
20
+ it "gives back the number of seconds for hours for dur. strings with only weeks defined" do
21
+ DurationString.to_seconds("3w").should == 60 * 60 * 24 * 7 * 3
22
+ end
23
+
24
+ it "gives back the number of seconds for a dur. string that combines several dur. characters" do
25
+ DurationString.to_seconds("1d3h18m22s").should == (60 * 60 * 24 * 1) + (60 * 60 * 3) + (60 * 18) + 22
26
+ end
27
+
28
+ end
@@ -0,0 +1,89 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe "A cuckoo twitterer with one line from a file" do
4
+ before do
5
+ Twuckoo::Runner.send(:include, OneLineFromFile)
6
+ @twuckoo = Twuckoo::Runner.new
7
+ # just so that no files will be written
8
+ @twuckoo.stubs(:store).returns(nil)
9
+ # and the actual text tweets are not tweeted (twittered?)
10
+ @twuckoo.stubs(:send_tweet).returns(true)
11
+ end
12
+
13
+ it "stores a line that was sent to it correctly" do
14
+ @twuckoo.lines.should be_empty
15
+ @twuckoo.add_lines("I am happy", "I am sad")
16
+ @twuckoo.lines.should == ["I am happy", "I am sad"]
17
+ end
18
+
19
+ it "loads all the lines in the file when sent the load_tweets message" do
20
+ lines = ["I am happy", "I am sad", "I am thrilled", "I am bored"]
21
+ @twuckoo.expects(:get_lines_from_file).returns(lines)
22
+ @twuckoo.load_tweets
23
+ @twuckoo.lines.should == lines
24
+ end
25
+
26
+ describe "when it tweeted a line already" do
27
+ before do
28
+ @twuckoo.add_lines("I am happy", "I am sad", "I am thrilled", "I am bored")
29
+ @twuckoo.stubs(:pick).returns(0)
30
+ @twuckoo.tweet(@twuckoo.next)
31
+ end
32
+
33
+ it "it removes it" do
34
+ @twuckoo.lines.should == ["I am sad", "I am thrilled", "I am bored"]
35
+ end
36
+
37
+ it "stores it" do
38
+ @twuckoo.stubs(:pick).returns(0)
39
+ @twuckoo.expects(:store).with("I am sad")
40
+ @twuckoo.tweet(@twuckoo.next)
41
+ end
42
+
43
+ it "it picks an unused line to tweet next" do
44
+ next_pick = @twuckoo.next
45
+ ["I am sad", "I am thrilled", "I am bored"].should include(next_pick)
46
+ end
47
+ end
48
+
49
+ it "tweets all the available lines in as many 'rounds' as there are lines" do
50
+ lines = ["I am happy", "I am sad", "I am thrilled", "I am bored"]
51
+ @twuckoo.add_lines(*lines)
52
+ lines.length.times { @twuckoo.tweet(@twuckoo.next) }
53
+ @twuckoo.lines.should be_empty
54
+ end
55
+
56
+ it "only reads the file to load lines from the first time around" do
57
+ @twuckoo.stubs(:get_used_lines_from_file).returns([])
58
+ @twuckoo.expects(:get_lines_from_file).returns(["I am happy", "I am sad", "I am thrilled", "I am bored"])
59
+ 2.times { @twuckoo.load_lines }
60
+ end
61
+
62
+ it "only reads the file to load used lines from the first time around" do
63
+ @twuckoo.stubs(:get_lines_from_file).returns(["I am happy", "I am sad", "I am thrilled", "I am bored"])
64
+ @twuckoo.expects(:get_used_lines_from_file).returns([])
65
+ 2.times { @twuckoo.load_lines }
66
+ end
67
+
68
+ describe "when loading lines to use" do
69
+ before do
70
+ @twuckoo.stubs(:get_lines_from_file).returns(["I am happy", "I am sad", "I am thrilled", "I am bored"])
71
+ @twuckoo.stubs(:get_used_lines_from_file).returns([])
72
+ end
73
+
74
+ it "loads the available ones" do
75
+ @twuckoo.load_lines
76
+ @twuckoo.lines.should == ["I am happy", "I am sad", "I am thrilled", "I am bored"]
77
+ end
78
+
79
+ describe "when having used ones from a previous run" do
80
+ before do
81
+ @twuckoo.stubs(:get_used_lines_from_file).returns(["I am happy", "I am sad"])
82
+ @twuckoo.load_lines
83
+ end
84
+ it "should not pick those used lines" do
85
+ @twuckoo.lines.should == ["I am thrilled", "I am bored"]
86
+ end
87
+ end
88
+ end
89
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,5 @@
1
+ --colour
2
+ --loadby random
3
+ -- format specdoc
4
+ --format progress
5
+ --backtrace
@@ -0,0 +1,8 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'twuckoo')
2
+
3
+ require "spec"
4
+ require "mocha"
5
+
6
+ Spec::Runner.configure do |config|
7
+ config.mock_with :mocha
8
+ end
@@ -0,0 +1,4 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe Twuckoo::Config do
4
+ end
@@ -0,0 +1,72 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe Twuckoo::Runner do
4
+ before do
5
+ @twuckoo = Twuckoo::Runner.new
6
+ # actual text tweets should not be tweeted (twittered?)
7
+ @twuckoo.stubs(:send_tweet).returns(true)
8
+ end
9
+
10
+ it "waits 1 day between tweets by default" do
11
+ @twuckoo.config[:time_to_sleep].should == "1d"
12
+ end
13
+
14
+ it "should not wait between tweets if 0 is given for the time_to_sleep option" do
15
+ @twuckoo.setup do |config|
16
+ config[:time_to_sleep] = "0"
17
+ end
18
+ #TODO: write a custom matcher so this could be written as:
19
+ # @twuckoo.should_not wait_between_tweets
20
+ @twuckoo.wait_between_tweets?.should == false
21
+ end
22
+
23
+ it "should wait between tweets if a non-zero value is given for the time_to_sleep option" do
24
+ @twuckoo.setup do |config|
25
+ config[:time_to_sleep] = "1h"
26
+ end
27
+ #TODO: write a custom matcher so this could be written as:
28
+ # @twuckoo.should_not wait_between_tweets
29
+ @twuckoo.wait_between_tweets?.should == true
30
+ end
31
+
32
+ it "can assign vars through the setup method" do
33
+ @twuckoo.setup do |config|
34
+ config[:time_to_sleep] = "3m"
35
+ end
36
+ @twuckoo.config[:time_to_sleep].should == "3m"
37
+ end
38
+
39
+ describe "loading values from the config file" do
40
+ it "sets the time interval to wait b/w tweets correctly" do
41
+ @twuckoo.expects(:get_config_values_from_file).returns({ :time_to_sleep => "3m" })
42
+ @twuckoo.setup_from_file
43
+ @twuckoo.config[:time_to_sleep].should == "3m"
44
+ end
45
+ end
46
+
47
+ describe "when there is nothing to tweet" do
48
+ before do
49
+ @twuckoo.stubs(:next).returns(nil)
50
+ @twuckoo.stubs(:load_tweets).returns(nil)
51
+ end
52
+ it "does not call store" do
53
+ @twuckoo.expects(:store).never
54
+ @twuckoo.run
55
+ end
56
+ end
57
+
58
+ describe "when there is nothing more to tweet after a while" do
59
+ before do
60
+ @twuckoo.setup do |config|
61
+ config[:time_to_sleep] = "0"
62
+ end
63
+ @twuckoo.stubs(:next).returns("tweet me this").then.returns(nil)
64
+ end
65
+ it "should send out a notification" do
66
+ @twuckoo.stubs(:send_email).returns(true)
67
+ @twuckoo.expects(:notify).once
68
+ @twuckoo.run
69
+ end
70
+ end
71
+
72
+ end
@@ -0,0 +1,24 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe "A cuckoo twitterer for wikipedia featured article" do
4
+ before do
5
+ Twuckoo::Runner.send(:include, WikipediaTFA)
6
+ @twuckoo = Twuckoo::Runner.new
7
+ @twuckoo.setup do |config|
8
+ config[:time_to_sleep] = "0"
9
+ end
10
+ # should not actually send out any tweets
11
+ @twuckoo.stubs(:send_tweet).returns(true)
12
+ @twuckoo.stubs(:send_email).returns(true)
13
+ end
14
+
15
+ it "should not tweet the same thing twice subsequently" do
16
+ @twuckoo.stubs(:get_last_tweet).returns("Twitter: http://en.wikipedia.org/wiki/Twitter")
17
+ @twuckoo.stubs(:fetch_tfa).returns("Twitter: http://en.wikipedia.org/wiki/Twitter")
18
+ @twuckoo.stubs(:next).returns(@twuckoo.get_last_tweet).then.
19
+ returns(@twuckoo.fetch_tfa).then.
20
+ returns(nil)
21
+ @twuckoo.expects(:send_tweet).once
22
+ @twuckoo.run
23
+ end
24
+ end
data/tasks/spec.rake ADDED
@@ -0,0 +1,10 @@
1
+ require "rake"
2
+ require "spec/rake/spectask"
3
+
4
+ ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
5
+
6
+ desc "Run all specs"
7
+ Spec::Rake::SpecTask.new(:spec) do |t|
8
+ t.spec_opts << '--options' << ROOT + '/spec/spec.opts'
9
+ t.spec_files = Dir.glob('spec/**/*_spec.rb').map { |f| f.to_s }
10
+ end
data/twuckoo.gemspec ADDED
@@ -0,0 +1,82 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{twuckoo}
8
+ s.version = "0.3.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Balint Erdi"]
12
+ s.date = %q{2010-01-12}
13
+ s.description = %q{ A simple yet elegant solution to tweet a message regularly from a file (from a webpage, a database, etc.)
14
+ }
15
+ s.email = %q{balint.erdi@gmail.com}
16
+ s.executables = ["edit_json.rb", "jeweler", "prettify_json.rb", "rubyforge", "t4rsh", "twuckoo"]
17
+ s.extra_rdoc_files = [
18
+ "README.markdown"
19
+ ]
20
+ s.files = [
21
+ ".gitignore",
22
+ "CHANGELOG",
23
+ "Gemfile",
24
+ "Manifest",
25
+ "README.markdown",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "bin/edit_json.rb",
29
+ "bin/prettify_json.rb",
30
+ "bin/t4rsh",
31
+ "bin/twuckoo",
32
+ "lib/duration_string.rb",
33
+ "lib/environments.rb",
34
+ "lib/modules.rb",
35
+ "lib/modules/one_line_from_file.rb",
36
+ "lib/modules/wikipedia_tfa.rb",
37
+ "lib/twuckoo.rb",
38
+ "lib/twuckoo/config.rb",
39
+ "lib/twuckoo/runner.rb",
40
+ "spec/duration_string_spec.rb",
41
+ "spec/one_line_from_file_spec.rb",
42
+ "spec/spec.opts",
43
+ "spec/spec_helper.rb",
44
+ "spec/twuckoo/config_spec.rb",
45
+ "spec/twuckoo/runner_spec.rb",
46
+ "spec/wikipedia_tfa_spec.rb",
47
+ "tasks/spec.rake",
48
+ "twuckoo.gemspec",
49
+ "vendor/gems/environment.rb",
50
+ "vendor/gems/ruby/1.8/cache/activesupport-2.3.5.gem",
51
+ "vendor/gems/ruby/1.8/cache/hpricot-0.8.2.gem",
52
+ "vendor/gems/ruby/1.8/cache/json-1.2.0.gem",
53
+ "vendor/gems/ruby/1.8/cache/mail-1.5.2.gem",
54
+ "vendor/gems/ruby/1.8/cache/mbbx6spp-twitter4r-0.4.0.gem",
55
+ "vendor/gems/ruby/1.8/cache/mime-types-1.16.gem",
56
+ "vendor/gems/ruby/1.8/cache/twibot-0.1.7.gem"
57
+ ]
58
+ s.homepage = %q{http://github.com/balinterdi/twuckoo}
59
+ s.rdoc_options = ["--charset=UTF-8"]
60
+ s.require_paths = ["lib"]
61
+ s.rubygems_version = %q{1.3.5}
62
+ s.summary = %q{Need to tweet periodically in an automated fashion? Then Twuckoo is for you!}
63
+ s.test_files = [
64
+ "spec/duration_string_spec.rb",
65
+ "spec/one_line_from_file_spec.rb",
66
+ "spec/spec_helper.rb",
67
+ "spec/twuckoo/config_spec.rb",
68
+ "spec/twuckoo/runner_spec.rb",
69
+ "spec/wikipedia_tfa_spec.rb"
70
+ ]
71
+
72
+ if s.respond_to? :specification_version then
73
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
74
+ s.specification_version = 3
75
+
76
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
77
+ else
78
+ end
79
+ else
80
+ end
81
+ end
82
+
@@ -0,0 +1,4 @@
1
+ require 'rbconfig'
2
+ engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
3
+ version = Config::CONFIG['ruby_version']
4
+ require File.expand_path("../#{engine}/#{version}/environment", __FILE__)
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: twuckoo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Balint Erdi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-12 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: " A simple yet elegant solution to tweet a message regularly from a file (from a webpage, a database, etc.)\n"
17
+ email: balint.erdi@gmail.com
18
+ executables:
19
+ - edit_json.rb
20
+ - jeweler
21
+ - prettify_json.rb
22
+ - rubyforge
23
+ - t4rsh
24
+ - twuckoo
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - README.markdown
29
+ files:
30
+ - .gitignore
31
+ - CHANGELOG
32
+ - Gemfile
33
+ - Manifest
34
+ - README.markdown
35
+ - Rakefile
36
+ - VERSION
37
+ - bin/edit_json.rb
38
+ - bin/prettify_json.rb
39
+ - bin/t4rsh
40
+ - bin/twuckoo
41
+ - lib/duration_string.rb
42
+ - lib/environments.rb
43
+ - lib/modules.rb
44
+ - lib/modules/one_line_from_file.rb
45
+ - lib/modules/wikipedia_tfa.rb
46
+ - lib/twuckoo.rb
47
+ - lib/twuckoo/config.rb
48
+ - lib/twuckoo/runner.rb
49
+ - spec/duration_string_spec.rb
50
+ - spec/one_line_from_file_spec.rb
51
+ - spec/spec.opts
52
+ - spec/spec_helper.rb
53
+ - spec/twuckoo/config_spec.rb
54
+ - spec/twuckoo/runner_spec.rb
55
+ - spec/wikipedia_tfa_spec.rb
56
+ - tasks/spec.rake
57
+ - twuckoo.gemspec
58
+ - vendor/gems/environment.rb
59
+ - vendor/gems/ruby/1.8/cache/activesupport-2.3.5.gem
60
+ - vendor/gems/ruby/1.8/cache/hpricot-0.8.2.gem
61
+ - vendor/gems/ruby/1.8/cache/json-1.2.0.gem
62
+ - vendor/gems/ruby/1.8/cache/mail-1.5.2.gem
63
+ - vendor/gems/ruby/1.8/cache/mbbx6spp-twitter4r-0.4.0.gem
64
+ - vendor/gems/ruby/1.8/cache/mime-types-1.16.gem
65
+ - vendor/gems/ruby/1.8/cache/twibot-0.1.7.gem
66
+ has_rdoc: true
67
+ homepage: http://github.com/balinterdi/twuckoo
68
+ licenses: []
69
+
70
+ post_install_message:
71
+ rdoc_options:
72
+ - --charset=UTF-8
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ version:
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: "0"
86
+ version:
87
+ requirements: []
88
+
89
+ rubyforge_project:
90
+ rubygems_version: 1.3.5
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: Need to tweet periodically in an automated fashion? Then Twuckoo is for you!
94
+ test_files:
95
+ - spec/duration_string_spec.rb
96
+ - spec/one_line_from_file_spec.rb
97
+ - spec/spec_helper.rb
98
+ - spec/twuckoo/config_spec.rb
99
+ - spec/twuckoo/runner_spec.rb
100
+ - spec/wikipedia_tfa_spec.rb