firejab 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in firejab.gemspec
4
+ gemspec
@@ -0,0 +1,48 @@
1
+ Firejab
2
+ =====
3
+
4
+ Firejab is a simple gem for connecting Campfire to Jabber. All communication is through a Jabber (or gchat) user.
5
+
6
+ Overview
7
+ -----
8
+
9
+ All Firejab needs to function is the site and room id for Campfire, and authentication information for both Campfire and Jabber. It just takes two lines to run the bot:
10
+
11
+ ``` ruby
12
+ c = Firejab::Connection.new(
13
+ :domain => campfire_domain,
14
+ :room_id => campfire_room_id,
15
+ :token => campfire_token,
16
+ :jabber => {
17
+ :username => jabber_email,
18
+ :password => jabber_password
19
+ }
20
+ )
21
+
22
+ c.run
23
+ ```
24
+
25
+ The first time a user communicates with Firejab, it will request an authentication token. If you would like to add one manually (for testing purposes), there's a public `add_token` method:
26
+
27
+ ``` ruby
28
+ c.add_token(jabber_email, campfire_token)
29
+ ```
30
+
31
+ TODO
32
+ -----
33
+
34
+ * Persistent store of user authentication information
35
+ * Support for multiple rooms or rooms defined by user
36
+ * Verify that token is valid and lookup user data
37
+ Eventually will probably have to make a CampfireUser class to handle this easily/gracefully
38
+ * Make HTTP requests within EventMachine async
39
+ * Presence notifications
40
+ * Utility commands like /who
41
+ * Properly handle subscription requests
42
+ * Error handling/reconnects
43
+ * Jabber disconnects when I send this: "I can probably dig up the old VB code... ;)"
44
+
45
+ Proposed Schema
46
+ -----
47
+
48
+ | jabber_username | campfire_token | campfire_uid | campfire_name |
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "firejab/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "firejab"
7
+ s.version = Firejab::VERSION
8
+ s.authors = ["Damon P. Cortesi"]
9
+ s.email = ["d.lifehacker@gmail.com"]
10
+ s.homepage = "https://github.com/dacort/firejab"
11
+ s.summary = %q{Jabber interface for Campfire}
12
+ s.description = %q{A simple Jabber bot that shuttles messages between Jabber and Campfire}
13
+
14
+ s.rubyforge_project = "firejab"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+
22
+ s.add_dependency "twitter-stream", "~> 0.1.14"
23
+ s.add_dependency "scashin133-xmpp4r-simple", "~> 0.8.9" # 1.9.x compat
24
+ s.add_dependency "yajl-ruby", "~> 0.8.2"
25
+ s.add_dependency "typhoeus", "~> 0.2.4"
26
+ end
@@ -0,0 +1,2 @@
1
+ require "firejab/version"
2
+ require "firejab/connection"
@@ -0,0 +1,166 @@
1
+ require 'twitter/json_stream'
2
+ require 'xmpp4r-simple'
3
+ require 'yajl'
4
+ require 'typhoeus'
5
+
6
+ module Firejab
7
+ class Connection
8
+ attr_accessor :be_noisy
9
+ attr_accessor :campfire, :campfire_uids, :campfire_options, :campfire_domain, :campfire_room_id
10
+ attr_accessor :jabber, :jabber_users
11
+
12
+ def initialize(params)
13
+ self.jabber = Jabber::Simple.new(params[:jabber][:username], params[:jabber][:password])
14
+
15
+ self.campfire_options = {
16
+ :path => "/room/#{params[:room_id]}/live.json",
17
+ :host => 'streaming.campfirenow.com',
18
+ :auth => "#{params[:token]}:x"
19
+ }
20
+ self.campfire_room_id = params[:room_id]
21
+ self.campfire_domain = params[:domain]
22
+ self.be_noisy = false
23
+
24
+ # Load known tokens for our users from a "database"
25
+ self.jabber_users = {}
26
+ self.campfire_uids = {}
27
+ end
28
+
29
+ def add_token(jabber_username, campfire_token)
30
+ self.jabber_users[jabber_username] ||= {}
31
+ self.jabber_users[jabber_username][:campfire_token] = campfire_token
32
+ end
33
+
34
+ def run
35
+ EM.run do
36
+ self.campfire = Twitter::JSONStream.connect(self.campfire_options)
37
+
38
+ # Tell us what to do when we receive a campfire message
39
+ self.campfire.each_item do |item|
40
+ puts "Received a new message from campfire: #{item}"
41
+ status = Yajl::Parser.parse(item)
42
+ # For ppl that are connected and(?) we have tokens for, send the msg
43
+ case status["type"]
44
+ when "TextMessage", "PasteMessage"
45
+ send_message_to_jabber_users(status['user_id'], status['body'])
46
+ when "UploadMessage"
47
+ #TODO: Retrieve full URL from `GET /room/#{id}/messages/#{upload_message_id}/upload.json`
48
+ send_message_to_jabber_users(status['user_id'], "Uploaded #{status['body']}")
49
+ when "EnterMessage"
50
+ send_message_to_jabber_users(status['user_id'], "Has entered the room!") if self.be_noisy
51
+ when "LeaveMessage", "KickMessage"
52
+ send_message_to_jabber_users(status['user_id'], "Has left the room.") if self.be_noisy
53
+ end
54
+ end
55
+
56
+ self.campfire.on_error do |message|
57
+ puts "Received a campfire error: #{message}"
58
+ end
59
+
60
+ self.campfire.on_max_reconnects do |timeout, retries|
61
+ puts "Fatal error with campfire, you'll need to restart"
62
+ end
63
+
64
+ EM::PeriodicTimer.new(1) do
65
+ check_jabber_connection
66
+
67
+ self.jabber.received_messages do |message|
68
+ # Removes "/resource"
69
+ jabber_username = message.from.strip
70
+
71
+ if is_valid_user(jabber_username)
72
+ send_message_to_campfire(jabber_username, message.body)
73
+ elsif message.body.match(/^\w{40}$/)
74
+ # We received an auth token
75
+ add_token(jabber_username, message.body)
76
+ #TODO: Verify token and lookup_campfire_uid
77
+ send_jabber_message(jabber_username, "Heloooooo!")
78
+ else
79
+ # We don't know who this is, ask for their token
80
+ send_jabber_message(jabber_username, "Hi! I don't know who you are, please send me your auth token from: https://#{self.campfire_domain}/member/edit")
81
+ end
82
+ end
83
+
84
+ self.jabber.presence_updates do |friend, presence, message|
85
+ # presence may be one of [:online, :unavailable, :away]
86
+ # puts "Received presence update from #{friend.inspect}: #{presence.inspect} => #{message.inspect}"
87
+ #TODO: Update room presence accordingly - POST /room/#{id}/[join,leave].json
88
+ set_status(friend, presence)
89
+ end
90
+
91
+ self.jabber.new_subscriptions do |friend, presence|
92
+ puts "New subscription request: #{friend.inspect}"
93
+ # self.jabber.add(friend['jid'])
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ private
100
+ def is_valid_user(jabber_username)
101
+ !(self.jabber_users[jabber_username].nil? or self.jabber_users[jabber_username][:campfire_token].nil?)
102
+ end
103
+
104
+ def check_jabber_connection
105
+ if !self.jabber.connected?
106
+ puts "Reconnecting to Jabber"
107
+ self.jabber.reconnect
108
+ end
109
+ end
110
+
111
+ def send_jabber_message(jid, message)
112
+ # TODO: Possibly make sure format is correct here
113
+ self.jabber.deliver(jid, message)
114
+ end
115
+
116
+ def send_message_to_jabber_users(from_uid, message)
117
+ self.jabber_users.each do |jid, jid_info|
118
+ next if jid_info[:status] == :unavailable
119
+ next if jid_info[:campfire_uid] == from_uid rescue false
120
+
121
+ send_jabber_message(jid, "#{campfire_name(from_uid)}: #{message}")
122
+ end
123
+ end
124
+
125
+ def send_message_to_campfire(from_jid, message)
126
+ jabber_username = from_jid.to_s.split("/").first
127
+ campfire_token = lookup_token(jabber_username)
128
+ #TODO: raise an error if nil
129
+
130
+ response = Typhoeus::Request.post("https://#{self.campfire_domain}/room/#{self.campfire_room_id}/speak.json",
131
+ :body => Yajl::Encoder.encode({:message => {:body => message}}),
132
+ :username => self.campfire_options[:auth].split(":").first, :password => "x",
133
+ :headers => {"Content-type" => "application/json"}
134
+ )
135
+
136
+ campfire_uid = Yajl::Parser.parse(response.body)['message']['user_id']
137
+ set_campfire_uid_on_jabber_user(jabber_username, campfire_uid)
138
+ end
139
+
140
+
141
+ def lookup_token(jabber_username)
142
+ self.jabber_users[jabber_username][:campfire_token] rescue nil
143
+ end
144
+
145
+ def set_status(jabber_username, status)
146
+ self.jabber_users[jabber_username] ||= {}
147
+ self.jabber_users[jabber_username][:status] = status
148
+ end
149
+
150
+ def set_campfire_uid_on_jabber_user(jabber_username, campfire_uid)
151
+ self.jabber_users[jabber_username] ||= {}
152
+ self.jabber_users[jabber_username][:campfire_uid] = campfire_uid
153
+ end
154
+
155
+ def campfire_name(campfire_uid)
156
+ self.campfire_uids[campfire_uid] ||= Yajl::Parser.parse(
157
+ Typhoeus::Request.get("https://#{self.campfire_domain}/users/#{campfire_uid}.json",
158
+ :username => self.campfire_options[:auth].split(":").first, :password => "x"
159
+ ).body
160
+ )['user']
161
+
162
+ self.campfire_uids[campfire_uid]['name']
163
+ end
164
+
165
+ end
166
+ end
@@ -0,0 +1,3 @@
1
+ module Firejab
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: firejab
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Damon P. Cortesi
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-09-07 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: twitter-stream
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ - 1
31
+ - 14
32
+ version: 0.1.14
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: scashin133-xmpp4r-simple
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ segments:
44
+ - 0
45
+ - 8
46
+ - 9
47
+ version: 0.8.9
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: yajl-ruby
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ~>
57
+ - !ruby/object:Gem::Version
58
+ segments:
59
+ - 0
60
+ - 8
61
+ - 2
62
+ version: 0.8.2
63
+ type: :runtime
64
+ version_requirements: *id003
65
+ - !ruby/object:Gem::Dependency
66
+ name: typhoeus
67
+ prerelease: false
68
+ requirement: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ~>
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ - 2
76
+ - 4
77
+ version: 0.2.4
78
+ type: :runtime
79
+ version_requirements: *id004
80
+ description: A simple Jabber bot that shuttles messages between Jabber and Campfire
81
+ email:
82
+ - d.lifehacker@gmail.com
83
+ executables: []
84
+
85
+ extensions: []
86
+
87
+ extra_rdoc_files: []
88
+
89
+ files:
90
+ - .gitignore
91
+ - Gemfile
92
+ - README.markdown
93
+ - Rakefile
94
+ - firejab.gemspec
95
+ - lib/firejab.rb
96
+ - lib/firejab/connection.rb
97
+ - lib/firejab/version.rb
98
+ has_rdoc: true
99
+ homepage: https://github.com/dacort/firejab
100
+ licenses: []
101
+
102
+ post_install_message:
103
+ rdoc_options: []
104
+
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ segments:
113
+ - 0
114
+ version: "0"
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ segments:
121
+ - 0
122
+ version: "0"
123
+ requirements: []
124
+
125
+ rubyforge_project: firejab
126
+ rubygems_version: 1.3.7
127
+ signing_key:
128
+ specification_version: 3
129
+ summary: Jabber interface for Campfire
130
+ test_files: []
131
+