wesabot 1.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 +5 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +182 -0
- data/Rakefile +13 -0
- data/bin/wesabot +111 -0
- data/config/wesabot.yml.sample +4 -0
- data/lib/campfire/bot.rb +53 -0
- data/lib/campfire/configuration.rb +65 -0
- data/lib/campfire/message.rb +102 -0
- data/lib/campfire/polling_bot/plugin.rb +162 -0
- data/lib/campfire/polling_bot/plugins/airbrake/.gitignore +1 -0
- data/lib/campfire/polling_bot/plugins/airbrake/airbrake/api.rb +48 -0
- data/lib/campfire/polling_bot/plugins/airbrake/airbrake/error.rb +51 -0
- data/lib/campfire/polling_bot/plugins/airbrake/airbrake_plugin.rb +63 -0
- data/lib/campfire/polling_bot/plugins/airbrake/airbrake_plugin.yml.sample +3 -0
- data/lib/campfire/polling_bot/plugins/bookmark/bookmark.rb +15 -0
- data/lib/campfire/polling_bot/plugins/bookmark/bookmark_plugin.rb +89 -0
- data/lib/campfire/polling_bot/plugins/debug/debug_plugin.rb +23 -0
- data/lib/campfire/polling_bot/plugins/deploy/deploy_plugin.rb +155 -0
- data/lib/campfire/polling_bot/plugins/deploy/deploy_plugin.yml.sample +9 -0
- data/lib/campfire/polling_bot/plugins/deploy/spec/deploy_plugin_spec.rb +153 -0
- data/lib/campfire/polling_bot/plugins/greeting/greeting_plugin.rb +146 -0
- data/lib/campfire/polling_bot/plugins/greeting/greeting_setting.rb +19 -0
- data/lib/campfire/polling_bot/plugins/greeting/spec/greeting_plugin_spec.rb +51 -0
- data/lib/campfire/polling_bot/plugins/greeting/spec/greeting_setting_spec.rb +61 -0
- data/lib/campfire/polling_bot/plugins/help/help_plugin.rb +53 -0
- data/lib/campfire/polling_bot/plugins/history/history_plugin.rb +34 -0
- data/lib/campfire/polling_bot/plugins/image_search/displayed_image.rb +8 -0
- data/lib/campfire/polling_bot/plugins/image_search/image_search_plugin.rb +106 -0
- data/lib/campfire/polling_bot/plugins/interjector/interjector_plugin.rb +58 -0
- data/lib/campfire/polling_bot/plugins/kibitz/kibitz_plugin.rb +90 -0
- data/lib/campfire/polling_bot/plugins/kibitz/spec/kibitz_plugin_spec.rb +56 -0
- data/lib/campfire/polling_bot/plugins/plugin.db +0 -0
- data/lib/campfire/polling_bot/plugins/reload/reload_plugin.rb +24 -0
- data/lib/campfire/polling_bot/plugins/remind_me/remind_me_plugin.rb +149 -0
- data/lib/campfire/polling_bot/plugins/remind_me/reminder.rb +8 -0
- data/lib/campfire/polling_bot/plugins/shared/message.rb +37 -0
- data/lib/campfire/polling_bot/plugins/shared/user.rb +32 -0
- data/lib/campfire/polling_bot/plugins/sms/sms_plugin.rb +88 -0
- data/lib/campfire/polling_bot/plugins/sms/sms_setting.rb +7 -0
- data/lib/campfire/polling_bot/plugins/time/time_plugin.rb +17 -0
- data/lib/campfire/polling_bot/plugins/tweet/tweet.rb +52 -0
- data/lib/campfire/polling_bot/plugins/tweet/tweet_plugin.rb +117 -0
- data/lib/campfire/polling_bot/plugins/tweet/tweet_plugin.yml.sample +4 -0
- data/lib/campfire/polling_bot/plugins/twitter_search/twitter_search_plugin.rb +58 -0
- data/lib/campfire/polling_bot.rb +125 -0
- data/lib/campfire/sample_plugin.rb +56 -0
- data/lib/campfire/version.rb +3 -0
- data/lib/wesabot.rb +3 -0
- data/spec/.gitignore +1 -0
- data/spec/polling_bot_spec.rb +23 -0
- data/spec/spec_helper.rb +190 -0
- data/wesabot.gemspec +55 -0
- metadata +336 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2006-2008 Wesabe
|
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.md
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
# Wesabot
|
2
|
+
|
3
|
+
Wesabot, the Campfire bot framework.
|
4
|
+
|
5
|
+
## Description
|
6
|
+
|
7
|
+
Wesabot is a Campfire bot framework we've been using and developing at Wesabe
|
8
|
+
since not long after our inception. It started as a way to avoid parking tickets
|
9
|
+
near our office ("Wes, remind me in 2 hours to move my car"), and has evolved
|
10
|
+
into an essential work aid. When you enter the room, Wes greets you with a link
|
11
|
+
to the point in the transcript where you last left. You can also ask him to
|
12
|
+
bookmark points in the transcript, send an sms message (well, an email) to
|
13
|
+
someone, or even post a tweet, among other things. His functionality is easily
|
14
|
+
extendable via plugins.
|
15
|
+
|
16
|
+
To give Wes new powers, simply drop a plugin file in the plugins directory and
|
17
|
+
restart Wes (or, via the ReloadPlugin, he can be told to reload himself). See
|
18
|
+
`campfire/polling_bot/sample_plugin.rb` for more information, or just browse
|
19
|
+
the included plugins. Some of the plugins are somewhat Wesabe-specific (like
|
20
|
+
DeployPlugin, which lets us see what commits are on deck to be deployed), but
|
21
|
+
can be adapted or ignored as you see fit.
|
22
|
+
|
23
|
+
If any of your plugins need to use a database, just drop a Datamapper model in
|
24
|
+
the plugins/models directory and it will be automatically loaded.
|
25
|
+
|
26
|
+
## Installation
|
27
|
+
|
28
|
+
### Prerequisites
|
29
|
+
|
30
|
+
Wesabot can be installed as a gem, but [Nokogiri](http://nokogiri.org/) is
|
31
|
+
required, and it has rather complicated prerequisites that vary by platform, so
|
32
|
+
rather than reproducing that information here, please see
|
33
|
+
<http://nokogiri.org/tutorials/installing_nokogiri.html>.
|
34
|
+
|
35
|
+
You'll also need to install [SQLite3](http://www.sqlite.org/), and, at least
|
36
|
+
on Ubuntu, the sqlite3 development libraries
|
37
|
+
(`sudo apt-get install libsqlite3-dev`). If you have specific installation
|
38
|
+
instructions for other platforms, please feel free to send a pull request
|
39
|
+
with changes to this README.
|
40
|
+
|
41
|
+
### Installing as a Gem
|
42
|
+
|
43
|
+
gem install wesabot
|
44
|
+
|
45
|
+
### Installing from Git
|
46
|
+
|
47
|
+
Clone this repository, then `cd` to it and run `bundle install`.
|
48
|
+
|
49
|
+
## Usage
|
50
|
+
|
51
|
+
The first thing you need to do is to create a Campfire user for your bot,
|
52
|
+
and make sure that user has access to whichever room(s) you would like the bot
|
53
|
+
to appear in. Log into Campfire as that user and get the API token (click on
|
54
|
+
"My info" in the upper right corner).
|
55
|
+
|
56
|
+
Wesabot has four required parameters:
|
57
|
+
|
58
|
+
* subdomain - your Campfire subdomain
|
59
|
+
* api_token - the Campfire API token
|
60
|
+
* room - the room in which you'd like the bot to appear
|
61
|
+
* datauri - the sqlite3 database uri/path
|
62
|
+
|
63
|
+
These parameters can be passed in either via a YAML config file, or on the
|
64
|
+
command-line. See `config/wesabot.yml.sample` for a sample configuration file.
|
65
|
+
|
66
|
+
Examples:
|
67
|
+
|
68
|
+
bin/wesabot -c config/wesabot.yml
|
69
|
+
bin/wesabot -d example -r Sandbox -t ecca8793813bd3e5720d9d562285db --database /path/to/database.db
|
70
|
+
|
71
|
+
Run `wesabot --help` for usage information.
|
72
|
+
|
73
|
+
**A few important things to note:**
|
74
|
+
|
75
|
+
* The SQLite database does not need to exist initially--wesabot will create one
|
76
|
+
at the path you specify.
|
77
|
+
* On some systems (Ubuntu, at least) you will need to use the `--ssl-no-verify`
|
78
|
+
(`-k`) option, at least until the next release of [Faraday](https://github.com/technoweenie/faraday),
|
79
|
+
which includes [a fix](https://github.com/technoweenie/faraday/commit/2b9b798d07b95b3a3348e95c513fe42f5e21c6ee)
|
80
|
+
for looking up SSL certs in the system store. If you run wesabot and get the
|
81
|
+
error:
|
82
|
+
|
83
|
+
/usr/lib/ruby/1.8/net/http.rb:1060:in `request': undefined method `closed?' for nil:NilClass (NoMethodError)
|
84
|
+
|
85
|
+
That is the cause. (Run it again in verbose mode to see the SSL error.)
|
86
|
+
|
87
|
+
|
88
|
+
Once Wes (or whatever you decide to name your bot) is running, you can see a list of available commands by entering into Campfire:
|
89
|
+
|
90
|
+
Wes, help
|
91
|
+
|
92
|
+
That list currently looks like:
|
93
|
+
|
94
|
+
AirbrakePlugin:
|
95
|
+
- resolve <error number>
|
96
|
+
mark an error as resolved
|
97
|
+
- unresolve <error number>
|
98
|
+
mark an error as unresolved
|
99
|
+
|
100
|
+
BookmarkPlugin:
|
101
|
+
- bookmark: <name>
|
102
|
+
bookmark the current location
|
103
|
+
|
104
|
+
DebugPlugin:
|
105
|
+
- <enable|disable> debugging
|
106
|
+
enable or disable debug mode
|
107
|
+
|
108
|
+
DeployPlugin:
|
109
|
+
- what's on deck for <project>?
|
110
|
+
shortlog of changes not yet deployed to production
|
111
|
+
- what's on deck for <project> staging?
|
112
|
+
shortlog of changes not yet deployed to staging
|
113
|
+
|
114
|
+
GreetingPlugin:
|
115
|
+
- (disable|turn off) greetings
|
116
|
+
don't say hi when you log in (you grump)
|
117
|
+
- (enable|turn on) greetings
|
118
|
+
say hi when you log in
|
119
|
+
- toggle greetings
|
120
|
+
disable greetings if enabled, enable if disabled. You know--toggle.
|
121
|
+
- catch me up|ketchup
|
122
|
+
gives you a link to the point in the transcript where you last logged out
|
123
|
+
|
124
|
+
HelpPlugin:
|
125
|
+
- help
|
126
|
+
this message
|
127
|
+
|
128
|
+
ImageSearchPlugin:
|
129
|
+
- (photo|image|picture) of <subject>
|
130
|
+
find a new picture of <subject>
|
131
|
+
- search (google|flickr) for a (photo|image|picture) of <subject>
|
132
|
+
search the stated service for a new picture of <subject>
|
133
|
+
|
134
|
+
ReloadPlugin:
|
135
|
+
- reload
|
136
|
+
update and reload Wes
|
137
|
+
|
138
|
+
RemindMePlugin:
|
139
|
+
- remind (me|<person>) [in] <time string> to <message>
|
140
|
+
set up a reminder
|
141
|
+
- remind (me|<person>) to <message> (in|on|at|next|this) <time string>
|
142
|
+
set up a reminder
|
143
|
+
- [list|show] [person]['s] reminders
|
144
|
+
display current reminders for yourself or person
|
145
|
+
- delete reminder <n>
|
146
|
+
delete your reminder #n
|
147
|
+
|
148
|
+
SMSPlugin:
|
149
|
+
- set my sms address to: <address>
|
150
|
+
set your sms address
|
151
|
+
- set <person>'s sms address to
|
152
|
+
set someone else's sms address
|
153
|
+
- (sms|text|txt) <person>: <message>
|
154
|
+
send an sms message
|
155
|
+
- list sms addresses
|
156
|
+
list all sms addresses
|
157
|
+
|
158
|
+
TimePlugin:
|
159
|
+
- time
|
160
|
+
say the current time
|
161
|
+
|
162
|
+
TweetPlugin:
|
163
|
+
- tweet: <message>
|
164
|
+
post <message> to the configured user's twitter account
|
165
|
+
- save tweet: <message>
|
166
|
+
save <message> for later
|
167
|
+
- show tweets
|
168
|
+
shows the queued tweets for the configured user's twitter account
|
169
|
+
- show next tweet
|
170
|
+
shows the oldest queued twitter message
|
171
|
+
- post next tweet
|
172
|
+
sends the oldest queued twitter message
|
173
|
+
- post tweet <n>
|
174
|
+
sends the <n>th tweet from the list
|
175
|
+
- delete tweet <n>
|
176
|
+
deletes the <n>th tweet from the list
|
177
|
+
|
178
|
+
TwitterSearchPlugin:
|
179
|
+
- what are (people|is everyone) saying about <subject>
|
180
|
+
search twitter for tweets on <subject>
|
181
|
+
- what's the word on <subject>
|
182
|
+
search twitter for tweets on <subject>
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
|
4
|
+
require 'rspec'
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
|
7
|
+
desc "Run the specs for wesabot"
|
8
|
+
RSpec::Core::RakeTask.new do |t|
|
9
|
+
t.pattern = 'spec/**/*_spec.rb'
|
10
|
+
end
|
11
|
+
|
12
|
+
task :cruise => :spec
|
13
|
+
task :default => :spec
|
data/bin/wesabot
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
# get the real path of this file so we can load the library
|
5
|
+
file = Pathname.new(__FILE__).realpath
|
6
|
+
|
7
|
+
# save the original invocation so we can restart ourselves later
|
8
|
+
INVOCATION = [file.to_s, *ARGV]
|
9
|
+
|
10
|
+
# chdir to this project's directory so bundler will be able to find
|
11
|
+
# the .bundle directory itself
|
12
|
+
oldpwd = Dir.pwd
|
13
|
+
Dir.chdir(File.expand_path('../..', file))
|
14
|
+
|
15
|
+
# load dependencies
|
16
|
+
$:.push File.expand_path("../../lib", file)
|
17
|
+
require 'rubygems'
|
18
|
+
require 'wesabot'
|
19
|
+
require 'optparse'
|
20
|
+
require 'openssl'
|
21
|
+
|
22
|
+
config = Campfire::Configuration.new
|
23
|
+
daemonize = false
|
24
|
+
pidfile = nil
|
25
|
+
|
26
|
+
# get configuration from ARGV
|
27
|
+
optparse = OptionParser.new do |opts|
|
28
|
+
opts.banner = "Usage: #{File.basename($0)} [options]"
|
29
|
+
|
30
|
+
opts.separator ""
|
31
|
+
opts.separator "Options:"
|
32
|
+
|
33
|
+
opts.on("-c", "--config FILE", "Configuration file") do |path|
|
34
|
+
config = Campfire::FileConfiguration.new(File.expand_path(path, oldpwd))
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.separator "OR"
|
38
|
+
|
39
|
+
opts.on("-t", "--token TOKEN", "API token (required)") do |api_token|
|
40
|
+
config.api_token = api_token
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on("-d", "--subdomain SUBDOMAIN", "Campfire subdomain (required)") do |subdomain|
|
44
|
+
config.subdomain = subdomain
|
45
|
+
end
|
46
|
+
|
47
|
+
opts.on("-r", "--room ROOM", "Campfire room (required)") do |room|
|
48
|
+
config.room = room
|
49
|
+
end
|
50
|
+
|
51
|
+
opts.on("--database PATH", "The sqlite3 database to use (required)") do |path|
|
52
|
+
config.datauri = "sqlite3://#{Pathname(File.expand_path(path, oldpwd)).expand_path}"
|
53
|
+
end
|
54
|
+
|
55
|
+
opts.on("-D", "--daemonize", "Daemonize the bot (run in the background)") do
|
56
|
+
daemonize = true
|
57
|
+
end
|
58
|
+
|
59
|
+
opts.on("--pid-file PATH", "PID file to write the daemon's PID to") do |path|
|
60
|
+
pidfile = path
|
61
|
+
end
|
62
|
+
|
63
|
+
opts.on("-o", "--log-file PATH", "The file to log STDOUT and STDERR to") do |path|
|
64
|
+
config.logger = Logger.new(path)
|
65
|
+
end
|
66
|
+
|
67
|
+
opts.on("-k", "--ssl-no-verify", "Don't verify SSL certs") do
|
68
|
+
config.ssl_verify = false
|
69
|
+
end
|
70
|
+
|
71
|
+
opts.on("-v", "--verbose", "Be verbose") do
|
72
|
+
config.verbose = true
|
73
|
+
end
|
74
|
+
|
75
|
+
opts.on("--version", "Print version") do
|
76
|
+
puts Campfire::VERSION
|
77
|
+
exit
|
78
|
+
end
|
79
|
+
|
80
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
81
|
+
puts opts
|
82
|
+
exit
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# check for required options
|
87
|
+
begin
|
88
|
+
optparse.parse!
|
89
|
+
config.validate!
|
90
|
+
|
91
|
+
config.logger.level = config.verbose?? Logger::DEBUG : Logger::INFO
|
92
|
+
|
93
|
+
if daemonize
|
94
|
+
require 'daemons'
|
95
|
+
puts "Daemonizing..."
|
96
|
+
Daemons.daemonize
|
97
|
+
end
|
98
|
+
|
99
|
+
File.open(pidfile, 'w') {|f| f << $$.to_s } if pidfile
|
100
|
+
rescue Campfire::ConfigurationError, OptionParser::InvalidOption, OptionParser::MissingArgument => e
|
101
|
+
puts "#{File.basename($0)}: #{e}"
|
102
|
+
puts optparse
|
103
|
+
exit(1)
|
104
|
+
end
|
105
|
+
|
106
|
+
OpenSSL::debug = config.verbose?
|
107
|
+
|
108
|
+
bot = Campfire::PollingBot.new(config)
|
109
|
+
trap(:INT) { bot.leave; exit }
|
110
|
+
trap(:TERM) { bot.leave; exit }
|
111
|
+
bot.run
|
data/lib/campfire/bot.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require "tinder"
|
2
|
+
|
3
|
+
module Campfire
|
4
|
+
class Bot
|
5
|
+
attr_accessor :config, :room, :name, :campfire, :debug
|
6
|
+
|
7
|
+
def initialize(config)
|
8
|
+
self.config = config
|
9
|
+
options = {:token => config.api_token, :ssl_verify => config.ssl_verify }
|
10
|
+
self.campfire = Tinder::Campfire.new(config.subdomain, options)
|
11
|
+
begin
|
12
|
+
self.name = campfire.me['name']
|
13
|
+
self.room = campfire.find_room_by_name(config.room) or
|
14
|
+
raise ConfigurationError, "Could not find a room named '#{config.room}'"
|
15
|
+
rescue Tinder::AuthenticationFailed => e
|
16
|
+
raise # maybe do some friendlier error handling later
|
17
|
+
end
|
18
|
+
room.join
|
19
|
+
say("hey guys")
|
20
|
+
end
|
21
|
+
|
22
|
+
def base_uri
|
23
|
+
campfire.connection.uri.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
# convenience method so I don't have to change all the old #say method to #speak
|
27
|
+
def say(*args)
|
28
|
+
room.speak(*args)
|
29
|
+
end
|
30
|
+
|
31
|
+
# pick something at random from an array of sayings
|
32
|
+
def say_random(sayings)
|
33
|
+
say(sayings[rand(sayings.size)])
|
34
|
+
end
|
35
|
+
|
36
|
+
# return a random person out of the list of users logged in to this room
|
37
|
+
def other_person(exclude = nil)
|
38
|
+
# don't choose the excluded person or ourself
|
39
|
+
options = room.users.reject{|u| u[:name] =~ /^(#{exclude}|#{self.name})/ }
|
40
|
+
# return the other person's first name, or nil if we didn't find one
|
41
|
+
options.any? ? options[rand(options.size)][:name].split(' ').first : nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def logger
|
45
|
+
config.logger
|
46
|
+
end
|
47
|
+
|
48
|
+
# Proxy everything to the room.
|
49
|
+
def method_missing(m, *args)
|
50
|
+
room.send(m, *args)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Campfire
|
4
|
+
class ConfigurationError < RuntimeError; end
|
5
|
+
|
6
|
+
class Configuration
|
7
|
+
protected
|
8
|
+
|
9
|
+
def initialize(data={})
|
10
|
+
load data
|
11
|
+
end
|
12
|
+
|
13
|
+
def load(data)
|
14
|
+
data = data.inject({}) {|h,(k,v)| h[k.to_sym] = v; h }
|
15
|
+
self.api_token = data[:api_token]
|
16
|
+
self.subdomain = data[:subdomain]
|
17
|
+
self.room = data[:room]
|
18
|
+
self.verbose = data[:verbose] || false
|
19
|
+
self.datauri = data[:datauri]
|
20
|
+
self.logger = data[:logger] || data[:logfile] || Logger.new(STDOUT)
|
21
|
+
self.google_api_key = data[:google_api_key]
|
22
|
+
self.ssl_verify = data[:ssl_verify] != false
|
23
|
+
end
|
24
|
+
|
25
|
+
public
|
26
|
+
|
27
|
+
attr_accessor :api_token, :subdomain, :room, :verbose, :datauri, :logger,
|
28
|
+
:google_api_key, :ssl_verify
|
29
|
+
|
30
|
+
alias_method :verbose?, :verbose
|
31
|
+
|
32
|
+
def logger=(logger)
|
33
|
+
logger = Logger.new(logger) unless logger.is_a?(Logger)
|
34
|
+
@logger = logger
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate!
|
38
|
+
api_token or raise ConfigurationError, 'no api token given'
|
39
|
+
subdomain or raise ConfigurationError, 'no subdomain given'
|
40
|
+
room or raise ConfigurationError, 'no room given'
|
41
|
+
datauri or raise ConfigurationError, 'no datauri given'
|
42
|
+
logger or raise ConfigurationError, 'no logger given'
|
43
|
+
end
|
44
|
+
|
45
|
+
def reload!
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class FileConfiguration < Configuration
|
50
|
+
protected
|
51
|
+
|
52
|
+
attr_reader :path
|
53
|
+
|
54
|
+
def initialize(path)
|
55
|
+
@path = path
|
56
|
+
reload!
|
57
|
+
end
|
58
|
+
|
59
|
+
public
|
60
|
+
|
61
|
+
def reload!
|
62
|
+
load YAML.load_file(path)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# Classes to encapsulate the various campfire message types
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
module Campfire
|
5
|
+
# base message class. All messages have a message_id, timestamp, person (first name of the user generating
|
6
|
+
# the message), person_full_name, and body, which is the text of the message
|
7
|
+
class Message
|
8
|
+
attr_accessor :message_id, :timestamp, :user, :person, :person_full_name, :body, :type
|
9
|
+
|
10
|
+
def initialize(params)
|
11
|
+
self.message_id = params[:id]
|
12
|
+
self.timestamp = params[:created_at] || Time.now
|
13
|
+
self.body = params[:body]
|
14
|
+
self.type = params[:type].gsub(/(.*?)Message$/, '\1') if params[:type]
|
15
|
+
end
|
16
|
+
|
17
|
+
def person_full_name=(name)
|
18
|
+
@person_full_name = name
|
19
|
+
@person = @person_full_name.split(' ').first # just get first name
|
20
|
+
end
|
21
|
+
|
22
|
+
def user=(user)
|
23
|
+
self.person_full_name = user.name
|
24
|
+
@user = user
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# TextMessage - normal user text message
|
29
|
+
# #command - if the message is addressed to the bot ("<bot name>, ..." or "..., <bot name>"), the
|
30
|
+
# the part of the body minus the bot name (and comma) is returned by #command
|
31
|
+
class TextMessage < Message
|
32
|
+
attr_accessor :command
|
33
|
+
|
34
|
+
def addressed_to_me?
|
35
|
+
not command.nil?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# a PasteMessage is sent when a paste block appears. #link contains the link to the full text of the
|
40
|
+
# pasted block (TODO: grab the full paste from the link and have it available)
|
41
|
+
class PasteMessage < Message
|
42
|
+
attr_accessor :link
|
43
|
+
|
44
|
+
def initialize(params)
|
45
|
+
super
|
46
|
+
# FIXME: link is no longer available as a param. If we want the link, we
|
47
|
+
# need to construct it from https://#{subdomain}.campfirenow.com/room/#{params[:room_id]}/paste/#{params[:id]}
|
48
|
+
# self.link = params[:link]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# an UploadMessage is sent when a user uploads a file. #link contains the link to the file
|
53
|
+
class UploadMessage < Message
|
54
|
+
attr_accessor :link
|
55
|
+
|
56
|
+
def initialize(params)
|
57
|
+
super
|
58
|
+
# FIXME: link is no longer available as a param. If we want the link, we
|
59
|
+
# need to construct it from https://#{subdomain}.campfirenow.com/room/#{params[:room_id]}/uploads/#{params[:id]}/#{params[:filename]} (?)
|
60
|
+
# self.link = params[:link]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# EnterMessage - sent when a user enters the room
|
65
|
+
class EnterMessage < Message; end
|
66
|
+
|
67
|
+
# LeaveMessage - sent when a user leaves the room
|
68
|
+
class LeaveMessage < Message; end
|
69
|
+
|
70
|
+
# KickMessage - sent when a user times out and is booted from the room
|
71
|
+
class KickMessage < Message; end
|
72
|
+
|
73
|
+
# LockMessage - sent when a user locks the room
|
74
|
+
class LockMessage < Message; end
|
75
|
+
|
76
|
+
# UnlockMessage - sent when the room is unlocked
|
77
|
+
class UnlockMessage < Message; end
|
78
|
+
|
79
|
+
# AllowGuestsMessage - sent when guest access is turned on
|
80
|
+
class AllowGuestsMessage < Message; end
|
81
|
+
|
82
|
+
# DisallowGuestsMessage - sent when guest access is turned off
|
83
|
+
class DisallowGuestsMessage < Message; end
|
84
|
+
|
85
|
+
# TopicChangeMessage - sent when the room's topic is changed
|
86
|
+
class TopicChangeMessage < Message; end
|
87
|
+
|
88
|
+
# TimestampMessage - sent when a timestamp is posted to the room
|
89
|
+
class TimestampMessage < Message; end
|
90
|
+
|
91
|
+
# AdvertisementMessage - ads
|
92
|
+
class AdvertisementMessage < Message; end
|
93
|
+
|
94
|
+
# SoundMessage - when a user plays a sound
|
95
|
+
class SoundMessage < Message; end
|
96
|
+
|
97
|
+
# ConferenceCreatedMessage - when a conference call is started
|
98
|
+
class ConferenceCreatedMessage < Message; end
|
99
|
+
|
100
|
+
# TweetMessage - when a tweet is posted
|
101
|
+
class TweetMessage < Message; end
|
102
|
+
end
|