messenger 0.0.1

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.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Brandon Arbini / Zencoder, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,2 @@
1
+ Messenger
2
+ ========
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 0
4
+ :patch: 1
data/bin/messenger ADDED
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib_dir = File.join(File.dirname(__FILE__), '..', 'lib')
4
+ $LOAD_PATH.unshift lib_dir if File.directory?(lib_dir)
5
+
6
+ require 'messenger'
7
+ require 'trollop'
8
+ require 'yaml'
9
+
10
+
11
+ #-------------------------------------
12
+ # Support
13
+ #-------------------------------------
14
+
15
+ class Hash
16
+
17
+ def symbolize_keys
18
+ inject({}) do |options, (key, value)|
19
+ options[(key.to_sym rescue key) || key] = value
20
+ options
21
+ end
22
+ end
23
+
24
+ def symbolize_keys!
25
+ self.replace(self.symbolize_keys)
26
+ end
27
+
28
+ end
29
+
30
+
31
+ #
32
+ # Configure options
33
+ #
34
+
35
+ if File.exists?(File.expand_path("~/.messenger"))
36
+ options = YAML.load_file(File.expand_path("~/.messenger")).symbolize_keys!
37
+ else
38
+ options = {}
39
+ end
40
+
41
+ trollop_options = Trollop::options do
42
+ version "Messenger #{Messenger.version} (c) Zencoder Inc. All rights reserved, etc."
43
+ banner <<-EOS
44
+ Messenger makes sending messages easy.
45
+
46
+ Usage:
47
+ script/messenger [options] <service> <message>
48
+
49
+ Where [options] are:
50
+ EOS
51
+
52
+ # Global options
53
+ opt :timeout, "The number of seconds to allow for the call", :type => Integer
54
+
55
+ # Email options
56
+ opt :from, "Who the message is from (email).", :type => String
57
+ opt :subject, "The message subject (email).", :type => String
58
+
59
+ # Jabber options
60
+ opt :jabber_id, "The jabber ID to connect as (user@example.com)", :type => String
61
+ opt :jabber_password, "The password for your jabber id", :type => String
62
+
63
+ # CLI options
64
+ opt :silent, "Don't print anything to stdout", :default => false
65
+ opt :verbose, "Print verbose output on success", :default => false
66
+ end
67
+
68
+ options.merge!(trollop_options.reject{|k,v| v.nil?})
69
+
70
+ #
71
+ # Validate input
72
+ #
73
+
74
+ if ARGV[0].nil? || ARGV[1].nil?
75
+ puts <<-EOS
76
+ Error: no service or message specified.
77
+
78
+ Usage (--help for more):
79
+
80
+ script/messenger [options] <service> <message>
81
+
82
+ EOS
83
+ exit -1
84
+ end
85
+
86
+
87
+ #
88
+ # Run Messenger
89
+ #
90
+ puts "# Sending message to #{ARGV[0]}"
91
+ begin
92
+ status, details = Messenger.send(ARGV[0], ARGV[1], options)
93
+ if !!status
94
+ puts "# Message sent successfully"
95
+ else
96
+ puts "# Message not sent"
97
+ puts "# Details:"
98
+ puts details
99
+ end
100
+ rescue => e
101
+ puts "# **Error** #{e}"
102
+ puts e.backtrace
103
+ end
@@ -0,0 +1,36 @@
1
+ require 'httparty'
2
+ require 'json'
3
+
4
+ module Messenger
5
+
6
+ class Campfire
7
+
8
+ def self.send(url, body, options={})
9
+ begin
10
+ api_key, room, subdomain = url.match(/^campfire:\/\/([^:]+):([^@]+)@([^\.]+)/)[1,3]
11
+ rescue
12
+ raise URLError, "The URL provided is invalid"
13
+ end
14
+ response = HTTParty.post(
15
+ "http://#{subdomain}.campfirenow.com/room/#{room}/speak.json",
16
+ :basic_auth => { :username => api_key, :password => "x" },
17
+ :headers => { "Content-Type" => "application/json" },
18
+ :body => { "message" => { "body" => body } }.to_json
19
+ )
20
+ [success?(response), response]
21
+ end
22
+
23
+
24
+ private
25
+
26
+ def self.success?(response)
27
+ case response.code
28
+ when 200, 201: true
29
+ else
30
+ false
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,19 @@
1
+ require 'pony'
2
+
3
+ module Messenger
4
+
5
+ class Email
6
+
7
+ def self.send(url, message, options={})
8
+ Pony.mail(
9
+ :to => url.sub(/mailto:/, ''),
10
+ :from => options[:from],
11
+ :subject => options[:subject],
12
+ :body => message
13
+ )
14
+ [true, nil]
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,7 @@
1
+ module Messenger
2
+
3
+ class MessengerError < StandardError; end
4
+ class ProtocolError < MessengerError; end
5
+ class URLError < MessengerError; end
6
+
7
+ end
@@ -0,0 +1,68 @@
1
+ require 'xmpp4r-simple'
2
+
3
+ module Messenger
4
+
5
+ class Jabber
6
+
7
+ def self.send(url, body, options={})
8
+ recipient, host = url.sub("jabber://", "").split("/")[0,2]
9
+ jabber = ::Jabber::Simple.new(options[:jabber_id], options[:jabber_password], host)
10
+ jabber.deliver(recipient, body)
11
+ pending_messages_count = 1
12
+ until pending_messages_count == 0
13
+ pending_messages_count = jabber.send(:queue, :pending_messages).size
14
+ sleep 1
15
+ end
16
+ status = jabber.subscribed_to?(recipient)
17
+ [status, status ? nil : "Not yet authorized"]
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+
24
+
25
+ # MONKEY PATCHING
26
+ #
27
+ # xmpp4r-simple does not allow you to specify the jabber host, but we need to do that for Google Apps.
28
+
29
+ module Jabber
30
+
31
+ class Simple
32
+
33
+ def initialize(jid, password, host=nil, status=nil, status_message="Available")
34
+ @jid = jid
35
+ @password = password
36
+ @host = host
37
+ @disconnected = false
38
+ status(status, status_message)
39
+ start_deferred_delivery_thread
40
+ end
41
+
42
+ def connect!
43
+ raise ConnectionError, "Connections are disabled - use Jabber::Simple::force_connect() to reconnect." if @disconnected
44
+ # Pre-connect
45
+ @connect_mutex ||= Mutex.new
46
+
47
+ # don't try to connect if another thread is already connecting.
48
+ return if @connect_mutex.locked?
49
+
50
+ @connect_mutex.lock
51
+ disconnect!(false) if connected?
52
+
53
+ # Connect
54
+ jid = JID.new(@jid)
55
+ my_client = Client.new(@jid)
56
+ my_client.connect(@host)
57
+ my_client.auth(@password)
58
+ self.client = my_client
59
+
60
+ # Post-connect
61
+ register_default_callbacks
62
+ status(@presence, @status_message)
63
+ @connect_mutex.unlock
64
+ end
65
+
66
+ end
67
+
68
+ end
@@ -0,0 +1,24 @@
1
+ require 'httparty'
2
+
3
+ module Messenger
4
+
5
+ class Web
6
+
7
+ def self.send(url, body, options={})
8
+ response = HTTParty.post(url, options.merge(:body => body))
9
+ [success?(response), response]
10
+ end
11
+
12
+ private
13
+
14
+ def self.success?(response)
15
+ case response.code
16
+ when 200, 201: true
17
+ else
18
+ false
19
+ end
20
+ end
21
+
22
+ end
23
+
24
+ end
data/lib/messenger.rb ADDED
@@ -0,0 +1,61 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'ruby-debug'
5
+ require 'messenger/errors'
6
+ require 'system_timer'
7
+
8
+
9
+ module Messenger
10
+
11
+ MESSAGER_VERSION = [0,1] unless defined?(MESSAGER_VERSION)
12
+ APP_ROOT = File.expand_path(File.dirname(__FILE__) + '/..') unless defined?(APP_ROOT)
13
+
14
+ def self.version
15
+ MESSAGER_VERSION.join(".")
16
+ end
17
+
18
+ def self.root
19
+ APP_ROOT
20
+ end
21
+
22
+
23
+ def self.send(url, message, options={})
24
+ service_handler = handler(url)
25
+ SystemTimer.timeout_after(options[:timeout] || 15) do
26
+ service_handler.send(url, message, options)
27
+ end
28
+ end
29
+
30
+
31
+ def self.protocol(url)
32
+ # TODO: More services
33
+ # sms://1231231234
34
+ # twitter://username
35
+ # aim://username
36
+ case url
37
+ when /^mailto/: :email
38
+ when /^http/: :http
39
+ when /^campfire/: :campfire
40
+ when /^jabber/: :jabber
41
+ end
42
+ end
43
+
44
+ def self.handler(url)
45
+ case protocol(url)
46
+ when :email: Email
47
+ when :http: Web
48
+ when :campfire: Campfire
49
+ when :jabber: Jabber
50
+ else
51
+ raise ProtocolError, "Malformed service URL: #{url}. Either this syntax is wrong or this service type is not yet implemented."
52
+ end
53
+ end
54
+
55
+
56
+ autoload :Email, "messenger/email"
57
+ autoload :Web, "messenger/web"
58
+ autoload :Campfire, "messenger/campfire"
59
+ autoload :Jabber, "messenger/jabber"
60
+
61
+ end
@@ -0,0 +1,35 @@
1
+ require "#{File.dirname(__FILE__)}/test_helper"
2
+ require 'httparty'
3
+
4
+ module Messenger
5
+
6
+ class CampfireTest < Test::Unit::TestCase
7
+
8
+ context "Campfire notification" do
9
+ setup do
10
+ @success_response = stub("response", :code => 200)
11
+ @failure_response = stub("response", :code => 500)
12
+ end
13
+
14
+ should "post a successful message" do
15
+ HTTParty.expects(:post).with("http://subdomain.campfirenow.com/room/room/speak.json", :basic_auth => { :username => 'api', :password => 'x' }, :body => '{"message":{"body":"content"}}', :headers => { "Content-Type" => "application/json" }).returns(@success_response)
16
+ result = Campfire.send("campfire://api:room@subdomain.campfirewnow.com", 'content')
17
+ assert_equal [true, @success_response], result
18
+ end
19
+
20
+ should "post a failed message" do
21
+ HTTParty.expects(:post).with("http://subdomain.campfirenow.com/room/room/speak.json", :basic_auth => { :username => 'api', :password => 'x' }, :body => '{"message":{"body":"content"}}', :headers => { "Content-Type" => "application/json" }).returns(@failure_response)
22
+ result = Campfire.send("campfire://api:room@subdomain.campfirewnow.com", 'content')
23
+ assert_equal [false, @failure_response], result
24
+ end
25
+
26
+ should "raise on invalid URL" do
27
+ assert_raises Messenger::URLError do
28
+ Campfire.send("campfire://missing_room@subdomain.campfirewnow.com", 'content')
29
+ end
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,17 @@
1
+ require "#{File.dirname(__FILE__)}/test_helper"
2
+ require 'pony'
3
+
4
+ module Messenger
5
+
6
+ class EmailTest < Test::Unit::TestCase
7
+
8
+ context "Email notification" do
9
+ should "send an email" do
10
+ Pony.expects(:mail).with(:to => "test@example.com", :body => "Test message", :from => "test@example.com", :subject => "Test")
11
+ Email.send("mailto:test@example.com", "Test message", :from => "test@example.com", :subject => "Test")
12
+ end
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,6 @@
1
+ require "#{File.dirname(__FILE__)}/../lib/messenger"
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+
6
+ Dir["#{File.dirname(__FILE__)}/shoulda_macros/*.rb"].each {|file| require file }
@@ -0,0 +1,35 @@
1
+ require "#{File.dirname(__FILE__)}/test_helper"
2
+ require 'xmpp4r-simple'
3
+
4
+ module Messenger
5
+
6
+ class JabberTest < Test::Unit::TestCase
7
+
8
+ context "Jabber notification" do
9
+ setup do
10
+ @successful_jabber = stub("jabber", :deliver => nil, :queue => stub("queue", :size => 0), :subscribed_to? => true)
11
+ @failed_jabber = stub("jabber", :deliver => nil, :queue => stub("queue", :size => 0), :subscribed_to? => false)
12
+ end
13
+
14
+ should "send a successful jabber message" do
15
+ ::Jabber::Simple.expects(:new).with("notifier@zencoder.com", "asdfasdf", nil).returns(@successful_jabber)
16
+ result = Jabber.send("jabber://brandon@zencoder.com", "Test message", :jabber_id => "notifier@zencoder.com", :jabber_password => "asdfasdf")
17
+ assert_equal [true, nil], result
18
+ end
19
+
20
+ should "determine and set the jabber host" do
21
+ ::Jabber::Simple.expects(:new).with("notifier@zencoder.com", "asdfasdf", "host.com").returns(@successful_jabber)
22
+ result = Jabber.send("jabber://brandon@zencoder.com/host.com", "Test message", :jabber_id => "notifier@zencoder.com", :jabber_password => "asdfasdf")
23
+ assert_equal [true, nil], result
24
+ end
25
+
26
+ should "fail if the recipient is not subscribed" do
27
+ ::Jabber::Simple.expects(:new).with("notifier@zencoder.com", "asdfasdf", nil).returns(@failed_jabber)
28
+ result = Jabber.send("jabber://brandon@zencoder.com", "Test message", :jabber_id => "notifier@zencoder.com", :jabber_password => "asdfasdf")
29
+ assert_equal [false, "Not yet authorized"], result
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,23 @@
1
+ require "#{File.dirname(__FILE__)}/test_helper"
2
+
3
+ module Messenger
4
+
5
+ class MessengerTest < Test::Unit::TestCase
6
+
7
+ context "Protocol/Handler" do
8
+ should "determine the proper service" do
9
+ assert_equal :email, Messenger.protocol("mailto:test@example.com")
10
+ assert_equal :http, Messenger.protocol("http://example.com")
11
+ assert_equal :http, Messenger.protocol("https://example.com")
12
+ end
13
+
14
+ should "determine the proper notification handler given a protocol" do
15
+ assert_equal Email, Messenger.handler("mailto:test@example.com")
16
+ assert_equal Web, Messenger.handler("http://example.com")
17
+ assert_equal Web, Messenger.handler("https://example.com")
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ end
data/test/test_web.rb ADDED
@@ -0,0 +1,29 @@
1
+ require "#{File.dirname(__FILE__)}/test_helper"
2
+ require 'httparty'
3
+
4
+ module Messenger
5
+
6
+ class WebTest < Test::Unit::TestCase
7
+
8
+ context "Web notification" do
9
+ setup do
10
+ @success_response = stub("response", :code => 200)
11
+ @failure_response = stub("response", :code => 500)
12
+ end
13
+
14
+ should "post a successful message" do
15
+ HTTParty.expects(:post).with("http://example.com", :body => '{ "key": "value" }', :headers => { "Content-Type" => "application/json" }).returns(@success_response)
16
+ result = Web.send("http://example.com", '{ "key": "value" }', :headers => { "Content-Type" => "application/json" })
17
+ assert_equal [true, @success_response], result
18
+ end
19
+
20
+ should "post a failed message" do
21
+ HTTParty.expects(:post).with("http://example.com", :body => '{ "key": "value" }', :headers => { "Content-Type" => "application/json" }).returns(@failure_response)
22
+ result = Web.send("http://example.com", '{ "key": "value" }', :headers => { "Content-Type" => "application/json" })
23
+ assert_equal [false, @failure_response], result
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ end
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: messenger
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Brandon Arbini
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-04 00:00:00 -08:00
13
+ default_executable: messenger
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: trollop
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "1.15"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: pony
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0.6"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: tmail
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.2.6
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: mime-types
47
+ type: :runtime
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "1.16"
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: httparty
57
+ type: :runtime
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 0.5.2
64
+ version:
65
+ - !ruby/object:Gem::Dependency
66
+ name: SystemTimer
67
+ type: :runtime
68
+ version_requirement:
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 1.1.3
74
+ version:
75
+ - !ruby/object:Gem::Dependency
76
+ name: xmpp4r
77
+ type: :runtime
78
+ version_requirement:
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "="
82
+ - !ruby/object:Gem::Version
83
+ version: "0.5"
84
+ version:
85
+ - !ruby/object:Gem::Dependency
86
+ name: xmpp4r-simple
87
+ type: :runtime
88
+ version_requirement:
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - "="
92
+ - !ruby/object:Gem::Version
93
+ version: 0.8.8
94
+ version:
95
+ - !ruby/object:Gem::Dependency
96
+ name: json_pure
97
+ type: :runtime
98
+ version_requirement:
99
+ version_requirements: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 1.2.0
104
+ version:
105
+ description: "Messenger: easy message sending"
106
+ email: brandon@zencoder.tv
107
+ executables:
108
+ - messenger
109
+ extensions: []
110
+
111
+ extra_rdoc_files:
112
+ - LICENSE
113
+ - README.markdown
114
+ files:
115
+ - README.markdown
116
+ - VERSION.yml
117
+ - lib/messenger.rb
118
+ - lib/messenger/campfire.rb
119
+ - lib/messenger/email.rb
120
+ - lib/messenger/errors.rb
121
+ - lib/messenger/jabber.rb
122
+ - lib/messenger/web.rb
123
+ - test/test_campfire.rb
124
+ - test/test_email.rb
125
+ - test/test_helper.rb
126
+ - test/test_jabber.rb
127
+ - test/test_messenger.rb
128
+ - test/test_web.rb
129
+ - LICENSE
130
+ has_rdoc: true
131
+ homepage: http://github.com/zencoder/messenger
132
+ licenses: []
133
+
134
+ post_install_message:
135
+ rdoc_options:
136
+ - --charset=UTF-8
137
+ require_paths:
138
+ - lib
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: "0"
144
+ version:
145
+ required_rubygems_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: "0"
150
+ version:
151
+ requirements: []
152
+
153
+ rubyforge_project:
154
+ rubygems_version: 1.3.5
155
+ signing_key:
156
+ specification_version: 3
157
+ summary: "Messenger: easy message sending"
158
+ test_files:
159
+ - test/test_campfire.rb
160
+ - test/test_email.rb
161
+ - test/test_helper.rb
162
+ - test/test_jabber.rb
163
+ - test/test_messenger.rb
164
+ - test/test_web.rb