watcher_in_the_water 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ === 0.1.0 / 2008-09-06
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
@@ -0,0 +1,13 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ Rakefile
5
+ bin/watcher_in_the_water
6
+ lib/watcher_in_the_water.rb
7
+ test/fixtures/dimrill_gate
8
+ test/fixtures/durins_bridge
9
+ test/fixtures/west_gate
10
+ test/live.yml
11
+ test/live_test.rb
12
+ test/test_watcher_in_the_water.rb
13
+ test/watcher/test.yml
@@ -0,0 +1,34 @@
1
+ = Watcher In The Water - http://en.wikipedia.org/wiki/Watcher_in_the_Water
2
+
3
+ == Description
4
+
5
+ Want to know when the page at a given URL changes? The Watcher in the
6
+ Water will tell you over Jabber; just create a ~/.watcher/config.yml
7
+ file and toss +watcher_in_the_water+ into your crontab!
8
+
9
+ ---
10
+ jid: watcher-in-the-water@jabber.org
11
+ password: mellon
12
+ recipient: phil@hagelb.org
13
+ urls:
14
+ - http://rubyconf.org
15
+
16
+ == Issues
17
+
18
+ XMPP4R takes a really long time to authenticate with my Jabber
19
+ server. Maybe it's just me though... No idea. This shouldn't run more
20
+ than once an hour or so, whatever; shouldn't matter.
21
+
22
+ == Install
23
+
24
+ $ sudo gem install technomancy-watcher_in_the_water --source=http://gems.github.com
25
+
26
+ == TODO
27
+
28
+ * Finish live tests?
29
+ * Just send a diff over IM?
30
+ * Only look at a given XPath?
31
+
32
+ == Author
33
+
34
+ By Phil Hagelberg (http://technomancy.us)
@@ -0,0 +1,16 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/watcher_in_the_water.rb'
6
+
7
+ Hoe.new('watcher_in_the_water', WatcherInTheWater::VERSION) do |p|
8
+ p.rubyforge_name = "seattlerb"
9
+ p.summary = "Want to know when the page at a given URL changes?
10
+ The Watcher in the Water will tell you over Jabber."
11
+ p.developer('Phil Hagelberg', 'http://technomancy.us')
12
+ p.url = 'http://en.wikipedia.org/wiki/Watcher_in_the_Water'
13
+ p.extra_deps << 'xmpp4r'
14
+ end
15
+
16
+ # vim: syntax=Ruby
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.dirname(__FILE__) + '/../lib/watcher_in_the_water'
4
+
5
+ WatcherInTheWater.configure(ARGV.first)
6
+ WatcherInTheWater.watch
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'open-uri'
5
+ require 'yaml'
6
+ require 'digest/sha1'
7
+ require 'xmpp4r'
8
+ require 'fileutils'
9
+
10
+ module WatcherInTheWater
11
+ include Jabber
12
+ VERSION = '0.1'
13
+
14
+ module_function
15
+
16
+ def configure(config = nil)
17
+ config = File.expand_path(config || '~/.watcher/config.yml')
18
+ FileUtils.cd(File.dirname(config))
19
+ @config = YAML.load(File.read(config))
20
+ rescue
21
+ abort "You need #{config} to contain a sender jabber ID, password,
22
+ a recipient jabber ID, and a list of URLs in YAML format. Example:
23
+
24
+ ---
25
+ jid: watcher-in-the-water@jabber.org
26
+ password: mellon
27
+ recipient: phil@hagelb.org
28
+ urls: ---
29
+ http://rubyconf.org
30
+ "
31
+ end
32
+
33
+ def watch
34
+ @config['urls'].each do |url|
35
+ content = open(url).read
36
+ hash = Digest::SHA1.hexdigest(content)
37
+ filename = 'hashes/' + url_transform(url)
38
+
39
+ if File.exist?(filename)
40
+ if File.read(filename) != hash
41
+ alert("#{url} changed to #{content[0 .. 200]}")
42
+ end
43
+ else
44
+ alert("Watching #{url} for you!")
45
+ end
46
+ FileUtils.mkdir_p(File.dirname(filename))
47
+ File.open(filename, 'w') { |f| f.write hash }
48
+ end
49
+ end
50
+
51
+ def alert(message)
52
+ connect
53
+ @client.send Message.new(@config['recipient'],
54
+ message).set_type(:normal).set_id('1')
55
+ end
56
+
57
+ def connect
58
+ return if @client
59
+ jid = JID.new("#{@config['jid']}/#{`hostname`.chomp}-watcher")
60
+ @client = Client.new(jid)
61
+ @client.connect
62
+ @client.auth(@config['password'])
63
+ end
64
+
65
+ def url_transform(url)
66
+ url.gsub(/[^\w]/, '_')[0 .. 50] + '_' + Digest::SHA1.hexdigest(url)
67
+ end
68
+ end
@@ -0,0 +1 @@
1
+ Dimrill Gate
@@ -0,0 +1 @@
1
+ Durin's Bridge
@@ -0,0 +1 @@
1
+ West Gate
@@ -0,0 +1,6 @@
1
+ ---
2
+ jid: test@hagelb.org
3
+ password: mellon
4
+ recipient: testrecipient@hagelb.org
5
+ urls:
6
+ - http://localhost:8123/
@@ -0,0 +1,54 @@
1
+ require 'rubygems'
2
+ begin; gem 'miniunit'; rescue LoadError; end
3
+ require 'test/unit'
4
+ require 'mongrel'
5
+ require File.dirname(__FILE__) + '/../lib/watcher_in_the_water'
6
+
7
+ # launch Mongrel
8
+ class LiveServer < Mongrel::HttpHandler
9
+ attr_accessor :string
10
+ def process(request, response)
11
+ response.start(200) do |head,out|
12
+ out.write(@string || "hello!\n")
13
+ end
14
+ end
15
+ end
16
+
17
+ MONGREL = Mongrel::HttpServer.new("0.0.0.0", "3000")
18
+ MONGREL.register("/test", SimpleHandler.new)
19
+ MONGREL.run
20
+
21
+ class LiveTest < Test::Unit::TestCase
22
+ def setup
23
+ WatcherInTheWater.configure(File.dirname(__FILE__) + '/live.yml')
24
+ end
25
+
26
+ def test_live_usage
27
+ # should alert about all pages being watched on first run
28
+ # then should alert for a single change
29
+ # then should send no alerts if nothing's changed
30
+ end
31
+
32
+ def test_host_not_found
33
+ end
34
+
35
+ def test_404
36
+ end
37
+
38
+ def test_sender_jabber_down
39
+ end
40
+
41
+ def test_bad_auth
42
+ end
43
+
44
+ def test_recipient_jabber_down
45
+ end
46
+
47
+ def test_recipient_jid_not_found
48
+ end
49
+
50
+ private
51
+ def watch
52
+ system "#{File.dirname(__FILE__)}/../bin/watcher #{File.dirname(__FILE__)}/live.yml"
53
+ end
54
+ end
@@ -0,0 +1,60 @@
1
+ require 'rubygems'
2
+ begin; gem 'miniunit'; rescue LoadError; end
3
+ require 'test/unit'
4
+ require File.dirname(__FILE__) + '/../lib/watcher_in_the_water'
5
+
6
+ module WatcherInTheWater
7
+ # Let's mock out the Jabber connection
8
+ @client = Object.new
9
+ @messages = []
10
+ messages_for_closure = @messages
11
+
12
+ def @client.send(message)
13
+ WatcherInTheWater.messages << message
14
+ end
15
+
16
+ def self.messages; @messages; end
17
+ def self.config; @config; end
18
+ end
19
+
20
+ WatcherInTheWater.configure(File.dirname(__FILE__) + '/watcher/test.yml')
21
+
22
+ class TestWatcherInTheWater < Test::Unit::TestCase
23
+ def setup
24
+ FileUtils.rm_rf('hashes')
25
+ FileUtils.rm_rf('fixtures')
26
+ FileUtils.cp_r('../fixtures', 'fixtures')
27
+ WatcherInTheWater.messages.clear
28
+ end
29
+
30
+ def test_watch_first_time
31
+ WatcherInTheWater.watch
32
+
33
+ ['fixtures_dimrill_gate_d2785ed5a8c89b47e541e85b7216d0153a383651',
34
+ 'fixtures_durins_bridge_f81c948ae30baa391371150bc42cc935ebf8287c',
35
+ 'fixtures_west_gate_cdef5d9283f6bdeddfa89de21bbca8d5acb3c673'].each do |u|
36
+ assert_equal 40, File.read('hashes/' + u).length
37
+ end
38
+
39
+ assert_equal 3, WatcherInTheWater.messages.size
40
+ end
41
+
42
+ def test_watch_one_change
43
+ WatcherInTheWater.watch
44
+ WatcherInTheWater.messages.clear
45
+
46
+ File.open('fixtures/durins_bridge', 'w') { |f| f.puts "Durin's Super-Bridge!" }
47
+ WatcherInTheWater.watch
48
+
49
+ assert_equal 1, WatcherInTheWater.messages.size
50
+ end
51
+
52
+ def test_watch_no_changes
53
+ WatcherInTheWater.watch
54
+ WatcherInTheWater.messages.clear
55
+
56
+ WatcherInTheWater.watch
57
+
58
+ assert_equal [], WatcherInTheWater.messages
59
+ end
60
+ end
@@ -0,0 +1,8 @@
1
+ ---
2
+ jid: watcher-in-the-water@jabber.org
3
+ password: mellon
4
+ recipient: phil@hagelb.org
5
+ urls:
6
+ - fixtures/west_gate
7
+ - fixtures/durins_bridge
8
+ - fixtures/dimrill_gate
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: watcher_in_the_water
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Phil Hagelberg
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-11-07 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: xmpp4r
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: hoe
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.8.2
34
+ version:
35
+ description:
36
+ email:
37
+ - http://technomancy.us
38
+ executables:
39
+ - watcher_in_the_water
40
+ extensions: []
41
+
42
+ extra_rdoc_files:
43
+ - History.txt
44
+ - Manifest.txt
45
+ files:
46
+ - History.txt
47
+ - Manifest.txt
48
+ - README.rdoc
49
+ - Rakefile
50
+ - bin/watcher_in_the_water
51
+ - lib/watcher_in_the_water.rb
52
+ - test/fixtures/dimrill_gate
53
+ - test/fixtures/durins_bridge
54
+ - test/fixtures/west_gate
55
+ - test/live.yml
56
+ - test/live_test.rb
57
+ - test/test_watcher_in_the_water.rb
58
+ - test/watcher/test.yml
59
+ has_rdoc: true
60
+ homepage: http://en.wikipedia.org/wiki/Watcher_in_the_Water
61
+ post_install_message:
62
+ rdoc_options:
63
+ - --main
64
+ - README.txt
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ version:
79
+ requirements: []
80
+
81
+ rubyforge_project: seattlerb
82
+ rubygems_version: 1.3.1
83
+ signing_key:
84
+ specification_version: 2
85
+ summary: Want to know when the page at a given URL changes? The Watcher in the Water will tell you over Jabber.
86
+ test_files:
87
+ - test/test_watcher_in_the_water.rb