tweet 0.6

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.
Files changed (65) hide show
  1. data/bin/ttime +36 -0
  2. data/bin/tweet +30 -0
  3. data/bin/tweetd +126 -0
  4. data/doc/classes/SimplePop.html +125 -0
  5. data/doc/classes/SimplePop.src/M000009.html +59 -0
  6. data/doc/classes/SimplePop.src/M000010.html +43 -0
  7. data/doc/classes/SimplePopWindow.html +126 -0
  8. data/doc/classes/SimplePopWindow.src/M000005.html +77 -0
  9. data/doc/classes/SimplePopWindow.src/M000006.html +36 -0
  10. data/doc/classes/SyslogNotifier.html +113 -0
  11. data/doc/classes/SyslogNotifier.src/M000003.html +34 -0
  12. data/doc/classes/SyslogNotifier.src/M000004.html +39 -0
  13. data/doc/classes/Tweet/Monitor.html +236 -0
  14. data/doc/classes/Tweet/Monitor.src/M000028.html +53 -0
  15. data/doc/classes/Tweet/Monitor.src/M000029.html +38 -0
  16. data/doc/classes/Tweet/Monitor.src/M000030.html +40 -0
  17. data/doc/classes/Tweet/Monitor.src/M000031.html +31 -0
  18. data/doc/classes/Tweet/Monitor.src/M000032.html +32 -0
  19. data/doc/classes/Tweet/Monitor.src/M000033.html +65 -0
  20. data/doc/classes/Tweet/Monitor.src/M000034.html +38 -0
  21. data/doc/classes/Tweet/Note.html +272 -0
  22. data/doc/classes/Tweet/Note.src/M000020.html +32 -0
  23. data/doc/classes/Tweet/Note.src/M000021.html +30 -0
  24. data/doc/classes/Tweet/Note.src/M000022.html +30 -0
  25. data/doc/classes/Tweet/Note.src/M000023.html +30 -0
  26. data/doc/classes/Tweet/Note.src/M000024.html +30 -0
  27. data/doc/classes/Tweet/Note.src/M000025.html +30 -0
  28. data/doc/classes/Tweet/Note.src/M000026.html +30 -0
  29. data/doc/classes/Tweet/Note.src/M000027.html +30 -0
  30. data/doc/classes/Tweet/Notifier.html +147 -0
  31. data/doc/classes/Tweet/Notifier.src/M000018.html +34 -0
  32. data/doc/classes/Tweet/Notifier.src/M000019.html +30 -0
  33. data/doc/classes/Tweet.html +336 -0
  34. data/doc/classes/Tweet.src/M000011.html +42 -0
  35. data/doc/classes/Tweet.src/M000012.html +30 -0
  36. data/doc/classes/Tweet.src/M000013.html +30 -0
  37. data/doc/classes/Tweet.src/M000014.html +30 -0
  38. data/doc/classes/Tweet.src/M000015.html +30 -0
  39. data/doc/classes/Tweet.src/M000016.html +30 -0
  40. data/doc/classes/Tweet.src/M000017.html +30 -0
  41. data/doc/classes/XOSDNotifier.html +113 -0
  42. data/doc/classes/XOSDNotifier.src/M000007.html +36 -0
  43. data/doc/classes/XOSDNotifier.src/M000008.html +38 -0
  44. data/doc/created.rid +1 -0
  45. data/doc/files/README.html +228 -0
  46. data/doc/files/bin/ttime.html +112 -0
  47. data/doc/files/bin/tweet.html +111 -0
  48. data/doc/files/bin/tweetd.html +163 -0
  49. data/doc/files/bin/tweetd.src/M000001.html +51 -0
  50. data/doc/files/bin/tweetd.src/M000002.html +30 -0
  51. data/doc/files/lib/tweet_rb.html +178 -0
  52. data/doc/files/plugins/simplepop_rb.html +97 -0
  53. data/doc/files/plugins/syslog_rb.html +101 -0
  54. data/doc/files/plugins/xosd_rb.html +96 -0
  55. data/doc/fr_class_index.html +53 -0
  56. data/doc/fr_file_index.html +53 -0
  57. data/doc/fr_method_index.html +79 -0
  58. data/doc/index.html +26 -0
  59. data/doc/rdoc-style.css +175 -0
  60. data/images/comments.png +0 -0
  61. data/lib/tweet.rb +437 -0
  62. data/plugins/simplepop.rb +128 -0
  63. data/plugins/syslog.rb +24 -0
  64. data/plugins/xosd.rb +23 -0
  65. metadata +142 -0
data/lib/tweet.rb ADDED
@@ -0,0 +1,437 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # = Tweet
4
+ #
5
+ # == Synopsis
6
+ #
7
+ # A generalized notification daemon. Can be petitioned by an arbitrary
8
+ # application to activate a notification. Notifications can be customized by
9
+ # the user via a plugin architecture. Examples include a GTK2 popup dialog, a
10
+ # syslog entry, or an email alert.
11
+ #
12
+ # Can also be required in a ruby script to access a running Tweet daemon (see
13
+ # Tweet.notify, Tweet.message, Tweet.running?, Tweet.stop).
14
+ #
15
+ # The website is here: http://tweet.rubyforge.org/
16
+ #
17
+ # == Installation
18
+ #
19
+ # gem install tweet
20
+ #
21
+ # or maybe:
22
+ #
23
+ # sudo gem install tweet
24
+ #
25
+ # == Usage
26
+ #
27
+ # tweetd [options]
28
+ #
29
+ # == Requirements
30
+ #
31
+ # - Ruby 1.8
32
+ # - daemons library
33
+ # - pidify library
34
+ #
35
+ # == Examples
36
+ #
37
+ # To start the daemon:
38
+ # tweetd -d
39
+ #
40
+ # To contact the daemon from the shell:
41
+ # tweet "hello world"
42
+ #
43
+ # To contact the daemon from ruby:
44
+ # require 'tweet'
45
+ # Tweet.message("hello world")
46
+ #
47
+ # == Author
48
+ #
49
+ # Payton Swick, 2006
50
+ #
51
+ # == License Creative Commons GPL license.
52
+ # http://creativecommons.org/licenses/GPL/2.0/
53
+ #
54
+
55
+ module Tweet
56
+
57
+ require 'rubygems'
58
+ require 'gserver'
59
+ require 'yaml'
60
+ require 'pidify'
61
+
62
+ VERSION = '0.6'
63
+
64
+ # Priority levels.
65
+ #
66
+ # They can be referenced from other classes like this:
67
+ #
68
+ # Tweet::PRI['WARNING']
69
+ PRI = {
70
+ 'CRITICAL' => 1,
71
+ 'WARNING' => 2,
72
+ 'INFO' => 3,
73
+ 'LOW' => 4,
74
+ 'DEBUG' => 5
75
+ }
76
+
77
+ # The TCP port to listen on.
78
+ PORT = 9128
79
+
80
+ # Enable using syslog for tweetd events (this is different from the syslog
81
+ # notifier plugin, as it does not log notifications. This logs only tweetd
82
+ # activity, eg: stopping and starting.)
83
+ USE_SYSLOG = true
84
+
85
+ # Experimental GTK Tray icon.
86
+ USE_GTK_TRAY_ICON = true
87
+
88
+ class << self
89
+
90
+ # Given an instance of Note, this will try to contact a running tweet
91
+ # instance and send a notification. See Tweet::message for a simpler
92
+ # version.
93
+ #
94
+ # Example:
95
+ # require 'tweet'
96
+ # Tweet.notify(Tweet::Note.info("Hello World", "Hello World!", "5", "test application"))
97
+ def notify(note)
98
+ require 'net/telnet'
99
+ message = 'app "'+note.application.to_s+'";priority "'+note.priority.to_s+'";duration "'+note.duration.to_s+'";notifier "'+note.requested_notifiers.join(' ')+'";title "'+note.title.to_s+'";message "'+note.message.to_s+'"'
100
+ begin
101
+ conn = Net::Telnet.new({'Host' => 'localhost', 'Port' => PORT, 'Telnet mode' => false })
102
+ rescue
103
+ raise "Connection to tweet failed. Maybe tweetd is not running?"
104
+ end
105
+ out = conn.recv(128)
106
+ raise "While trying to connect to tweetd, server replied: '#{out.chomp}'" if out !~ /^2/
107
+ conn.write(message+"\n")
108
+ out = conn.recv(128)
109
+ raise "While trying to send this: '#{message}', tweetd replied: '#{out.chomp}'" if out !~ /^2/
110
+ conn.close
111
+ end
112
+
113
+ # Given a String, this will try to contact a running tweet instance and send
114
+ # the String as a notification from the calling application with a duration
115
+ # of a number of seconds (the default is a duration of 0 (permanent)). This
116
+ # is a simple form of Tweet::notify.
117
+ #
118
+ # Example:
119
+ # require 'tweet'
120
+ # Tweet.message "Hello World!"
121
+ def message(message, duration=0)
122
+ notify(Note.info(message, message, duration, $0))
123
+ end
124
+
125
+ # Just like Tweet.message, but allows specifying an array of notifier
126
+ # plugins to use as requested notifiers on the server. See Monitor for
127
+ # more information.
128
+ def message_with_notifiers(message, notifiers=[], duration=0)
129
+ notify(Note.new(message, message, duration, Tweet::PRI['INFO'], $0, notifiers))
130
+ end
131
+
132
+ # Returns the path location to the library file.
133
+ def where_am_i?
134
+ File.dirname(__FILE__)+'/..'
135
+ end
136
+
137
+ # Returns true if an instance of tweetd is running (or appears to be
138
+ # running).
139
+ def running?
140
+ Pidify.running?
141
+ end
142
+
143
+ # Stops a running instance of tweetd.
144
+ def stop
145
+ Pidify.stop
146
+ end
147
+
148
+ def start
149
+ Pidify.start
150
+ end
151
+ end
152
+
153
+
154
+ # Represents a unique notification message. One of these objects is passed
155
+ # to the show() method of the Notifier.
156
+ #
157
+ # The message can be printed by simply printing the Note or by accessing
158
+ # note.message. The Note also contains a title, a duration, a priority,
159
+ # the application (program) that activated it, the connection method that
160
+ # it used, and the timestamp of when the message was requested. All of
161
+ # these parameters (except for the method and time) rely on the application
162
+ # being honest, and have no built-in effects. Any interpretation is done
163
+ # by the Notifier.
164
+ #
165
+ # A Note may also include an array of requested notifiers (see Monitor).
166
+ class Note
167
+ attr_reader :title, :message, :time, :duration, :priority, :application, :method_received, :requested_notifiers
168
+
169
+ # Creates a new Note.
170
+ def initialize(title, message, duration, priority, application, notifiers=[], method_received=:built_in)
171
+ @title, @message, @duration, @priority, @application, @method_received = title, message, duration.to_i, priority.to_i, application, method_received
172
+ @requested_notifiers = notifiers
173
+ time = Time.now
174
+ end
175
+
176
+ # Shortcut for calling Note.info with a duration of 0.
177
+ def Note.simple(message)
178
+ self.info(message, message, 0, $0)
179
+ end
180
+
181
+ # Shortcut for making a new note with the INFO priority.
182
+ def Note.info(title, message, duration, application, method_received=:built_in)
183
+ self.new(title, message, duration, PRI['INFO'], application, [], method_received)
184
+ end
185
+
186
+ # Shortcut for making a new note with the WARNING priority.
187
+ def Note.warning(title, message, duration, application, method_received=:built_in)
188
+ self.new(title, message, duration, PRI['WARNING'], application, [], method_received)
189
+ end
190
+
191
+ # Shortcut for making a new note with the LOW priority.
192
+ def Note.low(title, message, duration, application, method_received=:built_in)
193
+ self.new(title, message, duration, PRI['LOW'], application, [], method_received)
194
+ end
195
+
196
+ # Shortcut for making a new note with the CRITICAL priority.
197
+ def Note.critical(title, message, duration, application, method_received=:built_in)
198
+ self.new(title, message, duration, PRI['CRITICAL'], application, [], method_received)
199
+ end
200
+
201
+ # Shortcut for making a new note with the DEBUG priority.
202
+ def Note.debug(title, message, duration, application, method_received=:built_in)
203
+ self.new(title, message, duration, PRI['DEBUG'], application, [], method_received)
204
+ end
205
+
206
+ # Printing the Note prints the message.
207
+ def to_s
208
+ @message
209
+ end
210
+ end
211
+
212
+
213
+ # Listens on a network port for notifications, firing off the appropriate
214
+ # action (via a Notifier) when one is received.
215
+ #
216
+ # A proper request looks like this (fields can be in any order, semicolons
217
+ # not required):
218
+ #
219
+ # app "MyApplication";title "hello world";message "Hello World!";duration "2";priority "3"
220
+ #
221
+ # A request may also include a list of requested notifier plugins, space
222
+ # separated, like this:
223
+ #
224
+ # app "MyApplication";title "hello world";message "Hello World!";duration "2";notifier "MyPlugin1 MyPlugin2";priority "3"
225
+ #
226
+ # If the server is configured to allow requested notifiers (see
227
+ # Monitor.allow_requested_notifiers), then it will try to use the plugins
228
+ # that were requested instead of the configured notifier plugins for that
229
+ # request.
230
+ class Monitor < GServer
231
+
232
+ # Don't show (silently drop) notifications of priority under this.
233
+ attr_accessor :allow_priority
234
+
235
+ # A list of the Notifier objects to send notifications to.
236
+ attr_reader :active_notifiers
237
+
238
+ # If true, the client can request a notifier plugins in its request string.
239
+ attr_accessor :allow_requested_notifiers
240
+
241
+ # Creates a new Monitor. Defaults to showing notifications of INFO
242
+ # level and higher. Change allow_priority to modify this setting either
243
+ # here or after the creation of the object.
244
+ def initialize(allow_priority=PRI['INFO'])
245
+ super(PORT)
246
+ @allow_priority = allow_priority
247
+ @allow_requested_notifiers = true
248
+ @active_notifiers = []
249
+
250
+ Signal.trap('INT') { puts "Tweet stopped by user interrupt."; stop }
251
+
252
+ if USE_SYSLOG
253
+ begin
254
+ require 'syslog'
255
+ @syslog = Syslog.open("tweetd");
256
+ @syslog.info('tweetd starting.')
257
+ rescue LoadError
258
+ end
259
+ end
260
+
261
+ if USE_GTK_TRAY_ICON
262
+ begin
263
+ set_up_gtk_tray_icon
264
+ @syslog.info('gtk tray icon loaded.') if @syslog
265
+ rescue LoadError
266
+ @syslog.info('gtk tray icon not loaded.') if @syslog
267
+ end
268
+ end
269
+ end
270
+
271
+ def set_up_gtk_tray_icon
272
+ require 'gtk2'
273
+ require 'gtktrayicon'
274
+ Gtk::init
275
+
276
+ screen = Gdk::Screen.default
277
+ @tray = Gtk::TrayIcon.new("tweetd", screen)
278
+ image_file = File.dirname(__FILE__) + '/../images/comments.png'
279
+ if File.exist?(image_file)
280
+ image = Gtk::Image.new(image_file)
281
+ else
282
+ @syslog.info("Error, tray image does not exist: #{image_file}") if @syslog
283
+ image = Gtk::Image.new(Gtk::Stock::DIALOG_INFO, Gtk::IconSize::BUTTON)
284
+ end
285
+ button = Gtk::EventBox.new.add(image)
286
+ menu = Gtk::Menu.new
287
+
288
+ quit_item = Gtk::MenuItem.new("Quit Tweetd")
289
+ quit_item.signal_connect('activate') do
290
+ stop
291
+ end
292
+ menu.append(quit_item)
293
+
294
+ menu.show_all
295
+
296
+ button.signal_connect('button_press_event') do |widget,event|
297
+ menu.popup(nil, nil, event.button, event.time)
298
+ end
299
+
300
+ @tray.add(button)
301
+ @tray.show_all
302
+ @gtk_thread = Thread.new { Gtk.main }
303
+ end
304
+ private :set_up_gtk_tray_icon
305
+
306
+ # Instantiates a (registered) Notifier and adds it to the list of active
307
+ # notifiers for this Watcher. Returns false if it fails.
308
+ def activate_notifier(name)
309
+ begin
310
+ return false unless n = get_notifier(name)
311
+ @syslog.info("activating notifier: #{n.class}") if @syslog
312
+ @active_notifiers << n
313
+ return true
314
+ rescue Exception=>e
315
+ @syslog.info("problem activating notifier: #{name} (#{e})") if @syslog
316
+ end
317
+ return false
318
+ end
319
+
320
+ # Instantiates a (registered) Notifier and returns it, or returns false if
321
+ # it failed.
322
+ def get_notifier(name)
323
+ begin
324
+ klass = eval(name)
325
+ if Notifier.registered_notifiers.include? klass
326
+ return klass.new
327
+ else
328
+ @syslog.info("notifier not registered: #{klass}") if @syslog
329
+ end
330
+ rescue Exception=>e
331
+ @syslog.info("notifier not found: #{name} (#{e})") if @syslog
332
+ end
333
+ return false
334
+ end
335
+
336
+ alias_method :old_start, :start
337
+ def start
338
+ Pidify.start
339
+ old_start
340
+ end
341
+
342
+ alias_method :old_stop, :stop
343
+ def stop
344
+ @syslog.info('tweetd stopping.') if @syslog
345
+ Pidify.stop
346
+ old_stop
347
+ end
348
+
349
+ # Handles incoming TCP connections.
350
+ def serve(client)
351
+ client.puts "200 Tweet #{VERSION} ready."
352
+
353
+ data = client.gets.chomp
354
+ unless data =~ /app "([^"]*)"/
355
+ client.puts "500 I don't know who you are."
356
+ return
357
+ end
358
+ app = $1
359
+ unless data =~ /title "([^"]*)"/
360
+ client.puts "500 Title required."
361
+ return
362
+ end
363
+ title = $1
364
+ unless data =~ /message "([^"]*)"/
365
+ client.puts "500 Message required."
366
+ return
367
+ end
368
+ message = $1.gsub('\n', "\n")
369
+ unless data =~ /duration "([^"]*)"/
370
+ client.puts "500 Duration required."
371
+ return
372
+ end
373
+ duration = $1
374
+ notifier = ''
375
+ if data =~ /notifier "([^"]*)"/
376
+ notifier = $1
377
+ end
378
+ unless data =~ /priority "([^"]*)"/
379
+ client.puts "500 Priority required."
380
+ return
381
+ end
382
+ priority = $1.to_i
383
+ client.puts "200 Request accepted."
384
+
385
+ note = Note.new(title, message, duration, priority, app, notifier.split(' '), :tcp)
386
+ notify(note) unless priority > @allow_priority
387
+ end
388
+
389
+ # Calls the Notifier#show method for each active notifier.
390
+ def notify(note)
391
+ notifiers_to_use = []
392
+ if @allow_requested_notifiers
393
+ notifiers_to_use = note.requested_notifiers.collect { |n| get_notifier(n) }
394
+ end
395
+ notifiers_to_use = @active_notifiers if notifiers_to_use.empty?
396
+ notifiers_to_use.each do |n|
397
+ next unless n and n.respond_to? :show
398
+ Thread.new { n.show(note) }
399
+ end
400
+ end
401
+ end
402
+
403
+
404
+ # Plugin-based notification mechanism. When a Note is activated, it will
405
+ # call the Notifier#show method for each subclass of Notifier, which can be
406
+ # overridden to provide whatever functionality is required.
407
+ #
408
+ # Example of a plugin:
409
+ #
410
+ # class MyPlugin < Tweet::Notifier
411
+ # def show(e)
412
+ # puts "--"
413
+ # puts "alert!! there's a message for you: #{e}"
414
+ # puts "--"
415
+ # end
416
+ # end
417
+ class Notifier
418
+ # A list of classes to be used as notifiers.
419
+ @registered_notifiers = []
420
+
421
+ class << self; attr_reader :registered_notifiers end
422
+
423
+ def Notifier.inherited(sub)
424
+ Notifier.registered_notifiers << sub
425
+ begin
426
+ Syslog.info("registered plugin: #{sub}")
427
+ rescue
428
+ end
429
+ end
430
+
431
+ # Override this method in a subclass (child) as a callback
432
+ # hook to provide a notification plugin.
433
+ def show(note)
434
+ puts "[tweet!] #{note}"
435
+ end
436
+ end
437
+ end
@@ -0,0 +1,128 @@
1
+ require 'gtk2'
2
+ require 'tweet'
3
+
4
+ # GTK2 slider-window-based notifier plugin for tweet.
5
+ class SimplePop < Tweet::Notifier
6
+
7
+ XSCREENSAVER_WATCH = false
8
+
9
+ def initialize
10
+ @current_messages = []
11
+
12
+ if Gtk.main_level == 0
13
+ Thread.new do
14
+ Gtk::init
15
+ Gtk.main
16
+ end
17
+ end
18
+
19
+ @suspend_popups = false
20
+ if XSCREENSAVER_WATCH
21
+ begin
22
+ xscreensaver = `which xscreensaver-command`
23
+ if xscreensaver
24
+ Thread.new do
25
+ File.open("|#{xscreensaver} -watch") do |ss|
26
+ loop do
27
+ case ss.gets
28
+ when /^LOCK|^BLANK/
29
+ @suspend_popups = true
30
+ when /^UNBLANK/
31
+ @suspend_popups = false
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ rescue
38
+ end
39
+ end
40
+ end
41
+
42
+ def show(note)
43
+ return if @suspend_popups == true
44
+
45
+ # Create a new window.
46
+ element = SimplePopWindow.new(note, note.duration, @current_messages.last)
47
+
48
+ # Add the new window to the list of windows.
49
+ @current_messages << element
50
+
51
+ # Call notify which calls Gtk.main (blocks) until the window is clicked or
52
+ # times out.
53
+ element.notify # blocks until hidden.
54
+
55
+ # Remove the stored reference to this window.
56
+ @current_messages.delete element
57
+ end
58
+ end
59
+
60
+
61
+ class SimplePopWindow < Gtk::Window
62
+
63
+ attr_reader :start_y
64
+
65
+ def initialize(note, duration=0, highest=nil)
66
+ @note = note
67
+ @duration = duration
68
+ @width = 260
69
+ @height = 80
70
+
71
+ super(Gtk::Window::POPUP)
72
+
73
+ resize(@width,@height)
74
+ stick
75
+ title = @note.title if @note.respond_to? :title
76
+ title = @note.to_s unless title
77
+
78
+ @root_win = Gdk::Window.default_root_window
79
+ @start_x = @root_win.geometry[2]-@width-10
80
+ @start_y = @root_win.geometry[3]-@height
81
+ @start_y = (highest.start_y-@height) if highest.respond_to? :start_y
82
+ screen_top = 0
83
+ @start_y = @root_win.geometry[3]-@height if @start_y <= screen_top
84
+ move(@start_x,@start_y)
85
+
86
+ @note = @note.to_s.gsub("<", "&lt;")
87
+ @note = @note.to_s.gsub(">", "&gt;")
88
+
89
+ @button = Gtk::Button.new
90
+ frame = Gtk::Frame.new
91
+ button_box = Gtk::HBox.new(false, 0)
92
+ image = Gtk::Image.new(Gtk::Stock::DIALOG_WARNING, Gtk::IconSize::DIALOG)
93
+ label = Gtk::Label.new(@note)
94
+
95
+ label.width_chars = (@width-image.width_request)/10
96
+ col = (@width - image.width_request)/10
97
+ col = 40
98
+ wrapped_text = label.text
99
+ wrapped_text = wrapped_text.gsub(/(.{1,#{col}})( +|$\n?)|(.{1,#{col}})/, "\\1\\3\n")
100
+ wrapped_text = wrapped_text.split("\n")[0 .. 4].join("\n")
101
+ label.set_markup("<small>#{wrapped_text}</small>")
102
+
103
+ frame.add(button_box)
104
+ button_box.add(image)
105
+ button_box.add(label)
106
+ @button.add(frame)
107
+
108
+ @button.signal_connect('clicked') { @sleep_thread.kill if @sleep_thread }
109
+ add(@button)
110
+
111
+ realize
112
+ @window = window # The GDK window object this uses.
113
+ show_all
114
+ end
115
+
116
+ # Activates the notification by displaying the window.
117
+ def notify
118
+ if @duration < 1
119
+ @sleep_thread = Thread.new { loop { sleep(0.1) } }
120
+ else
121
+ @sleep_thread = Thread.new { sleep(@duration) }
122
+ end
123
+ @sleep_thread.join
124
+ self.destroy
125
+ end
126
+ end
127
+
128
+ # SimplePopWindow.new("tweet rocks and is a mild sedative when used with chocolate!", 4).notify
data/plugins/syslog.rb ADDED
@@ -0,0 +1,24 @@
1
+ # Notifier for Tweet that logs messages to syslog.
2
+ require 'syslog'
3
+ class SyslogNotifier < Tweet::Notifier
4
+ def initialize
5
+ begin
6
+ @log = Syslog.open("tweetd");
7
+ rescue
8
+ @log = Syslog
9
+ end
10
+ end
11
+
12
+ def show(n)
13
+ message = n.application+": "+n.message
14
+ case n.priority
15
+ when Tweet::PRI['CRITICAL']: @log.crit(message)
16
+ when Tweet::PRI['WARNING']: @log.warning(message)
17
+ when Tweet::PRI['INFO']: @log.info(message)
18
+ when Tweet::PRI['LOW']: @log.notice(message)
19
+ when Tweet::PRI['DEBUG']: @log.debug(message)
20
+ else
21
+ @log.info(message)
22
+ end
23
+ end
24
+ end
data/plugins/xosd.rb ADDED
@@ -0,0 +1,23 @@
1
+ class XOSDNotifier < Tweet::Notifier
2
+ def initialize
3
+ require 'xosd'
4
+ @display_secs = 1
5
+ begin
6
+ @log = Syslog.open("tweetd");
7
+ rescue
8
+ @log = Syslog
9
+ end
10
+ end
11
+
12
+ def show(note)
13
+ osd = XOSD::Xosd.new 3
14
+ osd.position = XOSD::MIDDLE
15
+ osd.align = XOSD::CENTER
16
+ osd.color = "#00f0f0"
17
+ osd.outline_offset = 2
18
+ osd.shadow_offset = 6
19
+ osd.font = "-adobe-helvetica-*-r-*-*-34"
20
+ osd.display_message(0, note.to_s)
21
+ osd.wait @display_secs.to_i
22
+ end
23
+ end