ahoward-growltdf 0.4.4

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 (5) hide show
  1. data/README +37 -0
  2. data/Rakefile +227 -0
  3. data/bin/growltdf +207 -0
  4. data/growltdf.gemspec +27 -0
  5. metadata +86 -0
data/README ADDED
@@ -0,0 +1,37 @@
1
+ NAME
2
+ growltdf v0.4.4
3
+
4
+ SYNOPSIS
5
+ growltdf [options]+
6
+
7
+ DESCRIPTION
8
+ growltdf is the greatest program evar. it let's you scrape
9
+ http://cyclingnews.com for TDF updates and dump them into growl to you can
10
+ keep up with the race while working.
11
+
12
+ . to install this code
13
+
14
+ - sudo gem install growltdf
15
+
16
+ . to run you need to enable your growl prefpane to look like this
17
+
18
+ http://s3.amazonaws.com/drawohara.com.screenshots/growltdf-prefpane.png
19
+
20
+ if you set a password you'll need to supply to the program when run.
21
+
22
+ . to run
23
+
24
+ without password
25
+
26
+ growltdf
27
+
28
+ with password
29
+
30
+ growltdf --growl-password=password
31
+
32
+ PARAMETERS
33
+ --stage=stage (0 ~> stage=latest)
34
+ --growl-password=growl-password (0 ~> growl-password)
35
+ --version
36
+ --help, -h
37
+
data/Rakefile ADDED
@@ -0,0 +1,227 @@
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']
188
+ unless version
189
+ version = `./bin/growltdf --version`.strip
190
+ end
191
+ This.version = version
192
+
193
+ abort('no lib') unless This.lib
194
+ abort('no version') unless This.version
195
+
196
+ module Util
197
+ def indent(s, n = 2)
198
+ s = unindent(s)
199
+ ws = ' ' * n
200
+ s.gsub(%r/^/, ws)
201
+ end
202
+
203
+ def unindent(s)
204
+ indent = nil
205
+ s.each do |line|
206
+ next if line =~ %r/^\s*$/
207
+ indent = line[%r/^\s*/] and break
208
+ end
209
+ indent ? s.gsub(%r/^#{ indent }/, "") : s
210
+ end
211
+ extend self
212
+ end
213
+
214
+ class Template
215
+ def initialize(&block)
216
+ @block = block
217
+ @template = block.call.to_s
218
+ end
219
+ def expand(b=nil)
220
+ ERB.new(Util.unindent(@template)).result(b||@block)
221
+ end
222
+ alias_method 'to_s', 'expand'
223
+ end
224
+ def Template(*args, &block) Template.new(*args, &block) end
225
+
226
+ Dir.chdir(This.dir)
227
+ }
data/bin/growltdf ADDED
@@ -0,0 +1,207 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ Main {
4
+ description <<-__
5
+ growltdf is the greatest program evar. it let's you scrape
6
+ http://cyclingnews.com for TDF updates and dump them into growl to you can
7
+ keep up with the race while working.
8
+
9
+ . to install this code
10
+
11
+ - sudo gem install growltdf
12
+
13
+ . to run you need to enable your growl prefpane to look like this
14
+
15
+ http://s3.amazonaws.com/drawohara.com.screenshots/growltdf-prefpane.png
16
+
17
+ if you set a password you'll need to supply to the program when run.
18
+
19
+ . to run
20
+
21
+ without password
22
+
23
+ growltdf
24
+
25
+ with password
26
+
27
+ growltdf --growl-password=password
28
+ __
29
+
30
+ version '0.4.4'
31
+
32
+ option('stage'){
33
+ argument :required
34
+ default :latest
35
+ }
36
+
37
+ option('growl-password'){
38
+ argument :required
39
+ }
40
+
41
+ option('version'){
42
+ }
43
+
44
+ def run
45
+ setup_growl
46
+
47
+ loop do
48
+ determine_the_current_stage
49
+ get_the_latest_live_entries
50
+ get_the_previous_live_entries
51
+ compare_them
52
+ growl_updated_live_entries
53
+ store_updated_live_entires
54
+ wait_a_little_while
55
+ end
56
+ end
57
+
58
+ def setup_growl
59
+ @growl =
60
+ Growl.new(
61
+ 'localhost', 'growltdf', %w[ initialize race stage ],
62
+ default_notifies=nil, params['growl-password'].value
63
+ )
64
+
65
+ @growl.notify 'initialize', 'growltdf', 'starting...'
66
+
67
+ puts <<-__
68
+ you should see a growl notification now.
69
+ if you do not you need to configure growl as per
70
+
71
+ http://s3.amazonaws.com/drawohara.com.screenshots/growltdf-prefpane.png
72
+ __
73
+ end
74
+
75
+ def determine_the_current_stage
76
+ @stage ||= nil
77
+ stage = param['stage']
78
+ if stage.given? and stage.value != :latest
79
+ @stage = Integer(stage.value)
80
+ else
81
+ today = Time.now.utc
82
+ if today.month == 7
83
+ stage = today.day - 3
84
+ if (1..21).include?(stage)
85
+ @stage = stage
86
+ end
87
+ end
88
+ end
89
+ abort 'no stage' unless @stage
90
+ end
91
+
92
+ def get_the_latest_live_entries
93
+ stage_url = stage_url_for(@stage)
94
+ puts "checking #{ stage_url } for updates..."
95
+ dom = dom_for(stage_url)
96
+ live_entries = dom.search('#live_entries')
97
+ @latest_live_entries =
98
+ live_entries.search('li').map do |li|
99
+ title = li.search('h3').inner_text.strip
100
+ content = li.search('p').inner_text.strip
101
+ [title, content]
102
+ end.reverse
103
+ end
104
+
105
+ def get_the_previous_live_entries
106
+ Db.transaction do
107
+ Db[@stage] ||= []
108
+ @previous_live_entries = Db[@stage]
109
+ end
110
+ end
111
+
112
+ def compare_them
113
+ @updated_entries = @latest_live_entries - @previous_live_entries
114
+ end
115
+
116
+ def growl_updated_live_entries
117
+ if @previous_live_entries.empty?
118
+ unless @latest_live_entries.empty?
119
+ @growl.notify 'stage', "TDF", "Stage #{ @stage } has started."
120
+ end
121
+ if @latest_live_entries.size > 10
122
+ @growl.notify 'race', "TDF", "#{ @latest_live_entries.size - 10 } updates..."
123
+ end
124
+ end
125
+ @updated_entries.last(10).each do |update|
126
+ title, content, *ignored = Array(update)
127
+ @growl.notify 'race', title.to_s, content.to_s
128
+ end
129
+ end
130
+
131
+ def store_updated_live_entires
132
+ Db.transaction do
133
+ Db[@stage] = @latest_live_entries
134
+ end
135
+ end
136
+
137
+ def wait_a_little_while
138
+ sleep 30
139
+ end
140
+
141
+ def stage_url_for(stage)
142
+ "http://www.cyclingnews.com/races/96th-tour-de-france-gt/stages/stage-#{ stage }/live-report"
143
+ end
144
+
145
+ def get(url)
146
+ open(url){|socket| socket.read}
147
+ rescue Exception
148
+ nil
149
+ end
150
+
151
+ def dom_for(url)
152
+ html = get(url)
153
+ return nil unless html
154
+ Nokogiri::HTML(html)
155
+ rescue Exception
156
+ nil
157
+ end
158
+
159
+ def head(url)
160
+ uri = URI.parse(url.to_s)
161
+ Net::HTTP.start(uri.host, uri.port){|http| http.head(uri.path)}
162
+ rescue
163
+ return false
164
+ end
165
+
166
+ def before_run
167
+ if param['version'].given?
168
+ puts(version)
169
+ exit
170
+ end
171
+ end
172
+ }
173
+
174
+ BEGIN {
175
+ require 'pathname'
176
+ Pn = Pathname
177
+
178
+ require 'fileutils'
179
+ Fu = FileUtils
180
+
181
+ require 'uri'
182
+ require 'net/http'
183
+ require 'open-uri'
184
+
185
+ require 'yaml'
186
+ require 'yaml/store'
187
+
188
+ require 'rubygems'
189
+ begin
190
+ require 'main'
191
+ rescue LoadError
192
+ abort "sudo gem intall main"
193
+ end
194
+ begin
195
+ require 'ruby-growl'
196
+ rescue LoadError
197
+ abort "sudo gem intall ruby-growl"
198
+ end
199
+ begin
200
+ require 'nokogiri'
201
+ rescue LoadError
202
+ abort "sudo gem intall nokogiri"
203
+ end
204
+
205
+ Home = Pn.new('~').expand_path.realpath
206
+ Db = YAML::Store.new(Home.join('.growltdf.yml').to_s)
207
+ }
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.4"
7
+ spec.platform = Gem::Platform::RUBY
8
+ spec.summary = "growltdf"
9
+
10
+ spec.files = ["bin", "bin/growltdf", "growltdf.gemspec", "Rakefile", "README"]
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,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ahoward-growltdf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.4
5
+ platform: ruby
6
+ authors:
7
+ - Ara T. Howard
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-16 00:00:00 -07: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
+ - README
59
+ has_rdoc: true
60
+ homepage: http://github.com/ahoward/growltdf/tree/master
61
+ post_install_message:
62
+ rdoc_options: []
63
+
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ requirements: []
79
+
80
+ rubyforge_project: codeforpeople
81
+ rubygems_version: 1.2.0
82
+ signing_key:
83
+ specification_version: 2
84
+ summary: growltdf
85
+ test_files: []
86
+