rowl 1.0.0
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.
- data/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +22 -0
- data/README.md +60 -0
- data/Rakefile +57 -0
- data/VERSION +1 -0
- data/lib/rowl.rb +176 -0
- data/test/rowl_test.rb +24 -0
- data/test/test_helper.rb +10 -0
- metadata +74 -0
data/.document
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2009 Jason Madigan
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
Rowl
|
2
|
+
====
|
3
|
+
Rowl is a simple [Growl] notification sender for Ruby.
|
4
|
+
|
5
|
+
Installation
|
6
|
+
============
|
7
|
+
|
8
|
+
As a RubyGem
|
9
|
+
|
10
|
+
sudo gem install rowl
|
11
|
+
|
12
|
+
Since Rowl is tiny (and has no dependencies), you may just want to drop it into an existing project
|
13
|
+
|
14
|
+
git clone git://github.com/jasonmadigan/rowl
|
15
|
+
mv rowl/lib/rowl.rb <location>
|
16
|
+
|
17
|
+
Then require it
|
18
|
+
|
19
|
+
require 'rowl'
|
20
|
+
|
21
|
+
Usage
|
22
|
+
=====
|
23
|
+
|
24
|
+
Before using Rowl, it's probably worth noting some things:
|
25
|
+
|
26
|
+
* Applications need to register themselves with Growl before they can send notifications
|
27
|
+
* Applications can have a number of different types of notifications associated with them
|
28
|
+
* Registration requires you to include any types of notifications you'll wish to use later on
|
29
|
+
* These notification types are user configurable - they can be enabled/disabled, styled etc. how a user wants
|
30
|
+
* You only need to send a register your application once, but you'll want to store the application name you registered, along with any notification types, for future reference
|
31
|
+
|
32
|
+
So, sending a notification is a little more involved than it might first seem. This reason why the API here is a little less terse than I'd like. Anyway.
|
33
|
+
|
34
|
+
Load it (as a gem)
|
35
|
+
|
36
|
+
require 'rubygems'
|
37
|
+
require 'rowl'
|
38
|
+
|
39
|
+
Use it like so
|
40
|
+
|
41
|
+
registration = Rowl::Registration.new("My Application", [{:name => "My Notification", :enabled => true}, {:name => "My Other Notification Type", :enabled => false}])
|
42
|
+
Rowl::Notification.new( :application => registration.application,
|
43
|
+
:notification => registration.notifications.first,
|
44
|
+
:host => "localhost",
|
45
|
+
:password => registration.password,
|
46
|
+
:title => "Title",
|
47
|
+
:description => "Description" )
|
48
|
+
|
49
|
+
Patches, Bugs & Hatemail
|
50
|
+
========================
|
51
|
+
|
52
|
+
* Feel free to fork the project and send me a pull request with any changes if you come any bugs or general nastiness
|
53
|
+
* All that I ask is that you don't touch the rakefile, version, or history (I'll update these and push out gem updates)
|
54
|
+
* Tests would be nice, but I'm not going to reject a perfectly good fix if they're missing
|
55
|
+
|
56
|
+
Copyright & Licensing
|
57
|
+
=====================
|
58
|
+
Copyright (c) 2009 Jason Madigan. MIT license, see LICENSE for details.
|
59
|
+
|
60
|
+
[Growl]: http://growl.info
|
data/Rakefile
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "rowl"
|
8
|
+
gem.summary = %Q{Rowl is a simple Growl notification sender for Ruby.}
|
9
|
+
gem.description = %Q{Rowl is a simple Growl notification sender for Ruby.}
|
10
|
+
gem.email = "jason@jasonmadigan.com"
|
11
|
+
gem.homepage = "http://github.com/jasonmadigan/rowl"
|
12
|
+
gem.authors = ["Jason Madigan"]
|
13
|
+
gem.add_development_dependency "thoughtbot-shoulda"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
Rake::TestTask.new(:test) do |test|
|
23
|
+
test.libs << 'lib' << 'test'
|
24
|
+
test.pattern = 'test/**/*_test.rb'
|
25
|
+
test.verbose = true
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
require 'rcov/rcovtask'
|
30
|
+
Rcov::RcovTask.new do |test|
|
31
|
+
test.libs << 'test'
|
32
|
+
test.pattern = 'test/**/*_test.rb'
|
33
|
+
test.verbose = true
|
34
|
+
end
|
35
|
+
rescue LoadError
|
36
|
+
task :rcov do
|
37
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
task :test => :check_dependencies
|
42
|
+
|
43
|
+
task :default => :test
|
44
|
+
|
45
|
+
require 'rake/rdoctask'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
if File.exist?('VERSION')
|
48
|
+
version = File.read('VERSION')
|
49
|
+
else
|
50
|
+
version = ""
|
51
|
+
end
|
52
|
+
|
53
|
+
rdoc.rdoc_dir = 'rdoc'
|
54
|
+
rdoc.title = "rowl #{version}"
|
55
|
+
rdoc.rdoc_files.include('README*')
|
56
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
57
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
data/lib/rowl.rb
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
# Protocol Description: http://growl.info/documentation/developer/protocol.php
|
2
|
+
|
3
|
+
require 'digest/md5'
|
4
|
+
require 'socket'
|
5
|
+
require 'rubygems'
|
6
|
+
require 'ruby-debug'
|
7
|
+
|
8
|
+
module Rowl
|
9
|
+
|
10
|
+
GROWL_UDP_PORT = 9887
|
11
|
+
GROWL_PROTOCOL_VERSION = 1
|
12
|
+
GROWL_TYPE_REGISTRATION = 0
|
13
|
+
GROWL_TYPE_NOTIFICATION = 1
|
14
|
+
REGISTRATION_FORMAT = "CCnCCa*" # Growl Network Registration Packet Format
|
15
|
+
NOTIFICATION_FORMAT = "CCnnnnna*" # Growl Network Notification Packet Format
|
16
|
+
|
17
|
+
class Registration
|
18
|
+
|
19
|
+
attr_accessor :application, :notifications, :host, :password
|
20
|
+
|
21
|
+
def initialize(application, notifications, host="localhost", password=nil)
|
22
|
+
@defaults = []
|
23
|
+
@application = application
|
24
|
+
@notifications = []
|
25
|
+
@password = password
|
26
|
+
@host = host
|
27
|
+
|
28
|
+
# Register notifications
|
29
|
+
notifications.each do |notification|
|
30
|
+
add_notification_type(notification[:name], notification[:enabled])
|
31
|
+
end
|
32
|
+
|
33
|
+
send_registration
|
34
|
+
end
|
35
|
+
|
36
|
+
def app_name
|
37
|
+
chars = ("a".."z").to_a + ("1".."9").to_a
|
38
|
+
Array.new(8, '').collect{chars[rand(chars.size)]}.join
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_notification_type(notification, enabled)
|
42
|
+
if enabled.nil?
|
43
|
+
enabled = true
|
44
|
+
end
|
45
|
+
@notifications << notification
|
46
|
+
if enabled
|
47
|
+
@defaults << @notifications.length - 1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def send_registration
|
52
|
+
socket = UDPSocket.open
|
53
|
+
socket.send(payload, 0, @host, 9887)
|
54
|
+
end
|
55
|
+
|
56
|
+
def payload
|
57
|
+
length = 0
|
58
|
+
data = []
|
59
|
+
data_format = ""
|
60
|
+
|
61
|
+
packet = [
|
62
|
+
GROWL_PROTOCOL_VERSION,
|
63
|
+
GROWL_TYPE_REGISTRATION
|
64
|
+
]
|
65
|
+
|
66
|
+
packet << @application.length
|
67
|
+
packet << @notifications.length
|
68
|
+
packet << @defaults.length
|
69
|
+
|
70
|
+
data << @application
|
71
|
+
data_format = "a#{@application.length}"
|
72
|
+
|
73
|
+
@notifications.each do |notify|
|
74
|
+
data << notify.length
|
75
|
+
data << notify
|
76
|
+
data_format << "na#{notify.length}"
|
77
|
+
end
|
78
|
+
|
79
|
+
@defaults.each do |notify|
|
80
|
+
data << notify
|
81
|
+
data_format << "C"
|
82
|
+
end
|
83
|
+
|
84
|
+
data = data.pack(data_format)
|
85
|
+
|
86
|
+
packet << data
|
87
|
+
packet = packet.pack(REGISTRATION_FORMAT)
|
88
|
+
|
89
|
+
if @password
|
90
|
+
checksum = Digest::MD5.digest(packet+@password)
|
91
|
+
else
|
92
|
+
checksum = Digest::MD5.digest(packet)
|
93
|
+
end
|
94
|
+
|
95
|
+
packet << checksum
|
96
|
+
|
97
|
+
return packet
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class Notification
|
102
|
+
def initialize(opts={})
|
103
|
+
opts = {
|
104
|
+
:priority => 0,
|
105
|
+
:sticky => false,
|
106
|
+
:host => "localhost"
|
107
|
+
}.merge(opts)
|
108
|
+
|
109
|
+
@application = opts[:application]
|
110
|
+
@password = opts[:password]
|
111
|
+
@host = opts[:host]
|
112
|
+
@notification = opts[:notification]
|
113
|
+
@title = opts[:title]
|
114
|
+
@description = opts[:description]
|
115
|
+
@priority = opts[:priority]
|
116
|
+
@sticky = opts[:sticky]
|
117
|
+
|
118
|
+
send_notification
|
119
|
+
end
|
120
|
+
|
121
|
+
def send_notification
|
122
|
+
socket = UDPSocket.open
|
123
|
+
socket.send(payload, 0, @host, 9887)
|
124
|
+
end
|
125
|
+
|
126
|
+
def payload
|
127
|
+
flags = 0
|
128
|
+
data = []
|
129
|
+
|
130
|
+
packet = [
|
131
|
+
GROWL_PROTOCOL_VERSION,
|
132
|
+
GROWL_TYPE_NOTIFICATION,
|
133
|
+
]
|
134
|
+
|
135
|
+
flags = 0
|
136
|
+
flags |= ((0x7 & @priority) << 1) # 3 bits for priority
|
137
|
+
flags |= 1 if @sticky # 1 bit for sticky
|
138
|
+
|
139
|
+
packet << flags
|
140
|
+
packet << @notification.length
|
141
|
+
packet << @title.length
|
142
|
+
packet << @description.length
|
143
|
+
packet << @application.length
|
144
|
+
|
145
|
+
data << @notification
|
146
|
+
data << @title
|
147
|
+
data << @description
|
148
|
+
data << @application
|
149
|
+
|
150
|
+
packet << data.join
|
151
|
+
packet = packet.pack(NOTIFICATION_FORMAT)
|
152
|
+
|
153
|
+
if @password
|
154
|
+
checksum = Digest::MD5.digest(packet+@password)
|
155
|
+
else
|
156
|
+
checksum = Digest::MD5.digest(packet)
|
157
|
+
end
|
158
|
+
|
159
|
+
packet << checksum
|
160
|
+
@datagram = packet
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
if __FILE__ == $0
|
168
|
+
registration = Rowl::Registration.new("My Application", [{:name => "My Notification", :enabled => true}, {:name => "My Other Notification Type", :enabled => false}])
|
169
|
+
Rowl::Notification.new( :application => registration.application,
|
170
|
+
:notification => registration.notifications.first,
|
171
|
+
:host => "localhost",
|
172
|
+
:password => registration.password,
|
173
|
+
:title => "Title",
|
174
|
+
:description => "Description" )
|
175
|
+
end
|
176
|
+
|
data/test/rowl_test.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class RowlTest < Test::Unit::TestCase
|
4
|
+
context "A Rowl instance" do
|
5
|
+
|
6
|
+
setup do
|
7
|
+
@registration = Rowl::Registration.new("My Application", [{:name => "My Notification", :enabled => true}, {:name => "My Other Notification Type", :enabled => false}])
|
8
|
+
end
|
9
|
+
|
10
|
+
should "have registered" do
|
11
|
+
assert_not_nil @registration
|
12
|
+
end
|
13
|
+
|
14
|
+
should "be able to send a notifcation as a registered application" do
|
15
|
+
assert_not_nil Rowl::Notification.new( :application => @registration.application,
|
16
|
+
:notification => @registration.notifications.first,
|
17
|
+
:host => "localhost",
|
18
|
+
:password => @registration.password,
|
19
|
+
:title => "Title",
|
20
|
+
:description => "Description" )
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rowl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jason Madigan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-15 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: thoughtbot-shoulda
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description: Rowl is a simple Growl notification sender for Ruby.
|
26
|
+
email: jason@jasonmadigan.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- LICENSE
|
33
|
+
- README.md
|
34
|
+
files:
|
35
|
+
- .document
|
36
|
+
- .gitignore
|
37
|
+
- LICENSE
|
38
|
+
- README.md
|
39
|
+
- Rakefile
|
40
|
+
- VERSION
|
41
|
+
- lib/rowl.rb
|
42
|
+
- test/rowl_test.rb
|
43
|
+
- test/test_helper.rb
|
44
|
+
has_rdoc: true
|
45
|
+
homepage: http://github.com/jasonmadigan/rowl
|
46
|
+
licenses: []
|
47
|
+
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options:
|
50
|
+
- --charset=UTF-8
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
version:
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: "0"
|
64
|
+
version:
|
65
|
+
requirements: []
|
66
|
+
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 1.3.5
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: Rowl is a simple Growl notification sender for Ruby.
|
72
|
+
test_files:
|
73
|
+
- test/rowl_test.rb
|
74
|
+
- test/test_helper.rb
|