ahoward-growltdf 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
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
+