cacophony 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ *.swp
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in cacophony.gemspec
4
+ gemspec
data/README.rdoc ADDED
@@ -0,0 +1,35 @@
1
+ = Cacophony notifier
2
+
3
+ * Author: David Lyons (http://loadedfingers.com)
4
+
5
+ == Caco-whatsie?
6
+
7
+ Cacophony is a small program that broadcasts notifications via a variety of mechanisms, such as growl, email and twitter.
8
+ It is great for notifiying you(or others) when a long running task is complete.
9
+ It operates as a standalone executable, and it also can read from STDIN to pipe output from your tasks to the notifiers.
10
+ The various notifiers are configured in ~/.cacophony, or via a config file passed via -c option.
11
+
12
+ == Requirements
13
+
14
+ * ruby 1.9.x
15
+ * trollop
16
+ * Growl (if you want growl notifications)
17
+
18
+ == Install
19
+
20
+ sudo gem install cacophony
21
+
22
+ Running cacophony for the first time will prompt you to create a sample configuration file, which you can edit as appropriate.
23
+
24
+ == Usage
25
+
26
+ Some examples:
27
+
28
+ cacophony -m 'just a message'
29
+ ./long_task_is_long | cacophony
30
+ ./long_task_is_long | cacophony -t 'job output:'
31
+ ./long_task_is_long && cacophony -m 'coffee break over'
32
+
33
+
34
+ == Developers
35
+ You can add customer notifiers by adding a class to lib/notifiers/. They must follow the naming pattern xNotifier, copy one of the existing classes for method signatures.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/bin/cacophony ADDED
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'yaml'
4
+ require 'trollop'
5
+ require 'fcntl'
6
+ require 'fileutils'
7
+
8
+ require 'cacophony'
9
+
10
+ #resolve symlinks FIX WHEN IN GEM
11
+ THIS_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
12
+ GEM_PATH = File.join('..','lib',File.dirname(THIS_FILE) )
13
+
14
+ RESULTS_SIZE = 50
15
+ DEFAULT_TITLE = 'Cacophony Notifier'
16
+ DEFAULT_MSG = 'Task finished!'
17
+
18
+ DEFAULT_CONF_PATH = '~/.cacophony'
19
+
20
+ opts = Trollop::options do
21
+ version "Cacophony v#{Cacophony::VERSION}(c) 2011 David Lyons"
22
+ banner <<-EOS
23
+ Cacophony is a small program that broadcasts notifications via a variety of mechanisms, such as growl, email and twitter.
24
+ It is great for notifiying you(or others) when a long running task is complete.
25
+ It operates as a standalone executable, and it also can read from STDIN to pipe output from your tasks to the notifiers.
26
+ The various notifiers are configured in #{DEFAULT_CONF_PATH}, or via a config file passed via -c option.
27
+
28
+ Usage:
29
+ cacophony [-options] [message]
30
+
31
+ Examples:
32
+ ./long_task_is_long | cacophony
33
+ ./long_task_is_long | cacophony -t 'job output:'
34
+ ./long_task_is_long && cacophony -m 'coffee break over'
35
+
36
+ Options:
37
+
38
+ EOS
39
+ opt :message, "The message to send via the notifiers", :short => 'm', :type => String, :default => DEFAULT_MSG
40
+ opt :title, "The title/subject to attach to messages", :short => 't', :type => String, :default => DEFAULT_TITLE
41
+ opt :conf_file, "Alternate location of config file (default: #{DEFAULT_CONF_PATH})", :short => 'c', :type => String
42
+ end
43
+ Trollop::die :conf_file, "must exist" unless File.exist?(opts[:conf_file]) if opts[:conf_file]
44
+
45
+ unless opts[:conf_file] || File.exist?(File.expand_path(DEFAULT_CONF_PATH))
46
+ puts "No cacophony config file found at #{DEFAULT_CONF_PATH}."
47
+ print "Would you like me to create a sample config file at #{DEFAULT_CONF_PATH} for you? (y/n):"
48
+ if $stdin.getc == 'y'
49
+ puts "Copying sample to #{DEFAULT_CONF_PATH}."
50
+ FileUtils.cp(File.join(File.dirname(THIS_FILE), '..', 'config', 'cacophony_sample.yaml'), File.expand_path(DEFAULT_CONF_PATH))
51
+ puts "Please edit this file to configure cacophony, and run again."
52
+ exit
53
+ end
54
+ end
55
+
56
+
57
+ CONF_FILE_PATH = opts[:conf_file] || File.join(File.expand_path('~'), '.cacophony')
58
+ begin
59
+ CONFIG = YAML.load_file(CONF_FILE_PATH)
60
+ rescue
61
+ Trollop::die "could not load config file: #{CONF_FILE_PATH}"
62
+ end
63
+
64
+ output = []
65
+
66
+
67
+ if STDIN.fcntl(Fcntl::F_GETFL, 0) == 0
68
+ ARGF.each do |line|
69
+ puts line
70
+ output << line
71
+ end
72
+ else
73
+ #output << ''
74
+ end
75
+
76
+ message = (opts[:message] == DEFAULT_MSG && m = ARGV.shift) ? m : opts[:message]
77
+ title = opts[:title]
78
+
79
+ notifer = Cacophony::Notifier.new(CONFIG)
80
+ notifer.notify(title, message, output)
data/cacophony.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "cacophony/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "cacophony"
7
+ s.version = Cacophony::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Dave Lyons"]
10
+ s.email = ["dalyons@gmail.com"]
11
+ s.homepage = "http://www.loadedfingers.com"
12
+ s.summary = %q{Broadcast messages from programs and the command line}
13
+ s.description = %q{see summary}
14
+
15
+ #s.rubyforge_project = "cacophony"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency('trollop')
23
+ end
@@ -0,0 +1,19 @@
1
+ #Cacophony sample config.
2
+ #Each availible notifier type is listed here, along with its options.
3
+ #To enable a notifier, uncomment it and set the options you require.
4
+
5
+ ##Growl notifer uses growl.
6
+ ##Please ensure 'Listen for availible notifications' and 'allow remote application registration' are ticked in System Preferences->Growl.
7
+ #growl_notifier:
8
+ # use_growl_gem: false
9
+ # sticky: true
10
+
11
+ ##Email notifier sends emails, below is a sample config for sending via gmail
12
+ #email_notifier:
13
+ # server: smtp.gmail.com
14
+ # port: 587
15
+ # tls: true
16
+ # username: USERNAME
17
+ # password: PASSWORD
18
+ # to_address: [addy1@gmail.com, addy2@somewhere.com]
19
+ # from_address: cacophony@test.com
@@ -0,0 +1,3 @@
1
+ module Cacophony
2
+ VERSION = "0.0.2"
3
+ end
data/lib/cacophony.rb ADDED
@@ -0,0 +1,34 @@
1
+ #require all the notifiers
2
+ require 'cacophony/version'
3
+ Dir.glob(File.join(File.dirname(__FILE__), 'notifiers', '*.rb')) {|f| require f}
4
+
5
+
6
+ module Cacophony
7
+ class Notifier
8
+
9
+ def initialize(conf)
10
+ raise 'need configuration hash' unless conf.is_a?(Hash) && conf.any?
11
+ @conf = conf
12
+ end
13
+
14
+ def notify(title, message, data)
15
+
16
+ threads = []
17
+ @conf.each do |notifier_type, opts|
18
+ begin
19
+ klass = Object.const_get(notifier_type.split('_').map(&:capitalize).join)
20
+ rescue
21
+ raise "Invalid configuration option(s): #{notifier_type}"
22
+ end
23
+
24
+ threads << Thread.new do
25
+ notifier = klass.new(opts || {} )
26
+ puts "Cacophony broadcasting via #{notifier_type.split('_').map(&:capitalize).join(' ')}"
27
+ notifier.notify(message, title, data)
28
+ end
29
+ end
30
+
31
+ threads.each{|t| t.join}
32
+ end
33
+ end
34
+ end
data/lib/growlnotify ADDED
Binary file
@@ -0,0 +1,47 @@
1
+
2
+ require 'net/smtp'
3
+
4
+
5
+ class EmailNotifier
6
+
7
+ def initialize(opts={})
8
+ @opts = opts
9
+ @from = opts['from'] || "Your sentient shell <shell@donotfearus.com>"
10
+ @to = opts['to'] || "Puny human"
11
+ @subject = opts['subject'] || "Job Complete"
12
+ @server = opts['server'] || 'localhost'
13
+ @port = opts['port'] || 25
14
+ @username = opts['username'] || nil
15
+ @password = opts['password'] || nil
16
+ @method = opts['method'] || :plain
17
+ @to_addresses = opts['to_address'].to_a
18
+ @from_address = opts['from_address'] || ''
19
+ @tls = opts['tls'] || false
20
+
21
+ end
22
+
23
+ def notify(message, title, data)
24
+
25
+ details = message.dup
26
+ details << "\n" + (data.any? ? "Last #{RESULTS_SIZE} lines...\n\n#{data.last(50).join}" : "No output.")
27
+
28
+ @to_addresses.each do |address|
29
+
30
+ msg = <<MESSAGE_END
31
+ From: #{@from}
32
+ To: #{@to}
33
+ Subject: #{title}: #{@subject}
34
+
35
+ #{details}
36
+
37
+ MESSAGE_END
38
+
39
+ smtp = Net::SMTP.new @server, @port
40
+ smtp.enable_starttls if @tls
41
+ smtp.start(@server, @username, @password, @method.to_sym) do
42
+ smtp.send_message(msg, @from_address, address)
43
+ end
44
+ end
45
+ end
46
+
47
+ end
@@ -0,0 +1,38 @@
1
+ begin
2
+ require 'ruby-growl'
3
+ GROWL_GEM = true
4
+ rescue LoadError
5
+ GROWL_GEM = false
6
+ end
7
+
8
+ class GrowlNotifier
9
+ def initialize(opts = {})
10
+ @server = opts['server'] || '127.0.0.1'
11
+ @sticky = opts['sticky'] || false
12
+ @use_growl_gem = opts['use_growl_gem'] == false ? false : true
13
+ @output_lines = opts['output_lines'] || 2
14
+ end
15
+
16
+ def notify(message, title = '', data = [])
17
+ msg = message.dup
18
+ if data.any?
19
+ msg << "\n\n"
20
+ #msg << "......#{data.length - @output_lines} more lines\n"
21
+ #(@output_lines - 1).downto(0).each{|i| msg << "#{data.length - i}: #{data[i]}"}
22
+ data.last(@output_lines).each_with_index{|line,i| msg << "#{data.length - i}: #{line}"}
23
+ msg << "......#{data.length - @output_lines} more lines"
24
+ end
25
+ (@use_growl_gem && GROWL_GEM) ? notify_via_gem(msg, title) : notify_via_binary(msg, title)
26
+ end
27
+
28
+ private
29
+ def notify_via_gem(message, title)
30
+ growl = Growl.new "127.0.0.1", "ruby-growl",["ruby-growl_Notification"]
31
+ growl.notify "ruby-growl_Notification", title, message
32
+ end
33
+
34
+ def notify_via_binary(message, title)
35
+ growl_bin = File.join(GEM_PATH, 'bin', 'growlnotify')
36
+ system %{#{growl_bin} -m "#{msg}" "#{title}" #{"-s" if @sticky}}
37
+ end
38
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cacophony
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.2
6
+ platform: ruby
7
+ authors:
8
+ - Dave Lyons
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-02-09 00:00:00 +11:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: trollop
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ description: see summary
28
+ email:
29
+ - dalyons@gmail.com
30
+ executables:
31
+ - cacophony
32
+ extensions: []
33
+
34
+ extra_rdoc_files: []
35
+
36
+ files:
37
+ - .gitignore
38
+ - Gemfile
39
+ - README.rdoc
40
+ - Rakefile
41
+ - bin/cacophony
42
+ - cacophony.gemspec
43
+ - config/cacophony_sample.yaml
44
+ - lib/cacophony.rb
45
+ - lib/cacophony/version.rb
46
+ - lib/growlnotify
47
+ - lib/notifiers/email_notifier.rb
48
+ - lib/notifiers/growl_notifier.rb
49
+ has_rdoc: true
50
+ homepage: http://www.loadedfingers.com
51
+ licenses: []
52
+
53
+ post_install_message:
54
+ rdoc_options: []
55
+
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ requirements: []
71
+
72
+ rubyforge_project:
73
+ rubygems_version: 1.5.0
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: Broadcast messages from programs and the command line
77
+ test_files: []
78
+