tweet 0.6

Sign up to get free protection for your applications and to get access to all the features.
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