cacophony 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/README.rdoc +35 -0
- data/Rakefile +2 -0
- data/bin/cacophony +80 -0
- data/cacophony.gemspec +23 -0
- data/config/cacophony_sample.yaml +19 -0
- data/lib/cacophony/version.rb +3 -0
- data/lib/cacophony.rb +34 -0
- data/lib/growlnotify +0 -0
- data/lib/notifiers/email_notifier.rb +47 -0
- data/lib/notifiers/growl_notifier.rb +38 -0
- metadata +78 -0
data/Gemfile
ADDED
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
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
|
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
|
+
|