twuckoo 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -0
- data/CHANGELOG +6 -0
- data/Gemfile +7 -0
- data/Manifest +18 -0
- data/README.markdown +102 -0
- data/Rakefile +21 -0
- data/VERSION +1 -0
- data/bin/edit_json.rb +3 -0
- data/bin/jeweler +3 -0
- data/bin/prettify_json.rb +3 -0
- data/bin/rubyforge +3 -0
- data/bin/t4rsh +3 -0
- data/bin/twuckoo +25 -0
- data/lib/duration_string.rb +12 -0
- data/lib/environments.rb +8 -0
- data/lib/modules/one_line_from_file.rb +70 -0
- data/lib/modules/wikipedia_tfa.rb +37 -0
- data/lib/modules.rb +2 -0
- data/lib/twuckoo/config.rb +5 -0
- data/lib/twuckoo/runner.rb +94 -0
- data/lib/twuckoo.rb +16 -0
- data/spec/duration_string_spec.rb +28 -0
- data/spec/one_line_from_file_spec.rb +89 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/twuckoo/config_spec.rb +4 -0
- data/spec/twuckoo/runner_spec.rb +72 -0
- data/spec/wikipedia_tfa_spec.rb +24 -0
- data/tasks/spec.rake +10 -0
- data/twuckoo.gemspec +82 -0
- data/vendor/gems/environment.rb +4 -0
- data/vendor/gems/ruby/1.8/cache/activesupport-2.3.5.gem +0 -0
- data/vendor/gems/ruby/1.8/cache/hpricot-0.8.2.gem +0 -0
- data/vendor/gems/ruby/1.8/cache/json-1.2.0.gem +0 -0
- data/vendor/gems/ruby/1.8/cache/mail-1.5.2.gem +0 -0
- data/vendor/gems/ruby/1.8/cache/mbbx6spp-twitter4r-0.4.0.gem +0 -0
- data/vendor/gems/ruby/1.8/cache/mime-types-1.16.gem +0 -0
- data/vendor/gems/ruby/1.8/cache/twibot-0.1.7.gem +0 -0
- metadata +100 -0
data/.gitignore
ADDED
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
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
data/bin/jeweler
ADDED
data/bin/rubyforge
ADDED
data/bin/t4rsh
ADDED
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
|
data/lib/environments.rb
ADDED
@@ -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,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
data/spec/spec_helper.rb
ADDED
@@ -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
|
+
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary 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
|