ruby-growl 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|