broach 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2009 Manfred Stienstra, Fingertips <manfred@fngtps.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,92 @@
1
+ require 'rubygems' rescue nil
2
+ require 'rest'
3
+ require 'json'
4
+
5
+ require 'broach/exceptions'
6
+
7
+ # === Settings
8
+ #
9
+ # Before you can do anything else you will need to provide credentials first, this includes the account name and
10
+ # authentication token. The +use_ssl+ parameter is optional and defaults to false.
11
+ #
12
+ # Broach.settings = { 'account' => 'example', 'token' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'use_ssl' => true }
13
+ #
14
+ # You can find the token for any Campfire account by logging into the web interface and clicking 'My Info' in the top-right
15
+ # corner.
16
+ #
17
+ # === Say someting in a room real quick
18
+ #
19
+ # If you just need to say something real quick in a room, you can use the speak class method.
20
+ #
21
+ # Broach.speak("Office", "Manfred just deployed a new version of the weblog (http://www.fngtps.com)")
22
+ #
23
+ # Note that this fetches a list of all rooms so it can figure out the ID for the room you specified.
24
+ #
25
+ # === Post a lot of stuff to a room
26
+ #
27
+ # If you want to post multiple lines to one room, it's a good idea to create a Room instance.
28
+ #
29
+ # room = Broach.rooms.find { |room| room.name == 'Office' }
30
+ # room.speak('Manfred just commited to the `weblog' repository')
31
+ # room.speak("commit 4578530113cb87e1e7dbd696c376181e97d429d7\n" +
32
+ # "Author: Manfred Stienstra <manfred@fngtps.com>\n" +
33
+ # "Date: Wed Dec 16 14:03:33 2009 +0100\n\n" +
34
+ # " Add a speak method to Broach to quickly say something in a room.", :type => :paste)
35
+ module Broach
36
+ autoload :Attributes, 'broach/attributes'
37
+ autoload :Session, 'broach/session'
38
+ autoload :User, 'broach/user'
39
+ autoload :Room, 'broach/room'
40
+
41
+ # Returns the current Broach settings
42
+ def self.settings
43
+ @settings
44
+ end
45
+
46
+ # Sets the broach settings
47
+ def self.settings=(settings)
48
+ @settings = settings
49
+ @session = nil
50
+ end
51
+
52
+ # Returns a session object with the current settings
53
+ def self.session
54
+ @session ||= Broach::Session.new(settings)
55
+ end
56
+
57
+ # Returns a User instance for the currently authenticated user
58
+ def self.me
59
+ Broach::User.me
60
+ end
61
+
62
+ # Returns a Room instance for all rooms accesible to the currently authenticated user
63
+ def self.rooms
64
+ Broach::Room.all
65
+ end
66
+
67
+ # Send a message to a room with a certain name.
68
+ #
69
+ # Note that you should only use this method if you're sending just one message. It fetches
70
+ # all rooms before sending the message to find the room with the name you're specifying.
71
+ #
72
+ # If you need to send multiple messages to the same room you should instantiate a room first.
73
+ #
74
+ # ==== Options
75
+ #
76
+ # +room+
77
+ # The name of the room, ie. 'Office'
78
+ # +content+
79
+ # The content of the message, see Broach::Room#speak for more information.
80
+ # +options+
81
+ # Options for the message, see Broach::Room#speak for more information.
82
+ #
83
+ # ==== Examples
84
+ #
85
+ # Broach.speak('Office', 'Manfred just deployed a new version of the weblog (http://www.fngtps.com)')
86
+ # Broach.speak('Office', 'crickets', :type => :sound)
87
+ def self.speak(room_name, content, options={})
88
+ if room = rooms.find { |room| room.name == room_name }
89
+ room.speak(content, options)
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,18 @@
1
+ module Broach
2
+ # Makes a very simple attribute driven model from the class when included.
3
+ module Attributes
4
+ def initialize(attributes)
5
+ @attributes = attributes
6
+ end
7
+
8
+ def id; @attributes['id']; end
9
+
10
+ def method_missing(method, *arguments, &block)
11
+ if value = @attributes[method.to_s]
12
+ value
13
+ else
14
+ super
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ module Broach
2
+ # Raised when something unexpected happened during communication with Campfire
3
+ class APIError < RuntimeError
4
+ attr_accessor :response
5
+ end
6
+
7
+ # Raised when the credentials were incorrect
8
+ class AuthenticationError < APIError; end
9
+
10
+ # Raised when the credentials were correct, but the resource could not be accessed
11
+ class AuthorizationError < APIError; end
12
+ end
@@ -0,0 +1,51 @@
1
+ module Broach
2
+ # Represents a chat room on the server
3
+ class Room
4
+ TYPE_MAP = {
5
+ :text => 'TextMessage',
6
+ :paste => 'PasteMessage',
7
+ :sound => 'SoundMessage'
8
+ }
9
+
10
+ include Broach::Attributes
11
+
12
+ # Send a message to the room
13
+ #
14
+ # ==== Parameters and options
15
+ #
16
+ # [+content+]
17
+ # Content to send. For a normal text message this is the content of the message. For a paste
18
+ # it's the content of the paste. For a sound it's the name of the sound.
19
+ #
20
+ # [<tt>:type</tt>]
21
+ # The type of message to send, this is :text by default for normal text messages.
22
+ # You can also use :paste and :sound. Valid sound messages are 'rimshot', 'crickets',
23
+ # or 'trombone'.
24
+ #
25
+ # ==== Examples
26
+ #
27
+ # room = Broach::Room.all.first
28
+ # room.speak("Let's review these figures.")
29
+ # room.speak("<code>$stderr.write('-')</code>", :type => :paste)
30
+ # room.speak("rimshot", :type => :sound)
31
+ def speak(content, options={})
32
+ options[:type] ||= :text
33
+ Broach.session.post("room/#{id}/speak", 'message' => {
34
+ 'type' => TYPE_MAP[options[:type]],
35
+ 'body' => content
36
+ })['message']
37
+ end
38
+
39
+ # Returns a Room instance for all rooms accessible to the authenticated user
40
+ def self.all
41
+ Broach.session.get('rooms')['rooms'].map do |attributes|
42
+ Broach::Room.new(attributes)
43
+ end
44
+ end
45
+
46
+ # Returns a Room instance for a room with a specific ID
47
+ def self.find(id)
48
+ new(Broach.session.get("room/#{id.to_i}")['room'])
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,73 @@
1
+ module Broach
2
+ # Represents a session with Campfire
3
+ class Session
4
+ include Broach::Attributes
5
+
6
+ # Returns true when the connection should use SSL and false otherwise.
7
+ def use_ssl?
8
+ @attributes['use_ssl'] || false
9
+ end
10
+
11
+ # Returns either http or https depending on whether we should use SSL or not.
12
+ def scheme
13
+ use_ssl? ? 'https' : 'http'
14
+ end
15
+
16
+ # Returns the full URL for a certain path
17
+ #
18
+ # session.url_for('rooms') #=> "http://example.campfirenow.com/rooms"
19
+ def url_for(path)
20
+ ["#{scheme}:/", "#{account}.campfirenow.com", path].join('/')
21
+ end
22
+
23
+ # Returns the headers to send for a specific HTTP method
24
+ #
25
+ # session.headers_for(:get) #=> { 'Accept' => 'application/json' }
26
+ def headers_for(method)
27
+ headers = { 'Accept' => 'application/json', 'User-Agent' => 'Broach' }
28
+ headers['Content-type'] = 'application/json' if method == :post
29
+ headers
30
+ end
31
+
32
+ # Returns the credentials to authenticate the current user
33
+ def credentials
34
+ { :username => token, :password => 'x' }
35
+ end
36
+
37
+ # Gets a resource with a certain path on the server. When the GET is succesful
38
+ # the parsed body is returned, otherwise an exception is raised.
39
+ def get(path)
40
+ response = REST.get(url_for(path), headers_for(:get), credentials)
41
+ if response.ok?
42
+ return JSON.parse(response.body)
43
+ else
44
+ handle_response(:get, path, response)
45
+ end
46
+ end
47
+
48
+ # Posts a resource to a certain path on the server. When the POST is successful
49
+ # the parsed body is returned, otherwise an exception is raised.
50
+ def post(path, payload)
51
+ response = REST.post(url_for(path), JSON.dump(payload), headers_for(:post), credentials)
52
+ if response.created?
53
+ return JSON.parse(response.body)
54
+ else
55
+ handle_response(:post, path, response)
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def handle_response(method, path, response)
62
+ exception = if response.unauthorized?
63
+ Broach::AuthenticationError.new("Couldn't authenticate with the supplied credentials for the account `#{account}'")
64
+ elsif response.forbidden?
65
+ Broach::AuthorizationError.new("Couldn't #{method.to_s.upcase} the resource `#{path}' on the account `#{account}'")
66
+ else
67
+ Broach::APIError.new("Response from the server was unexpected (#{response.status_code})")
68
+ end
69
+ exception.response = response
70
+ raise exception
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,16 @@
1
+ module Broach
2
+ # Represents a user on the server
3
+ class User
4
+ include Broach::Attributes
5
+
6
+ # Returns a User instance for the currently authenticated user
7
+ def self.me
8
+ new(Broach.session.get('users/me')['user'])
9
+ end
10
+
11
+ # Returns a User instance for a user with a specific ID
12
+ def self.find(id)
13
+ new(Broach.session.get("users/#{id.to_i}")['user'])
14
+ end
15
+ end
16
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: broach
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Manfred Stienstra
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-16 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: " Ruby implementation of 37signal's Campfire API.\n"
17
+ email: manfred@fngtps.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ files:
25
+ - LICENSE
26
+ - lib/broach/attributes.rb
27
+ - lib/broach/exceptions.rb
28
+ - lib/broach/room.rb
29
+ - lib/broach/session.rb
30
+ - lib/broach/user.rb
31
+ - lib/broach.rb
32
+ has_rdoc: true
33
+ homepage:
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --charset=utf-8
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ requirements: []
54
+
55
+ rubyforge_project:
56
+ rubygems_version: 1.3.5
57
+ signing_key:
58
+ specification_version: 3
59
+ summary: Ruby implementation of 37signal's Campfire API.
60
+ test_files: []
61
+