growltdf 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. data/Rakefile +229 -0
  2. data/bin/growltdf +188 -0
  3. data/growltdf.gemspec +27 -0
  4. metadata +85 -0
data/Rakefile ADDED
@@ -0,0 +1,229 @@
1
+
2
+ This.rubyforge_project = 'codeforpeople'
3
+ This.author = "Ara T. Howard"
4
+ This.email = "ara.t.howard@gmail.com"
5
+ This.homepage = "http://github.com/ahoward/#{ This.lib }/tree/master"
6
+
7
+
8
+ task :default do
9
+ puts(Rake::Task.tasks.map{|task| task.name} - ['default'])
10
+ end
11
+
12
+
13
+ task :gemspec do
14
+ ignore_extensions = 'git', 'svn', 'tmp', /sw./, 'bak', 'gem'
15
+ ignore_directories = 'pkg'
16
+ ignore_files = 'test/log'
17
+
18
+ shiteless =
19
+ lambda do |list|
20
+ list.delete_if do |entry|
21
+ next unless test(?e, entry)
22
+ extension = File.basename(entry).split(%r/[.]/).last
23
+ ignore_extensions.any?{|ext| ext === extension}
24
+ end
25
+ list.delete_if do |entry|
26
+ next unless test(?d, entry)
27
+ dirname = File.expand_path(entry)
28
+ ignore_directories.any?{|dir| File.expand_path(dir) == dirname}
29
+ end
30
+ list.delete_if do |entry|
31
+ next unless test(?f, entry)
32
+ filename = File.expand_path(entry)
33
+ ignore_files.any?{|file| File.expand_path(file) == filename}
34
+ end
35
+ end
36
+
37
+ lib = This.lib
38
+ version = This.version
39
+ files = shiteless[Dir::glob("**/**")]
40
+ executables = shiteless[Dir::glob("bin/*")].map{|exe| File.basename(exe)}
41
+ has_rdoc = true #File.exist?('doc')
42
+ test_files = "test/#{ lib }.rb" if File.file?("test/#{ lib }.rb")
43
+
44
+ extensions = This.extensions
45
+ if extensions.nil?
46
+ %w( Makefile configure extconf.rb ).each do |ext|
47
+ extensions << ext if File.exists?(ext)
48
+ end
49
+ end
50
+ extensions = [extensions].flatten.compact
51
+
52
+ template =
53
+ if test(?e, 'gemspec.erb')
54
+ Template{ IO.read('gemspec.erb') }
55
+ else
56
+ Template {
57
+ <<-__
58
+ ## #{ lib }.gemspec
59
+ #
60
+
61
+ Gem::Specification::new do |spec|
62
+ spec.name = #{ lib.inspect }
63
+ spec.version = #{ version.inspect }
64
+ spec.platform = Gem::Platform::RUBY
65
+ spec.summary = #{ lib.inspect }
66
+
67
+ spec.files = #{ files.inspect }
68
+ spec.executables = #{ executables.inspect }
69
+
70
+ spec.require_path = "lib"
71
+
72
+ spec.has_rdoc = #{ has_rdoc.inspect }
73
+ spec.test_files = #{ test_files.inspect }
74
+ spec.add_dependency 'main'
75
+ spec.add_dependency 'ruby-growl'
76
+ spec.add_dependency 'nokogiri'
77
+
78
+ spec.extensions.push(*#{ extensions.inspect })
79
+
80
+ spec.rubyforge_project = #{ This.rubyforge_project.inspect }
81
+ spec.author = #{ This.author.inspect }
82
+ spec.email = #{ This.email.inspect }
83
+ spec.homepage = #{ This.homepage.inspect }
84
+ end
85
+ __
86
+ }
87
+ end
88
+
89
+ open("#{ lib }.gemspec", "w"){|fd| fd.puts template}
90
+ This.gemspec = "#{ lib }.gemspec"
91
+ end
92
+
93
+ task :gem => [:clean, :gemspec] do
94
+ Fu.mkdir_p This.pkgdir
95
+ before = Dir['*.gem']
96
+ cmd = "gem build #{ This.gemspec }"
97
+ `#{ cmd }`
98
+ after = Dir['*.gem']
99
+ gem = ((after - before).first || after.first) or abort('no gem!')
100
+ Fu.mv gem, This.pkgdir
101
+ This.gem = File.basename(gem)
102
+ end
103
+
104
+ task :readme do
105
+ samples = ''
106
+ prompt = '~ > '
107
+ lib = This.lib
108
+ version = This.version
109
+
110
+ Dir['sample*/*'].sort.each do |sample|
111
+ samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
112
+
113
+ cmd = "cat #{ sample }"
114
+ samples << Util.indent(prompt + cmd, 2) << "\n\n"
115
+ samples << Util.indent(`#{ cmd }`, 4) << "\n"
116
+
117
+ cmd = "ruby #{ sample }"
118
+ samples << Util.indent(prompt + cmd, 2) << "\n\n"
119
+
120
+ cmd = "ruby -e'STDOUT.sync=true; exec %(ruby -Ilib #{ sample })'"
121
+ samples << Util.indent(`#{ cmd } 2>&1`, 4) << "\n"
122
+ end
123
+
124
+ template =
125
+ if test(?e, 'readme.erb')
126
+ Template{ IO.read('readme.erb') }
127
+ else
128
+ Template {
129
+ <<-__
130
+ NAME
131
+ #{ lib }
132
+
133
+ DESCRIPTION
134
+
135
+ INSTALL
136
+ gem install #{ lib }
137
+
138
+ SAMPLES
139
+ #{ samples }
140
+ __
141
+ }
142
+ end
143
+
144
+ open("README", "w"){|fd| fd.puts template}
145
+ end
146
+
147
+
148
+ task :clean do
149
+ Dir[File.join(This.pkgdir, '**/**')].each{|entry| Fu.rm_rf(entry)}
150
+ end
151
+
152
+
153
+ task :release => [:clean, :gemspec, :gem] do
154
+ gems = Dir[File.join(This.pkgdir, '*.gem')].flatten
155
+ raise "which one? : #{ gems.inspect }" if gems.size > 1
156
+ raise "no gems?" if gems.size < 1
157
+ cmd = "rubyforge login && rubyforge add_release #{ This.rubyforge_project } #{ This.lib } #{ This.version } #{ This.pkgdir }/#{ This.gem }"
158
+ puts cmd
159
+ system cmd
160
+ end
161
+
162
+
163
+
164
+
165
+
166
+ BEGIN {
167
+ $VERBOSE = nil
168
+
169
+ require 'ostruct'
170
+ require 'erb'
171
+ require 'fileutils'
172
+
173
+ Fu = FileUtils
174
+
175
+ This = OpenStruct.new
176
+
177
+ This.file = File.expand_path(__FILE__)
178
+ This.dir = File.dirname(This.file)
179
+ This.pkgdir = File.join(This.dir, 'pkg')
180
+
181
+ lib = ENV['LIB'] || 'growltdf'
182
+ unless lib
183
+ lib = File.basename(Dir.pwd)
184
+ end
185
+ This.lib = lib
186
+
187
+ version = ENV['VERSION'] || '0.4.2'
188
+ unless version
189
+ name = lib.capitalize
190
+ require "./lib/#{ lib }"
191
+ version = eval(name).send(:version)
192
+ end
193
+ This.version = version
194
+
195
+ abort('no lib') unless This.lib
196
+ abort('no version') unless This.version
197
+
198
+ module Util
199
+ def indent(s, n = 2)
200
+ s = unindent(s)
201
+ ws = ' ' * n
202
+ s.gsub(%r/^/, ws)
203
+ end
204
+
205
+ def unindent(s)
206
+ indent = nil
207
+ s.each do |line|
208
+ next if line =~ %r/^\s*$/
209
+ indent = line[%r/^\s*/] and break
210
+ end
211
+ indent ? s.gsub(%r/^#{ indent }/, "") : s
212
+ end
213
+ extend self
214
+ end
215
+
216
+ class Template
217
+ def initialize(&block)
218
+ @block = block
219
+ @template = block.call.to_s
220
+ end
221
+ def expand(b=nil)
222
+ ERB.new(Util.unindent(@template)).result(b||@block)
223
+ end
224
+ alias_method 'to_s', 'expand'
225
+ end
226
+ def Template(*args, &block) Template.new(*args, &block) end
227
+
228
+ Dir.chdir(This.dir)
229
+ }
data/bin/growltdf ADDED
@@ -0,0 +1,188 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ #
4
+ # growltdf is the greatest program evar. it let's you scrape
5
+ # http://cyclingnews.com for TDF updates and dump them into growl to you can
6
+ # keep up with the race while working.
7
+ #
8
+ # . to install this code
9
+ #
10
+ # - sudo gem install growltdf
11
+ #
12
+ # . to run you need to enable your growl prefpane to look like this
13
+ #
14
+ # http://s3.amazonaws.com/drawohara.com.screenshots/growltdf-prefpane.png
15
+ #
16
+ # if you set a password you'll need to supply to the program when run.
17
+ #
18
+ # . to run
19
+ #
20
+ # without password
21
+ #
22
+ # growltdf
23
+ #
24
+ # with password
25
+ #
26
+ # growltdf --growl-password=password
27
+ #
28
+
29
+ Main {
30
+ option('stage'){
31
+ argument :required
32
+ default :latest
33
+ }
34
+
35
+ option('growl-password'){
36
+ argument :required
37
+ }
38
+
39
+ def run
40
+ setup_growl
41
+
42
+ loop do
43
+ determine_the_current_stage
44
+ get_the_latest_live_entries
45
+ get_the_previous_live_entries
46
+ compare_them
47
+ growl_updated_live_entries
48
+ store_updated_live_entires
49
+ wait_a_little_while
50
+ end
51
+ end
52
+
53
+ def setup_growl
54
+ @growl =
55
+ Growl.new(
56
+ 'localhost', 'growltdf', %w[ race stage ],
57
+ default_notifies=nil, params['growl-password'].value
58
+ )
59
+ end
60
+
61
+ def determine_the_current_stage
62
+ @stage ||= nil
63
+ stage = param['stage']
64
+ if stage.given? and stage.value != :latest
65
+ @stage = Integer(stage.value)
66
+ else
67
+ today = Time.now.utc
68
+ if today.month == 7
69
+ stage = today.day - 3
70
+ if (1..21).include?(stage)
71
+ if @stage != stage
72
+ @growl.notify 'stage', "Stage #{ stage }"
73
+ end
74
+ @stage = stage
75
+ end
76
+ end
77
+ end
78
+ abort 'no stage' unless @stage
79
+ end
80
+
81
+ def get_the_latest_live_entries
82
+ stage_url = stage_url_for(@stage)
83
+ dom = dom_for(stage_url)
84
+ live_entries = dom.search('#live_entries')
85
+ @latest_live_entries =
86
+ live_entries.search('li').map do |li|
87
+ title = li.search('h3').inner_text.strip
88
+ content = li.search('p').inner_text.strip
89
+ [title, content]
90
+ end.reverse
91
+ end
92
+
93
+ def get_the_previous_live_entries
94
+ Db.transaction do
95
+ Db[@stage] ||= []
96
+ @previous_live_entries = Db[@stage]
97
+ end
98
+ end
99
+
100
+ def compare_them
101
+ @updated_entries = @latest_live_entries - @previous_live_entries
102
+ end
103
+
104
+ def growl_updated_live_entries
105
+ if @previous_live_entries.empty?
106
+ unless @latest_live_entries.empty?
107
+ @growl.notify 'stage', "TDF", "Stage #{ @stage } has started."
108
+ end
109
+ if @latest_live_entries.size > 10
110
+ @growl.notify 'race', "TDF", "#{ @latest_live_entries.size - 10 } updates..."
111
+ end
112
+ end
113
+ @updated_entries.last(10).each do |update|
114
+ title, content, *ignored = Array(update)
115
+ @growl.notify 'race', title.to_s, content.to_s
116
+ end
117
+ end
118
+
119
+ def store_updated_live_entires
120
+ Db.transaction do
121
+ Db[@stage] = @latest_live_entries
122
+ end
123
+ end
124
+
125
+ def wait_a_little_while
126
+ sleep 3
127
+ end
128
+
129
+ def stage_url_for(stage)
130
+ "http://www.cyclingnews.com/races/96th-tour-de-france-gt/stages/stage-#{ stage }/live-report"
131
+ end
132
+
133
+ def get(url)
134
+ open(url){|socket| socket.read}
135
+ rescue Exception
136
+ nil
137
+ end
138
+
139
+ def dom_for(url)
140
+ html = get(url)
141
+ return nil unless html
142
+ Nokogiri::HTML(html)
143
+ rescue Exception
144
+ nil
145
+ end
146
+
147
+ def head(url)
148
+ uri = URI.parse(url.to_s)
149
+ Net::HTTP.start(uri.host, uri.port){|http| http.head(uri.path)}
150
+ rescue
151
+ return false
152
+ end
153
+ }
154
+
155
+ BEGIN {
156
+ require 'pathname'
157
+ Pn = Pathname
158
+
159
+ require 'fileutils'
160
+ Fu = FileUtils
161
+
162
+ require 'uri'
163
+ require 'net/http'
164
+ require 'open-uri'
165
+
166
+ require 'yaml'
167
+ require 'yaml/store'
168
+
169
+ require 'rubygems'
170
+ begin
171
+ require 'main'
172
+ rescue LoadError
173
+ abort "sudo gem intall main"
174
+ end
175
+ begin
176
+ require 'ruby-growl'
177
+ rescue LoadError
178
+ abort "sudo gem intall ruby-growl"
179
+ end
180
+ begin
181
+ require 'nokogiri'
182
+ rescue LoadError
183
+ abort "sudo gem intall nokogiri"
184
+ end
185
+
186
+ Home = Pn.new('~').expand_path.realpath
187
+ Db = YAML::Store.new(Home.join('.growltdf.yml').to_s)
188
+ }
data/growltdf.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ ## growltdf.gemspec
2
+ #
3
+
4
+ Gem::Specification::new do |spec|
5
+ spec.name = "growltdf"
6
+ spec.version = "0.4.2"
7
+ spec.platform = Gem::Platform::RUBY
8
+ spec.summary = "growltdf"
9
+
10
+ spec.files = ["bin", "bin/growltdf", "growltdf.gemspec", "Rakefile"]
11
+ spec.executables = ["growltdf"]
12
+
13
+ spec.require_path = "lib"
14
+
15
+ spec.has_rdoc = true
16
+ spec.test_files = nil
17
+ spec.add_dependency 'main'
18
+ spec.add_dependency 'ruby-growl'
19
+ spec.add_dependency 'nokogiri'
20
+
21
+ spec.extensions.push(*[])
22
+
23
+ spec.rubyforge_project = "codeforpeople"
24
+ spec.author = "Ara T. Howard"
25
+ spec.email = "ara.t.howard@gmail.com"
26
+ spec.homepage = "http://github.com/ahoward/growltdf/tree/master"
27
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: growltdf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.2
5
+ platform: ruby
6
+ authors:
7
+ - Ara T. Howard
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-06 00:00:00 -06:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: main
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: ruby-growl
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: nokogiri
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ description:
46
+ email: ara.t.howard@gmail.com
47
+ executables:
48
+ - growltdf
49
+ extensions: []
50
+
51
+ extra_rdoc_files: []
52
+
53
+ files:
54
+ - bin
55
+ - bin/growltdf
56
+ - growltdf.gemspec
57
+ - Rakefile
58
+ has_rdoc: true
59
+ homepage: http://github.com/ahoward/growltdf/tree/master
60
+ post_install_message:
61
+ rdoc_options: []
62
+
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ requirements: []
78
+
79
+ rubyforge_project: codeforpeople
80
+ rubygems_version: 1.3.1
81
+ signing_key:
82
+ specification_version: 2
83
+ summary: growltdf
84
+ test_files: []
85
+