ruby-growl 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/LICENSE +27 -0
- data/Manifest.txt +6 -0
- data/Rakefile +67 -0
- data/bin/growl +97 -0
- data/lib/ruby-growl.rb +274 -0
- data/test/test_ruby-growl.rb +217 -0
- metadata +49 -0
data/LICENSE
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Copyright 2004 Eric Hodel. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
4
|
+
modification, are permitted provided that the following conditions
|
5
|
+
are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright
|
8
|
+
notice, this list of conditions and the following disclaimer.
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright
|
10
|
+
notice, this list of conditions and the following disclaimer in the
|
11
|
+
documentation and/or other materials provided with the distribution.
|
12
|
+
3. Neither the names of the authors nor the names of their contributors
|
13
|
+
may be used to endorse or promote products derived from this software
|
14
|
+
without specific prior written permission.
|
15
|
+
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
17
|
+
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
19
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
|
20
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
21
|
+
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
22
|
+
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
23
|
+
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
24
|
+
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
25
|
+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
26
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
|
data/Manifest.txt
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
|
7
|
+
require 'lib/ruby-growl'
|
8
|
+
|
9
|
+
$VERBOSE = nil
|
10
|
+
|
11
|
+
spec = Gem::Specification.new do |s|
|
12
|
+
s.name = "ruby-growl"
|
13
|
+
s.version = Growl::VERSION
|
14
|
+
s.summary = "Pure-Ruby Growl Notifier"
|
15
|
+
s.description = <<-EOF
|
16
|
+
ruby-growl allows you to perform Growl notification via UDP from machines
|
17
|
+
without growl installed (for example, non-OSX machines).
|
18
|
+
|
19
|
+
What's Growl? Growl is a really cool "global notification system for Mac OS
|
20
|
+
X". See http://growl.info/
|
21
|
+
|
22
|
+
See also the Ruby Growl bindings in Growl's subversion repository:
|
23
|
+
http://growl.info/documentation/growl-source-install.php
|
24
|
+
|
25
|
+
ruby-growl also contains a command-line notification tool named 'growl'. Where possible, it isoption-compatible with growlnotify. (Use --priority instead of -p.)
|
26
|
+
EOF
|
27
|
+
|
28
|
+
s.files = File.read("Manifest.txt").split($\)
|
29
|
+
|
30
|
+
s.require_path = 'lib'
|
31
|
+
|
32
|
+
s.executables = ["growl"]
|
33
|
+
s.default_executable = "growl"
|
34
|
+
|
35
|
+
s.has_rdoc = true
|
36
|
+
|
37
|
+
s.author = "Eric Hodel"
|
38
|
+
s.email = "drbrain@segment7.net"
|
39
|
+
s.homepage = "http://segment7.net/projects/ruby/growl/"
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Targets
|
44
|
+
##
|
45
|
+
|
46
|
+
desc "Run the tests"
|
47
|
+
task :default => [ :test ]
|
48
|
+
|
49
|
+
desc "Run the tests"
|
50
|
+
Rake::TestTask.new "test" do |t|
|
51
|
+
t.libs << "test"
|
52
|
+
t.pattern = "test/test_*.rb"
|
53
|
+
t.verbose = true
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "Build RDoc"
|
57
|
+
Rake::RDocTask.new "rdoc" do |rd|
|
58
|
+
rd.rdoc_dir = "doc"
|
59
|
+
rd.rdoc_files.add "lib"
|
60
|
+
rd.main = "Growl"
|
61
|
+
end
|
62
|
+
|
63
|
+
desc "Build Packages"
|
64
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
65
|
+
pkg.need_tar = true
|
66
|
+
end
|
67
|
+
|
data/bin/growl
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
require 'ruby-growl'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
##
|
7
|
+
# Defaults
|
8
|
+
|
9
|
+
host = nil
|
10
|
+
name = "ruby-growl"
|
11
|
+
notify_type = "ruby-growl Notification"
|
12
|
+
title = ""
|
13
|
+
message = nil
|
14
|
+
priority = 0
|
15
|
+
sticky = false
|
16
|
+
password = nil
|
17
|
+
|
18
|
+
##
|
19
|
+
# Options
|
20
|
+
|
21
|
+
opts = OptionParser.new do |opts|
|
22
|
+
opts.banner = "Usage: #{$0} -H HOSTNAME [options]"
|
23
|
+
opts.separator ""
|
24
|
+
opts.separator " Where possible, growl is compatible with growlnotify's arguments."
|
25
|
+
opts.separator " (Except for -p, use --priority)"
|
26
|
+
opts.separator ""
|
27
|
+
opts.separator "Synopsis:"
|
28
|
+
opts.separator "echo \"message\" | growl -H localhost"
|
29
|
+
opts.separator ""
|
30
|
+
opts.separator "growl -H localhost -m message"
|
31
|
+
opts.separator ""
|
32
|
+
opts.separator "Options:"
|
33
|
+
|
34
|
+
opts.on("-H", "--host HOSTNAME", "Send notifications to HOSTNAME") do |val|
|
35
|
+
host = val
|
36
|
+
end
|
37
|
+
|
38
|
+
opts.on("-n", "--name [NAME]", "Sending application name",
|
39
|
+
"(Defaults to \"ruby-growl\")") do |val|
|
40
|
+
name = val
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on("-y", "--type [TYPE]", "Notification type",
|
44
|
+
"(Defauts to \"Ruby Growl Notification\")") do |val|
|
45
|
+
notify_type = val
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on("-t", "--title [TITLE]", "Notification title") do |val|
|
49
|
+
title = val
|
50
|
+
end
|
51
|
+
|
52
|
+
opts.on("-m", "--message [MESSAGE]",
|
53
|
+
"Send this message instead of reading STDIN") do |val|
|
54
|
+
message = val
|
55
|
+
end
|
56
|
+
|
57
|
+
# HACK -p -1 raises
|
58
|
+
opts.on("--priority [PRIORITY]", Integer,
|
59
|
+
"Notification priority",
|
60
|
+
"Priority can be between -2 and 2") do |val|
|
61
|
+
priority = val
|
62
|
+
end
|
63
|
+
|
64
|
+
opts.on("-s", "--[no-]sticky", "Make the notification sticky") do |val|
|
65
|
+
sticky = val
|
66
|
+
end
|
67
|
+
|
68
|
+
opts.on("-P", "--password [PASSWORD]", "Growl UDP Password") do |val|
|
69
|
+
password = val
|
70
|
+
end
|
71
|
+
|
72
|
+
opts.separator ""
|
73
|
+
|
74
|
+
opts.on("-h", "--help", "Show this message") do
|
75
|
+
puts opts
|
76
|
+
exit
|
77
|
+
end
|
78
|
+
|
79
|
+
opts.on("-v", "--version", "Show version") do
|
80
|
+
puts Growl::VERSION
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# Do it!
|
86
|
+
opts.parse!
|
87
|
+
|
88
|
+
if host.nil? then
|
89
|
+
puts opts
|
90
|
+
exit 1
|
91
|
+
end
|
92
|
+
|
93
|
+
message = STDIN.read if message.nil?
|
94
|
+
|
95
|
+
g = Growl.new host, name, [notify_type], [notify_type], password
|
96
|
+
g.notify notify_type, title, message, priority, sticky
|
97
|
+
|
data/lib/ruby-growl.rb
ADDED
@@ -0,0 +1,274 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
$TESTING = false unless defined? $TESTING
|
4
|
+
|
5
|
+
require 'md5'
|
6
|
+
require 'socket'
|
7
|
+
|
8
|
+
##
|
9
|
+
# ruby-growl allows you to perform Growl notification via UDP from machines
|
10
|
+
# without growl installed (for example, non-OSX machines).
|
11
|
+
#
|
12
|
+
# What's Growl? Growl is a really cool "global notification system for Mac OS
|
13
|
+
# X". See http://growl.info/
|
14
|
+
#
|
15
|
+
# You'll need a Mac to recieve Growl notifications, but you can send Growl
|
16
|
+
# notifications from any UDP-capable machine that runs Ruby.
|
17
|
+
#
|
18
|
+
# See also the Ruby Growl bindings in Growl's subversion repository:
|
19
|
+
# http://growl.info/documentation/growl-source-install.php
|
20
|
+
#
|
21
|
+
# ruby-growl also contains a command-line notification tool named 'growl'. It
|
22
|
+
# is almost completely option-compatible with growlnotify. (All except for -p
|
23
|
+
# is supported, use --priority instead.)
|
24
|
+
#
|
25
|
+
# = Synopsis
|
26
|
+
#
|
27
|
+
# g = Growl.new "127.0.0.1", "ruby-growl",
|
28
|
+
# ["ruby-growl Notification"]
|
29
|
+
# g.notify "ruby-growl Notification", "It Came From Ruby-Growl",
|
30
|
+
# "Greetings!"
|
31
|
+
|
32
|
+
class Growl
|
33
|
+
|
34
|
+
##
|
35
|
+
# ruby-growl Version
|
36
|
+
|
37
|
+
VERSION = "1.0.0"
|
38
|
+
|
39
|
+
##
|
40
|
+
# Growl Network Registration Packet +pack+ Format
|
41
|
+
#--
|
42
|
+
# Format:
|
43
|
+
#
|
44
|
+
# struct GrowlNetworkRegistration {
|
45
|
+
# struct GrowlNetworkPacket {
|
46
|
+
# unsigned char version;
|
47
|
+
# unsigned char type;
|
48
|
+
# } __attribute__((packed));
|
49
|
+
# unsigned short appNameLen;
|
50
|
+
# unsigned char numAllNotifications;
|
51
|
+
# unsigned char numDefaultNotifications;
|
52
|
+
# /*
|
53
|
+
# * Variable sized. Format:
|
54
|
+
# * <application name><all notifications><default notifications><checksum>
|
55
|
+
# * where <all notifications> is of the form (<length><name>){num} and
|
56
|
+
# * <default notifications> is an array of indices into the all notifications
|
57
|
+
# * array, each index being 8 bits.
|
58
|
+
# */
|
59
|
+
# unsigned char data[];
|
60
|
+
# } __attribute__((packed));
|
61
|
+
|
62
|
+
GNR_FORMAT = "CCnCCa*"
|
63
|
+
|
64
|
+
##
|
65
|
+
# Growl Network Notification Packet +pack+ Format
|
66
|
+
#--
|
67
|
+
# Format:
|
68
|
+
#
|
69
|
+
# struct GrowlNetworkNotification {
|
70
|
+
# struct GrowlNetworkPacket {
|
71
|
+
# unsigned char version;
|
72
|
+
# unsigned char type;
|
73
|
+
# } __attribute__((packed));
|
74
|
+
# struct GrowlNetworkNotificationFlags {
|
75
|
+
# unsigned reserved: 12;
|
76
|
+
# signed priority: 3;
|
77
|
+
# unsigned sticky: 1;
|
78
|
+
# } __attribute__((packed)) flags; //size = 16 (12 + 3 + 1)
|
79
|
+
# unsigned short nameLen;
|
80
|
+
# unsigned short titleLen;
|
81
|
+
# unsigned short descriptionLen;
|
82
|
+
# unsigned short appNameLen;
|
83
|
+
# /*
|
84
|
+
# * Variable sized. Format:
|
85
|
+
# * <notification name><title><description><application name><checksum>
|
86
|
+
# */
|
87
|
+
# unsigned char data[];
|
88
|
+
# } __attribute__((packed));
|
89
|
+
|
90
|
+
GNN_FORMAT = "CCnnnnna*"
|
91
|
+
|
92
|
+
##
|
93
|
+
# Growl UDP Port
|
94
|
+
|
95
|
+
GROWL_UDP_PORT = 9887
|
96
|
+
|
97
|
+
##
|
98
|
+
# Growl Protocol Version
|
99
|
+
|
100
|
+
GROWL_PROTOCOL_VERSION = 1
|
101
|
+
|
102
|
+
##
|
103
|
+
# Growl Registration Packet Id
|
104
|
+
|
105
|
+
GROWL_TYPE_REGISTRATION = 0
|
106
|
+
|
107
|
+
##
|
108
|
+
# Growl Notification Packet Id
|
109
|
+
|
110
|
+
GROWL_TYPE_NOTIFICATION = 1
|
111
|
+
|
112
|
+
##
|
113
|
+
# Creates a new Growl notifier and automatically registers any notifications
|
114
|
+
# with the remote machine.
|
115
|
+
#
|
116
|
+
# +host+ is the host to contact.
|
117
|
+
#
|
118
|
+
# +app_name+ is the name of the application sending the notifications.
|
119
|
+
#
|
120
|
+
# +all_notifies+ is a list of notification types your application sends.
|
121
|
+
#
|
122
|
+
# +default_notifies+ is a list of notification types that are turned on by
|
123
|
+
# default.
|
124
|
+
#
|
125
|
+
# I'm not sure about what +default_notifies+ is supposed to be set to, since
|
126
|
+
# there is a comment that says "not a subset of all_notifies" in the code.
|
127
|
+
#
|
128
|
+
# +password+ is the password needed to send notifications to +host+.
|
129
|
+
|
130
|
+
def initialize(host, app_name, all_notifies, default_notifies = nil,
|
131
|
+
password = nil)
|
132
|
+
@socket = UDPSocket.open
|
133
|
+
# FIXME This goes somewhere else
|
134
|
+
@socket.connect host, GROWL_UDP_PORT
|
135
|
+
@app_name = app_name
|
136
|
+
@all_notifies = all_notifies
|
137
|
+
@default_notifies = default_notifies.nil? ? all_notifies : default_notifies
|
138
|
+
@password = password
|
139
|
+
|
140
|
+
register
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# Sends a notification.
|
145
|
+
#
|
146
|
+
# +notify_type+ is the type of notification to send.
|
147
|
+
#
|
148
|
+
# +title+ is a title for the notification.
|
149
|
+
#
|
150
|
+
# +message+ is the body of the notification.
|
151
|
+
#
|
152
|
+
# +priority+ is the priorty of message to send.
|
153
|
+
#
|
154
|
+
# +sticky+ makes the notification stick until clicked.
|
155
|
+
|
156
|
+
def notify(notify_type, title, message, priority = 0, sticky = false)
|
157
|
+
raise "Unknown Notification" unless @all_notifies.include? notify_type
|
158
|
+
raise "Invalid Priority" unless priority >= -2 and priority <= 2
|
159
|
+
|
160
|
+
send notification_packet(notify_type, title, message, priority, sticky)
|
161
|
+
end
|
162
|
+
|
163
|
+
private unless $TESTING
|
164
|
+
|
165
|
+
##
|
166
|
+
# Registers the notification types with +host+.
|
167
|
+
|
168
|
+
def register
|
169
|
+
send registration_packet
|
170
|
+
end
|
171
|
+
|
172
|
+
##
|
173
|
+
# Sends a Growl packet
|
174
|
+
|
175
|
+
def send(packet)
|
176
|
+
set_sndbuf packet.length
|
177
|
+
@socket.send packet, 0
|
178
|
+
@socket.flush
|
179
|
+
end
|
180
|
+
|
181
|
+
##
|
182
|
+
# Builds a Growl registration packet
|
183
|
+
|
184
|
+
def registration_packet
|
185
|
+
length = 0
|
186
|
+
data = []
|
187
|
+
data_format = ""
|
188
|
+
|
189
|
+
packet = [
|
190
|
+
GROWL_PROTOCOL_VERSION,
|
191
|
+
GROWL_TYPE_REGISTRATION
|
192
|
+
]
|
193
|
+
|
194
|
+
packet << @app_name.length
|
195
|
+
packet << @all_notifies.length
|
196
|
+
packet << @default_notifies.length
|
197
|
+
|
198
|
+
data << @app_name
|
199
|
+
data_format = "a#{@app_name.length}"
|
200
|
+
|
201
|
+
@all_notifies.each do |notify|
|
202
|
+
data << notify.length
|
203
|
+
data << notify
|
204
|
+
data_format << "na#{notify.length}"
|
205
|
+
end
|
206
|
+
|
207
|
+
@default_notifies.each do |notify|
|
208
|
+
data << @all_notifies.index(notify) if @all_notifies.include? notify
|
209
|
+
data_format << "C"
|
210
|
+
end
|
211
|
+
|
212
|
+
data = data.pack data_format
|
213
|
+
|
214
|
+
packet << data
|
215
|
+
|
216
|
+
packet = packet.pack GNR_FORMAT
|
217
|
+
|
218
|
+
checksum = MD5.new packet
|
219
|
+
checksum.update @password unless @password.nil?
|
220
|
+
|
221
|
+
packet << checksum.digest
|
222
|
+
|
223
|
+
return packet
|
224
|
+
end
|
225
|
+
|
226
|
+
##
|
227
|
+
# Builds a Growl notification packet
|
228
|
+
|
229
|
+
def notification_packet(name, title, description, priority, sticky)
|
230
|
+
flags = 0
|
231
|
+
data = []
|
232
|
+
|
233
|
+
packet = [
|
234
|
+
GROWL_PROTOCOL_VERSION,
|
235
|
+
GROWL_TYPE_NOTIFICATION,
|
236
|
+
]
|
237
|
+
|
238
|
+
flags = 0
|
239
|
+
flags |= ((0x7 & priority) << 1) # 3 bits for priority
|
240
|
+
flags |= 1 if sticky # 1 bit for sticky
|
241
|
+
|
242
|
+
packet << flags
|
243
|
+
packet << name.length
|
244
|
+
packet << title.length
|
245
|
+
packet << description.length
|
246
|
+
packet << @app_name.length
|
247
|
+
|
248
|
+
data << name
|
249
|
+
data << title
|
250
|
+
data << description
|
251
|
+
data << @app_name
|
252
|
+
|
253
|
+
packet << data.join
|
254
|
+
packet = packet.pack GNN_FORMAT
|
255
|
+
|
256
|
+
checksum = MD5.new packet
|
257
|
+
checksum.update @password unless @password.nil?
|
258
|
+
|
259
|
+
packet << checksum.digest
|
260
|
+
|
261
|
+
return packet
|
262
|
+
end
|
263
|
+
|
264
|
+
##
|
265
|
+
# Set the size of the send buffer
|
266
|
+
#--
|
267
|
+
# Is this truly necessary?
|
268
|
+
|
269
|
+
def set_sndbuf(length)
|
270
|
+
@socket.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDBUF, length
|
271
|
+
end
|
272
|
+
|
273
|
+
end
|
274
|
+
|
@@ -0,0 +1,217 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
$TESTING = true
|
4
|
+
|
5
|
+
require 'test/unit'
|
6
|
+
|
7
|
+
require 'ruby-growl'
|
8
|
+
|
9
|
+
class TestGrowl < Test::Unit::TestCase
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@growl = Growl.new "localhost", "ruby-growl test",
|
13
|
+
["ruby-growl Test Notification"]
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_notify_priority
|
17
|
+
assert_raises RuntimeError do
|
18
|
+
@growl.notify "ruby-growl Test Notification", "", "", -3
|
19
|
+
end
|
20
|
+
|
21
|
+
assert_nothing_raised do
|
22
|
+
-2.upto 2 do |priority|
|
23
|
+
@growl.notify "ruby-growl Test Notification",
|
24
|
+
"Priority #{priority}",
|
25
|
+
"This message should have a priority set.", priority
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
assert_raises RuntimeError do
|
30
|
+
@growl.notify "ruby-growl Test Notification", "", "", 3
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_notify_notify_type
|
35
|
+
assert_raises RuntimeError do
|
36
|
+
@growl.notify "bad notify type", "", ""
|
37
|
+
end
|
38
|
+
|
39
|
+
assert_nothing_raised do
|
40
|
+
@growl.notify "ruby-growl Test Notification", "Empty", "This notification is empty."
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_notify_sticky
|
45
|
+
@growl.notify "ruby-growl Test Notification", "Sticky",
|
46
|
+
"This notification should be sticky.", 0, true
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_registration_packet
|
50
|
+
@growl = Growl.new "localhost", "growlnotify",
|
51
|
+
["Command-Line Growl Notification"]
|
52
|
+
|
53
|
+
expected = [
|
54
|
+
"01", "00", "00", "0b", "01", "01", "67", "72", # ......gr
|
55
|
+
"6f", "77", "6c", "6e", "6f", "74", "69", "66", # owlnotif
|
56
|
+
"79", "00", "1f", "43", "6f", "6d", "6d", "61", # y..Comma
|
57
|
+
"6e", "64", "2d", "4c", "69", "6e", "65", "20", # nd-Line.
|
58
|
+
"47", "72", "6f", "77", "6c", "20", "4e", "6f", # Growl.No
|
59
|
+
"74", "69", "66", "69", "63", "61", "74", "69", # tificati
|
60
|
+
"6f", "6e", "00", "57", "4a", "e3", "1b", "a5", # on.WJ...
|
61
|
+
"49", "9c", "25", "3a", "be", "75", "5d", "e5", # I.%:.u].
|
62
|
+
"2c", "c9", "96" # ,..
|
63
|
+
]
|
64
|
+
|
65
|
+
packet = @growl.registration_packet
|
66
|
+
|
67
|
+
packet = packet.split(//).map { |char| "%02x" % char[0] }
|
68
|
+
|
69
|
+
assert_equal expected, packet
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_notification_packet
|
73
|
+
@growl = Growl.new "localhost", "growlnotify",
|
74
|
+
["Command-Line Growl Notification"]
|
75
|
+
|
76
|
+
expected = [
|
77
|
+
"01", "01", "00", "00", "00", "1f", "00", "00", # ........
|
78
|
+
"00", "02", "00", "0b", "43", "6f", "6d", "6d", # ....Comm
|
79
|
+
"61", "6e", "64", "2d", "4c", "69", "6e", "65", # and-Line
|
80
|
+
"20", "47", "72", "6f", "77", "6c", "20", "4e", # .Growl.N
|
81
|
+
"6f", "74", "69", "66", "69", "63", "61", "74", # otificat
|
82
|
+
"69", "6f", "6e", "68", "69", "67", "72", "6f", # ionhigro
|
83
|
+
"77", "6c", "6e", "6f", "74", "69", "66", "79", # wlnotify
|
84
|
+
"7f", "9c", "a0", "dd", "b6", "6b", "64", "75", # .....kdu
|
85
|
+
"99", "c4", "4e", "7b", "f1", "b2", "5b", "e2", # ..N{..[.
|
86
|
+
]
|
87
|
+
|
88
|
+
packet = @growl.notification_packet "Command-Line Growl Notification",
|
89
|
+
"", "hi", 0, false
|
90
|
+
|
91
|
+
packet = packet.split(//).map { |char| "%02x" % char[0] }
|
92
|
+
|
93
|
+
assert_equal expected, packet
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_notification_packet_priority_negative_2
|
97
|
+
@growl = Growl.new "localhost", "growlnotify",
|
98
|
+
["Command-Line Growl Notification"]
|
99
|
+
|
100
|
+
expected = [
|
101
|
+
"01", "01", "00", "0c", "00", "1f", "00", "00", # ........
|
102
|
+
"00", "02", "00", "0b", "43", "6f", "6d", "6d", # ....Comm
|
103
|
+
"61", "6e", "64", "2d", "4c", "69", "6e", "65", # and-Line
|
104
|
+
"20", "47", "72", "6f", "77", "6c", "20", "4e", # .Growl.N
|
105
|
+
"6f", "74", "69", "66", "69", "63", "61", "74", # otificat
|
106
|
+
"69", "6f", "6e", "68", "69", "67", "72", "6f", # ionhigro
|
107
|
+
"77", "6c", "6e", "6f", "74", "69", "66", "79", # wlnotify
|
108
|
+
"6d", "98", "51", "12", "4f", "dc", "38", "4a",
|
109
|
+
"b5", "eb", "9e", "f3", "2d", "e0", "aa", "5e"
|
110
|
+
]
|
111
|
+
|
112
|
+
packet = @growl.notification_packet "Command-Line Growl Notification",
|
113
|
+
"", "hi", -2, false
|
114
|
+
|
115
|
+
packet = packet.split(//).map { |char| "%02x" % char[0] }
|
116
|
+
|
117
|
+
assert_equal expected, packet
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_notification_packet_priority_negative_1
|
121
|
+
@growl = Growl.new "localhost", "growlnotify",
|
122
|
+
["Command-Line Growl Notification"]
|
123
|
+
|
124
|
+
expected = [
|
125
|
+
"01", "01", "00", "0e", "00", "1f", "00", "00", # ........
|
126
|
+
"00", "02", "00", "0b", "43", "6f", "6d", "6d", # ....Comm
|
127
|
+
"61", "6e", "64", "2d", "4c", "69", "6e", "65", # and-Line
|
128
|
+
"20", "47", "72", "6f", "77", "6c", "20", "4e", # .Growl.N
|
129
|
+
"6f", "74", "69", "66", "69", "63", "61", "74", # otificat
|
130
|
+
"69", "6f", "6e", "68", "69", "67", "72", "6f", # ionhigro
|
131
|
+
"77", "6c", "6e", "6f", "74", "69", "66", "79", # wlnotify
|
132
|
+
"d2", "cc", "44", "30", "21", "fa", "fd", "c6",
|
133
|
+
"a8", "f3", "db", "72", "2b", "64", "f4", "25"
|
134
|
+
]
|
135
|
+
|
136
|
+
packet = @growl.notification_packet "Command-Line Growl Notification",
|
137
|
+
"", "hi", -1, false
|
138
|
+
|
139
|
+
packet = packet.split(//).map { |char| "%02x" % char[0] }
|
140
|
+
|
141
|
+
assert_equal expected, packet
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_notification_packet_priority_1
|
145
|
+
@growl = Growl.new "localhost", "growlnotify",
|
146
|
+
["Command-Line Growl Notification"]
|
147
|
+
|
148
|
+
expected = [
|
149
|
+
"01", "01", "00", "02", "00", "1f", "00", "00", # ........
|
150
|
+
"00", "02", "00", "0b", "43", "6f", "6d", "6d", # ....Comm
|
151
|
+
"61", "6e", "64", "2d", "4c", "69", "6e", "65", # and-Line
|
152
|
+
"20", "47", "72", "6f", "77", "6c", "20", "4e", # .Growl.N
|
153
|
+
"6f", "74", "69", "66", "69", "63", "61", "74", # otificat
|
154
|
+
"69", "6f", "6e", "68", "69", "67", "72", "6f", # ionhigro
|
155
|
+
"77", "6c", "6e", "6f", "74", "69", "66", "79", # wlnotify
|
156
|
+
"bf", "de", "a5", "63", "09", "29", "27", "02",
|
157
|
+
"13", "1f", "8e", "5c", "f1", "88", "f8", "93"
|
158
|
+
]
|
159
|
+
|
160
|
+
packet = @growl.notification_packet "Command-Line Growl Notification",
|
161
|
+
"", "hi", 1, false
|
162
|
+
|
163
|
+
packet = packet.split(//).map { |char| "%02x" % char[0] }
|
164
|
+
|
165
|
+
assert_equal expected, packet
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_notification_packet_priority_2
|
169
|
+
@growl = Growl.new "localhost", "growlnotify",
|
170
|
+
["Command-Line Growl Notification"]
|
171
|
+
|
172
|
+
expected = [
|
173
|
+
"01", "01", "00", "04", "00", "1f", "00", "00", # ........
|
174
|
+
"00", "02", "00", "0b", "43", "6f", "6d", "6d", # ....Comm
|
175
|
+
"61", "6e", "64", "2d", "4c", "69", "6e", "65", # and-Line
|
176
|
+
"20", "47", "72", "6f", "77", "6c", "20", "4e", # .Growl.N
|
177
|
+
"6f", "74", "69", "66", "69", "63", "61", "74", # otificat
|
178
|
+
"69", "6f", "6e", "68", "69", "67", "72", "6f", # ionhigro
|
179
|
+
"77", "6c", "6e", "6f", "74", "69", "66", "79", # wlnotify
|
180
|
+
"d5", "40", "af", "67", "3c", "d3", "80", "eb",
|
181
|
+
"3d", "46", "5d", "c3", "75", "09", "24", "95"
|
182
|
+
]
|
183
|
+
|
184
|
+
packet = @growl.notification_packet "Command-Line Growl Notification",
|
185
|
+
"", "hi", 2, false
|
186
|
+
|
187
|
+
packet = packet.split(//).map { |char| "%02x" % char[0] }
|
188
|
+
|
189
|
+
assert_equal expected, packet
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_notification_packet_priority_sticky
|
193
|
+
@growl = Growl.new "localhost", "growlnotify",
|
194
|
+
["Command-Line Growl Notification"]
|
195
|
+
|
196
|
+
expected = [
|
197
|
+
"01", "01", "00", "01", "00", "1f", "00", "00", # ........
|
198
|
+
"00", "02", "00", "0b", "43", "6f", "6d", "6d", # ....Comm
|
199
|
+
"61", "6e", "64", "2d", "4c", "69", "6e", "65", # and-Line
|
200
|
+
"20", "47", "72", "6f", "77", "6c", "20", "4e", # .Growl.N
|
201
|
+
"6f", "74", "69", "66", "69", "63", "61", "74", # otificat
|
202
|
+
"69", "6f", "6e", "68", "69", "67", "72", "6f", # ionhigro
|
203
|
+
"77", "6c", "6e", "6f", "74", "69", "66", "79", # wlnotify
|
204
|
+
"eb", "75", "2a", "36", "85", "6c", "d7", "a2",
|
205
|
+
"72", "0b", "13", "6b", "41", "c7", "ea", "1b"
|
206
|
+
]
|
207
|
+
|
208
|
+
packet = @growl.notification_packet "Command-Line Growl Notification",
|
209
|
+
"", "hi", 0, true
|
210
|
+
|
211
|
+
packet = packet.split(//).map { |char| "%02x" % char[0] }
|
212
|
+
|
213
|
+
assert_equal expected, packet
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
|
metadata
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.3
|
3
|
+
specification_version: 1
|
4
|
+
name: ruby-growl
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2004-12-13
|
8
|
+
summary: Pure-Ruby Growl Notifier
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: drbrain@segment7.net
|
12
|
+
homepage: http://segment7.net/projects/ruby/growl/
|
13
|
+
rubyforge_project:
|
14
|
+
description: "ruby-growl allows you to perform Growl notification via UDP from machines
|
15
|
+
without growl installed (for example, non-OSX machines). What's Growl? Growl
|
16
|
+
is a really cool \"global notification system for Mac OS X\". See
|
17
|
+
http://growl.info/ See also the Ruby Growl bindings in Growl's subversion
|
18
|
+
repository: http://growl.info/documentation/growl-source-install.php ruby-growl
|
19
|
+
also contains a command-line notification tool named 'growl'. Where possible,
|
20
|
+
it isoption-compatible with growlnotify. (Use --priority instead of -p.)"
|
21
|
+
autorequire:
|
22
|
+
default_executable: growl
|
23
|
+
bindir: bin
|
24
|
+
has_rdoc: true
|
25
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
26
|
+
requirements:
|
27
|
+
-
|
28
|
+
- ">"
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: 0.0.0
|
31
|
+
version:
|
32
|
+
platform: ruby
|
33
|
+
authors:
|
34
|
+
- Eric Hodel
|
35
|
+
files:
|
36
|
+
- LICENSE
|
37
|
+
- Manifest.txt
|
38
|
+
- Rakefile
|
39
|
+
- bin/growl
|
40
|
+
- lib/ruby-growl.rb
|
41
|
+
- test/test_ruby-growl.rb
|
42
|
+
test_files: []
|
43
|
+
rdoc_options: []
|
44
|
+
extra_rdoc_files: []
|
45
|
+
executables:
|
46
|
+
- growl
|
47
|
+
extensions: []
|
48
|
+
requirements: []
|
49
|
+
dependencies: []
|