firejab 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.
@@ -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
+