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.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.markdown +48 -0
- data/Rakefile +1 -0
- data/firejab.gemspec +26 -0
- data/lib/firejab.rb +2 -0
- data/lib/firejab/connection.rb +166 -0
- data/lib/firejab/version.rb +3 -0
- metadata +131 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.markdown
ADDED
|
@@ -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 |
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/firejab.gemspec
ADDED
|
@@ -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
|
data/lib/firejab.rb
ADDED
|
@@ -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
|
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
|
+
|