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
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
# plugin to search twitter
|
4
|
+
class TwitterSearchPlugin < Campfire::PollingBot::Plugin
|
5
|
+
priority 1
|
6
|
+
accepts :text_message, :addressed_to_me => true
|
7
|
+
|
8
|
+
def process(message)
|
9
|
+
searched = false
|
10
|
+
|
11
|
+
case message.command
|
12
|
+
when /(?:(?:what(?:'s)? (?:(?:are )?people|(?:is |does )?every(?:one|body)) (?:saying|tweeting|think) about)|what's the word on)\s+(?:the )?(.*?)[.?!]?\s*$/i
|
13
|
+
subject = $1
|
14
|
+
tweets = search_twitter(subject)
|
15
|
+
if tweets.any?
|
16
|
+
tweets.each {|t| bot.tweet(t) }
|
17
|
+
else
|
18
|
+
bot.say("Couldn't find anything for \"#{subject}\"")
|
19
|
+
end
|
20
|
+
return HALT
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# return array of available commands and descriptions
|
25
|
+
def help
|
26
|
+
[
|
27
|
+
["what are (people|is everyone) saying about <subject>", "search twitter for tweets on <subject>"],
|
28
|
+
["what's the word on <subject>", "search twitter for tweets on <subject>"],
|
29
|
+
]
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# construct a twitter url from the given response json
|
35
|
+
def twitter_url(json)
|
36
|
+
"http://twitter.com/#{json['from_user']}/status/#{json['id']}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def search_twitter(subject)
|
40
|
+
tweets = []
|
41
|
+
res = HTTParty.get(
|
42
|
+
"http://search.twitter.com/search.json",
|
43
|
+
:query => { :q => subject, :result_type => "mixed" },
|
44
|
+
# other possible result types include "popular" and "recent"
|
45
|
+
:headers => {'User-Agent' => 'wesabot/1.0 github-hackarts-wesabot'})
|
46
|
+
case res.code
|
47
|
+
when 200
|
48
|
+
tweets = res["results"].first(5).map {|r| twitter_url(r) }
|
49
|
+
when 400, 420
|
50
|
+
bot.say("Sorry, we've hit the Twitter rate limit for searches.")
|
51
|
+
else
|
52
|
+
bot.say("Hmm...didn't work. Got this response:")
|
53
|
+
bot.paste("#{res.code} (#{res.message})\n#{res.body}")
|
54
|
+
end
|
55
|
+
|
56
|
+
return tweets
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# PollingBot - a bot that polls the room for messages
|
2
|
+
require 'campfire/bot'
|
3
|
+
require 'campfire/message'
|
4
|
+
|
5
|
+
require 'firering'
|
6
|
+
|
7
|
+
module Campfire
|
8
|
+
class PollingBot < Bot
|
9
|
+
require 'campfire/polling_bot/plugin'
|
10
|
+
attr_accessor :plugins
|
11
|
+
HEARTBEAT_INTERVAL = 3 # seconds
|
12
|
+
|
13
|
+
def initialize(config)
|
14
|
+
# load plugin queue, sorting by priority
|
15
|
+
super
|
16
|
+
self.plugins = Plugin.load_all(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
# main event loop
|
20
|
+
def run
|
21
|
+
# set up a heartbeat thread for plugins that want them
|
22
|
+
Thread.new do
|
23
|
+
loop do
|
24
|
+
plugins.each {|p| p.heartbeat if p.respond_to?(:heartbeat)}
|
25
|
+
sleep HEARTBEAT_INTERVAL
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
host = "https://#{config.subdomain}.campfirenow.com"
|
30
|
+
conn = Firering::Connection.new(host) do |c|
|
31
|
+
c.token = config.api_token
|
32
|
+
c.logger = logger
|
33
|
+
c.retry_delay = 2
|
34
|
+
end
|
35
|
+
|
36
|
+
EM.run do
|
37
|
+
conn.room(room.id) do |room|
|
38
|
+
room.stream do |data|
|
39
|
+
|
40
|
+
begin
|
41
|
+
klass = Campfire.const_get(data.type)
|
42
|
+
message = klass.new(data)
|
43
|
+
|
44
|
+
if data.from_user?
|
45
|
+
data.user do |user|
|
46
|
+
dbuser = User.first(:campfire_id => user.id)
|
47
|
+
|
48
|
+
if dbuser.nil?
|
49
|
+
dbuser = User.create(
|
50
|
+
:campfire_id => user.id,
|
51
|
+
:name => user.name
|
52
|
+
)
|
53
|
+
else
|
54
|
+
dbuser.update(:name => user.name)
|
55
|
+
end
|
56
|
+
|
57
|
+
message.user = dbuser
|
58
|
+
process(message)
|
59
|
+
end
|
60
|
+
else
|
61
|
+
process(message)
|
62
|
+
end
|
63
|
+
|
64
|
+
rescue => e
|
65
|
+
log_error(e)
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
trap("INT") { EM.stop; raise SystemExit }
|
72
|
+
end
|
73
|
+
|
74
|
+
rescue Exception => e # leave the room if we crash
|
75
|
+
if e.kind_of?(SystemExit)
|
76
|
+
room.leave
|
77
|
+
exit 0
|
78
|
+
else
|
79
|
+
log_error(e)
|
80
|
+
room.leave
|
81
|
+
exit 1
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def process(message)
|
86
|
+
logger.debug "processing #{message} (#{message.person} - #{message.body})"
|
87
|
+
|
88
|
+
# ignore messages from ourself
|
89
|
+
return if [message.person, message.person_full_name].include? self.name
|
90
|
+
|
91
|
+
plugins.each do |plugin|
|
92
|
+
begin
|
93
|
+
if plugin.accepts?(message)
|
94
|
+
logger.debug "sending to plugin #{plugin} (priority #{plugin.priority})"
|
95
|
+
status = plugin.process(message)
|
96
|
+
if status == Plugin::HALT
|
97
|
+
logger.debug "plugin chain halted"
|
98
|
+
break
|
99
|
+
end
|
100
|
+
end
|
101
|
+
rescue Exception => e
|
102
|
+
say("Oops, #{plugin.class} threw an exception. Enable debugging to see it.") unless debug
|
103
|
+
log_error(e)
|
104
|
+
break
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
logger.debug "done processing #{message}"
|
109
|
+
end
|
110
|
+
|
111
|
+
# determine if a message is addressed to the bot. if so, store the command in the message
|
112
|
+
def addressed_to_me?(message)
|
113
|
+
m = message.body.match(/^#{name}(?:[,:]\s*|\s+)(.*)/i)
|
114
|
+
m ||= message.body.match(/^\s*(.*?)(?:,\s+)?\b#{name}[.!?\s]*$/i)
|
115
|
+
message.command = m[1] if m
|
116
|
+
end
|
117
|
+
|
118
|
+
def log_error(e)
|
119
|
+
msg = "Exception: #{e.class}: #{e.message}\n\t#{e.backtrace.join("\n\t")}"
|
120
|
+
logger.error(msg)
|
121
|
+
paste(msg) if debug
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# Sample Campfire plugin. Plugins must be placed in the plugins directory in order to be loaded.
|
2
|
+
class SamplePlugin < Campfire::PollingBot::Plugin
|
3
|
+
# accept - specify which kinds of messages this plugin accepts. Put each type on its own line.
|
4
|
+
# You may optionally set :addressed_to_me => true to get only messages addressed to the bot.
|
5
|
+
# For example,
|
6
|
+
# accept :text_message, :addressed_to_me => true
|
7
|
+
# Will only accept text messages that are in the form "<bot name>, ..." or "... <bot name>".
|
8
|
+
# The body of the message minus the bot name will be returned by the 'command' method of the
|
9
|
+
# message.
|
10
|
+
#
|
11
|
+
# Message types are:
|
12
|
+
# - :all - all messages
|
13
|
+
# - :text_message - normal user text message
|
14
|
+
# - :paste_message - a paste
|
15
|
+
# - :enter_message - sent when a user enters the room
|
16
|
+
# - :leave_message - sent when a user leaves the room
|
17
|
+
# - :kick_message - sent when a user times out from inactivity
|
18
|
+
# - :lock_message - sent when the room is locked
|
19
|
+
# - :unlock_message - sent when the room is unlocked
|
20
|
+
# - :allow_guests_message - sent when guest access is turned on
|
21
|
+
# - :disallow_guests_message - sent when guest access is turned off
|
22
|
+
# - :topic_change_message - sent when the room's topic is changed
|
23
|
+
|
24
|
+
accepts :text_message, :addressed_to_me => true
|
25
|
+
accepts :paste_message
|
26
|
+
|
27
|
+
# priority is used to determine the plugin's order in the plugin queue. A higher number represents
|
28
|
+
# a higher priority. There are no upper or lower bounds. If you don't specify a priority, it defaults
|
29
|
+
# to 0.
|
30
|
+
|
31
|
+
priority 10
|
32
|
+
|
33
|
+
# If you need to do any one-time setup when the plugin is initially loaded, do it here. Optional.
|
34
|
+
def initialize
|
35
|
+
end
|
36
|
+
|
37
|
+
# If your plugin implements the heartbeat method, it will be called every time the bot polls the room
|
38
|
+
# for activity (currently every 3 seconds), whether or not there are any new messages. The heartbeat
|
39
|
+
# method is optional. It does not take any parameters.
|
40
|
+
def heartbeat
|
41
|
+
end
|
42
|
+
|
43
|
+
# process is the only method your plugin needs to implement. This is called by the bot whenever it
|
44
|
+
# has a new message that matches one of the message types accepted by the plugin. See Campfire::Message
|
45
|
+
# for message documentation.
|
46
|
+
# If no other plugins should receive the message after this plugin, return HALT.
|
47
|
+
def process(message)
|
48
|
+
end
|
49
|
+
|
50
|
+
# help is actually functionality provided by another plugin, HelpPlugin. Just return an array of
|
51
|
+
# ['command', 'description'] tuples
|
52
|
+
def help
|
53
|
+
[['some command', 'description of some command'],
|
54
|
+
['some other command', 'description of some other command']]
|
55
|
+
end
|
56
|
+
end
|
data/lib/wesabot.rb
ADDED
data/spec/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
test.sqlite
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Campfire::PollingBot do
|
4
|
+
before do
|
5
|
+
@bot = FakeBot.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'recognizes commands addressed to itself' do
|
9
|
+
messages = ["wes", "wes?", "wes hi", "wes, hi", "hi, wes", "hi wes",
|
10
|
+
"wes: hi"]
|
11
|
+
messages.each do |m|
|
12
|
+
@bot.addressed_to_me?(Campfire::TextMessage.new(:body => m)).should be_true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'does not recognize commands not addressed to itself' do
|
17
|
+
messages = ["hi", "western", "weswes?"]
|
18
|
+
messages.each do |m|
|
19
|
+
@bot.addressed_to_me?(Campfire::TextMessage.new(:body => m)).should be_false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.setup
|
4
|
+
|
5
|
+
$:.push File.expand_path("../lib", __FILE__)
|
6
|
+
require 'wesabot'
|
7
|
+
require 'rspec'
|
8
|
+
|
9
|
+
Campfire::PollingBot::Plugin.load_plugin_classes
|
10
|
+
|
11
|
+
class FakeBot < Campfire::PollingBot
|
12
|
+
def initialize
|
13
|
+
self.name = 'Wes'
|
14
|
+
self.config = Campfire::Configuration.new(:datauri => "sqlite3://#{File.expand_path('../test.sqlite', __FILE__)}")
|
15
|
+
Campfire::PollingBot::Plugin.load_all(self)
|
16
|
+
end
|
17
|
+
|
18
|
+
def say(message)
|
19
|
+
transcript << [:say, message]
|
20
|
+
end
|
21
|
+
|
22
|
+
def paste(message)
|
23
|
+
transcript << [:paste, message]
|
24
|
+
end
|
25
|
+
|
26
|
+
def say_random(messages)
|
27
|
+
transcript << [:say, messages.first]
|
28
|
+
end
|
29
|
+
|
30
|
+
def transcript
|
31
|
+
@transcript ||= []
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
RSpec.configure do |config|
|
36
|
+
def saying(what)
|
37
|
+
message Campfire::TextMessage, :body => what
|
38
|
+
end
|
39
|
+
|
40
|
+
alias :asking :saying
|
41
|
+
alias :say :saying
|
42
|
+
|
43
|
+
def entering
|
44
|
+
message Campfire::EnterMessage
|
45
|
+
end
|
46
|
+
|
47
|
+
alias :enter :entering
|
48
|
+
|
49
|
+
def leaving
|
50
|
+
message Campfire::LeaveMessage
|
51
|
+
end
|
52
|
+
|
53
|
+
alias :leave :leaving
|
54
|
+
|
55
|
+
def message(type, params={})
|
56
|
+
bot = FakeBot.new
|
57
|
+
@plugin.class.bot = bot
|
58
|
+
message = type.new(params)
|
59
|
+
@user ||= User.create(:name => "John Tester")
|
60
|
+
message.user = @user
|
61
|
+
@plugin.process(message) if @plugin.accepts?(message)
|
62
|
+
return bot.transcript
|
63
|
+
end
|
64
|
+
|
65
|
+
def make_wes_say(what)
|
66
|
+
MakeWesSend.new.and_say(what)
|
67
|
+
end
|
68
|
+
|
69
|
+
def make_wes_paste(what)
|
70
|
+
MakeWesSend.new.and_paste(what)
|
71
|
+
end
|
72
|
+
|
73
|
+
def make_wes_say_something
|
74
|
+
MakeWesSaySomething.new
|
75
|
+
end
|
76
|
+
|
77
|
+
alias :make_wes_say_anything :make_wes_say_something
|
78
|
+
|
79
|
+
module MessagePrinter
|
80
|
+
def print_messages(messages)
|
81
|
+
messages.map {|e| " #{e.first} #{e.last.inspect}"}.join("\n")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class MakeWesSend
|
86
|
+
include MessagePrinter
|
87
|
+
|
88
|
+
def matches?(actual)
|
89
|
+
@actual = actual
|
90
|
+
|
91
|
+
if actual.size != expected.size
|
92
|
+
@failure = [:size, actual.size, expected.size]
|
93
|
+
return false
|
94
|
+
end
|
95
|
+
|
96
|
+
actual.zip(expected).each do |a, e|
|
97
|
+
if a.first != e.first
|
98
|
+
@failure = [:type, a, e]
|
99
|
+
return false
|
100
|
+
end
|
101
|
+
|
102
|
+
case e.last
|
103
|
+
when Regexp
|
104
|
+
if a.last !~ e.last
|
105
|
+
@failure = [:match, a, e]
|
106
|
+
return false
|
107
|
+
end
|
108
|
+
else
|
109
|
+
if e.last != a.last
|
110
|
+
@failure = [:equal, a, e]
|
111
|
+
return false
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
return true
|
117
|
+
end
|
118
|
+
|
119
|
+
def failure_message
|
120
|
+
failure_type, actual, expected = *@failure
|
121
|
+
|
122
|
+
case failure_type
|
123
|
+
when :size
|
124
|
+
"expected #{expected} message(s):\n\n" +
|
125
|
+
print_messages(@expected) +
|
126
|
+
"\n\ngot #{actual} message(s):\n\n" +
|
127
|
+
print_messages(@actual)
|
128
|
+
when :type
|
129
|
+
"expected Wes to #{expected.first} #{expected.last.inspect}, " +
|
130
|
+
"but got #{actual.first} #{actual.last.inspect}"
|
131
|
+
when :match
|
132
|
+
"expected Wes to #{expected.first} something matching #{expected.last.inspect}, " +
|
133
|
+
"but got #{actual.last.inspect}"
|
134
|
+
when :equal
|
135
|
+
"expected Wes to #{expected.first} #{expected.last.inspect}, " +
|
136
|
+
"but got #{actual.last.inspect}"
|
137
|
+
else
|
138
|
+
@failure.inspect
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def negative_failure_message
|
143
|
+
"expected not to get the following message(s), but did:\n\n" +
|
144
|
+
print_messages(@expected)
|
145
|
+
end
|
146
|
+
|
147
|
+
def and(expected)
|
148
|
+
expect nil, expected
|
149
|
+
end
|
150
|
+
|
151
|
+
def and_say(expected)
|
152
|
+
expect :say, expected
|
153
|
+
end
|
154
|
+
|
155
|
+
def and_paste(expected)
|
156
|
+
expect :paste, expected
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def expect(type, message)
|
162
|
+
type ||= @last_type
|
163
|
+
expected << [type, message]
|
164
|
+
@last_type = type
|
165
|
+
return self
|
166
|
+
end
|
167
|
+
|
168
|
+
def expected
|
169
|
+
@expected ||= []
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
class MakeWesSaySomething
|
174
|
+
include MessagePrinter
|
175
|
+
|
176
|
+
def matches?(actual)
|
177
|
+
@actual = actual
|
178
|
+
actual.any?
|
179
|
+
end
|
180
|
+
|
181
|
+
def failure_message
|
182
|
+
"expected Wes to say something, but he didn't"
|
183
|
+
end
|
184
|
+
|
185
|
+
def negative_failure_message
|
186
|
+
"expected Wes not to say anything, but he did:\n\n" +
|
187
|
+
print_messages(@actual)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
data/wesabot.gemspec
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "campfire/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "wesabot"
|
7
|
+
s.version = Campfire::VERSION
|
8
|
+
s.authors = ["Brad Greenlee", "André Arko", "Brian Donovan"]
|
9
|
+
s.email = ["brad@footle.org", "andre@arko.net", "me@brian-donovan.com"]
|
10
|
+
s.homepage = "https://github.com/hackarts/wesabot"
|
11
|
+
s.summary = %q{Wesabe's Campfire bot framework}
|
12
|
+
s.description = %q{Wesabot is a Campfire bot framework we've been using and
|
13
|
+
developing at Wesabe since not long after our inception. It started as a
|
14
|
+
way to avoid parking tickets near our office ("Wes, remind me in 2 hours
|
15
|
+
to move my car"), and has evolved into an essential work aid. When you
|
16
|
+
enter the room, Wes greets you with a link to the point in the transcript
|
17
|
+
where you last left. You can also ask him to bookmark points in the
|
18
|
+
transcript, send an sms message (well, an email) to someone, or even post
|
19
|
+
a tweet, among other things. His functionality is easily extendable via
|
20
|
+
plugins.}
|
21
|
+
|
22
|
+
s.rubyforge_project = "wesabot"
|
23
|
+
|
24
|
+
s.files = `git ls-files`.split("\n")
|
25
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
26
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
27
|
+
s.require_paths = ["lib"]
|
28
|
+
|
29
|
+
### core dependencies
|
30
|
+
s.add_dependency "tinder", "~> 1.7.0"
|
31
|
+
s.add_dependency "data_mapper", "~> 1.1"
|
32
|
+
s.add_dependency "dm-sqlite-adapter", "~> 1.1"
|
33
|
+
s.add_dependency "daemons"
|
34
|
+
s.add_dependency "i18n"
|
35
|
+
s.add_dependency "firering", "~> 1.2.0"
|
36
|
+
|
37
|
+
### plugin dependencies
|
38
|
+
|
39
|
+
# airbrake
|
40
|
+
s.add_dependency "nokogiri"
|
41
|
+
s.add_dependency "rest-client"
|
42
|
+
|
43
|
+
# image_search
|
44
|
+
s.add_dependency "httparty" # also used by twitter_search
|
45
|
+
s.add_dependency "google-search"
|
46
|
+
|
47
|
+
# remind_me
|
48
|
+
s.add_dependency "chronic"
|
49
|
+
|
50
|
+
### development dependencies
|
51
|
+
s.add_development_dependency "rspec", "~> 2.6.0"
|
52
|
+
s.add_development_dependency "rake"
|
53
|
+
s.add_development_dependency "ruby-debug"
|
54
|
+
|
55
|
+
end
|