scamp 1.2.0 → 2.0.0.pre
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.
- checksums.yaml +4 -4
- data/.gitignore +5 -0
- data/README.md +41 -128
- data/examples/v2.rb +39 -0
- data/lib/scamp/adapter.rb +47 -0
- data/lib/scamp/matcher.rb +15 -91
- data/lib/scamp/matches.rb +22 -0
- data/lib/scamp/message.rb +39 -0
- data/lib/scamp/plugin.rb +33 -0
- data/lib/scamp/version.rb +1 -1
- data/lib/scamp.rb +33 -43
- data/scamp.gemspec +9 -10
- data/spec/lib/adapter_spec.rb +145 -0
- data/spec/lib/matcher_spec.rb +122 -0
- data/spec/lib/matches_spec.rb +29 -0
- data/spec/lib/message_spec.rb +52 -0
- data/spec/lib/plugin_spec.rb +33 -0
- data/spec/lib/scamp_spec.rb +119 -659
- data/spec/spec_helper.rb +23 -1
- metadata +55 -58
- data/examples/bot.rb +0 -72
- data/lib/scamp/action.rb +0 -70
- data/lib/scamp/connection.rb +0 -32
- data/lib/scamp/messages.rb +0 -35
- data/lib/scamp/rooms.rb +0 -116
- data/lib/scamp/users.rb +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 68ec4dbee8f688bce6bc1b63ea69e53a4a343c0d
|
4
|
+
data.tar.gz: 46806e4a3ac13a4c961e09f32cef1354830185c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f8b6808337113e7ee703ee49536a297f053cb355a1200fb875f348335465f398dcc7f1ff7484b936b748695052bb7e101e9fd6ab54126635247c6f287caeac4c
|
7
|
+
data.tar.gz: 7e27db164920d26c8a75404b1c8c710e3addd3810022b06f847e1759cf4e047a298ab6cd69c0b6ad8525c32568f78e3818cfeca7bf60819fb36825db90bf165a
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -10,11 +10,11 @@ If you like or use Scamp I'd love to hear from you. Drop me at line at will at 3
|
|
10
10
|
|
11
11
|
## Requirements
|
12
12
|
|
13
|
-
Ruby >= 1.9.2
|
13
|
+
Ruby >= 1.9.2
|
14
14
|
|
15
15
|
## Installation
|
16
16
|
|
17
|
-
`gem install scamp` or
|
17
|
+
`gem install scamp` or `gem 'scamp'` in your Gemfile.
|
18
18
|
|
19
19
|
## Usage and Examples
|
20
20
|
|
@@ -22,30 +22,34 @@ Ruby >= 1.9.2 (At least for the named captures)
|
|
22
22
|
|
23
23
|
``` ruby
|
24
24
|
require 'scamp'
|
25
|
+
require 'scamp-campfire-adapter'
|
25
26
|
|
26
|
-
|
27
|
+
Scamp.new do |scamp|
|
28
|
+
scamp.adapter :campfire, Scamp::Campfire::Adapter, api_key: "YOUR API KEY",
|
29
|
+
subdomain: "yoursubdomain",
|
30
|
+
rooms: [293788]
|
27
31
|
|
28
|
-
scamp.behaviour do
|
29
32
|
# Simple matching based on regex or string:
|
30
|
-
match "ping" do
|
31
|
-
say "pong"
|
33
|
+
scamp.match "ping" do |room, msg|
|
34
|
+
room.say "pong"
|
32
35
|
end
|
33
36
|
end
|
34
|
-
|
35
|
-
# Connect and join some rooms
|
36
|
-
scamp.connect!([293788, "Monitoring"])
|
37
37
|
```
|
38
38
|
|
39
39
|
### Everyone wants an image search
|
40
40
|
|
41
41
|
``` ruby
|
42
42
|
require 'scamp'
|
43
|
+
require 'scamp-campfire-adapter'
|
44
|
+
require 'em-http-request'
|
43
45
|
require 'cgi'
|
44
46
|
|
45
|
-
|
47
|
+
Scamp.new do |scamp|
|
48
|
+
scamp.adapter :campfire, Scamp::Campfire::Adapter, api_key: "YOUR API KEY",
|
49
|
+
subdomain: "yoursubdomain",
|
50
|
+
rooms: [293788]
|
46
51
|
|
47
|
-
scamp.
|
48
|
-
match /^artme (?<search>\w+)/ do
|
52
|
+
scamp.match /^artme (?<search>\w+)/ do |room, msg|
|
49
53
|
url = "http://ajax.googleapis.com/ajax/services/search/images?rsz=large&start=0&v=1.0&q=#{CGI.escape(search)}"
|
50
54
|
http = EventMachine::HttpRequest.new(url).get
|
51
55
|
http.errback { say "Couldn't get #{url}: #{http.response_status.inspect}" }
|
@@ -53,20 +57,16 @@ scamp.behaviour do
|
|
53
57
|
if http.response_header.status == 200
|
54
58
|
results = Yajl::Parser.parse(http.response)
|
55
59
|
if results['responseData']['results'].size > 0
|
56
|
-
say results['responseData']['results'][0]['url']
|
60
|
+
room.say results['responseData']['results'][0]['url']
|
57
61
|
else
|
58
|
-
say "No images matched #{search}"
|
62
|
+
room.say "No images matched #{search}"
|
59
63
|
end
|
60
64
|
else
|
61
|
-
|
62
|
-
say "Couldn't get #{url}"
|
65
|
+
room.say "Couldn't get #{url}"
|
63
66
|
end
|
64
67
|
}
|
65
68
|
end
|
66
69
|
end
|
67
|
-
|
68
|
-
# Connect and join some rooms
|
69
|
-
scamp.connect!([293788, "Monitoring"])
|
70
70
|
```
|
71
71
|
|
72
72
|
### A more in-depth run through
|
@@ -77,139 +77,53 @@ Matchers are tested in order and all that satisfy the match and conditions will
|
|
77
77
|
require 'scamp'
|
78
78
|
|
79
79
|
# Add :verbose => true to get debug output, otherwise the logger will output INFO
|
80
|
-
|
80
|
+
Scamp.new do |scamp|
|
81
|
+
scamp.adapter :campfire, Scamp::Campfire::Adapter, api_key: "YOUR API KEY",
|
82
|
+
subdomain: "yoursubdomain",
|
83
|
+
rooms: [293788],
|
84
|
+
verbose: true
|
81
85
|
|
82
|
-
scamp.behaviour do
|
83
86
|
#
|
84
87
|
# Simple matching based on regex or string:
|
85
88
|
#
|
86
|
-
match /^repeat (\w+), (\w+)$/ do
|
87
|
-
say "You said #{matches[0]} and #{matches[1]}"
|
88
|
-
end
|
89
|
-
|
90
|
-
#
|
91
|
-
# You can specifically paste text:
|
92
|
-
#
|
93
|
-
|
94
|
-
match "paste stuff" do
|
95
|
-
paste "Awesome texts"
|
96
|
-
|
97
|
-
# say()'ing multiline strings will paste automatically however:
|
98
|
-
say <<-EOS
|
99
|
-
This will be pasted
|
100
|
-
even though you called say
|
101
|
-
EOS
|
102
|
-
end
|
103
|
-
|
104
|
-
#
|
105
|
-
# A special user and room method is available in match blocks.
|
106
|
-
#
|
107
|
-
match "a user said" do
|
108
|
-
say "#{user} said something in room #{room}"
|
109
|
-
end
|
110
|
-
|
111
|
-
match "Hello!" do
|
112
|
-
say "Hi there"
|
113
|
-
end
|
114
|
-
|
115
|
-
#
|
116
|
-
# You can play awesome sounds
|
117
|
-
#
|
118
|
-
match "ohmy" do
|
119
|
-
play "yeah"
|
120
|
-
end
|
121
|
-
|
122
|
-
#
|
123
|
-
# Limit the match to certain rooms, users or both.
|
124
|
-
#
|
125
|
-
match /^Lets match (.+)$/, :conditions => {:room => "Some Room"} do
|
126
|
-
say "Only said if room name matches 'Some Room'"
|
127
|
-
end
|
128
|
-
|
129
|
-
match "some text", :conditions => {:user => "Some User"} do
|
130
|
-
say "Only said if user name matches 'Some User'"
|
131
|
-
end
|
132
|
-
|
133
|
-
match /some other text/, :conditions => {:user => "Some User", :room => 123456} do
|
134
|
-
say "You can mix conditions"
|
135
|
-
end
|
136
|
-
|
137
|
-
match "some text", :conditions => {:room => ["Some Room", "Some Other Room"]} do
|
138
|
-
say "You can list multiple rooms"
|
89
|
+
scamp.match /^repeat (\w+), (\w+)$/ do |room, msg|
|
90
|
+
room.say "You said #{matches[0]} and #{matches[1]}"
|
139
91
|
end
|
140
92
|
|
141
93
|
#
|
142
94
|
# Named captures become available in your match block
|
143
95
|
#
|
144
|
-
match /^say (?<yousaid>.+)$/ do
|
145
|
-
say "You said #{yousaid}"
|
146
|
-
end
|
147
|
-
|
148
|
-
#
|
149
|
-
# You can say multiple times, and you can specify an alternate room.
|
150
|
-
# Default behaviour is to 'say' in the room that caused the match.
|
151
|
-
#
|
152
|
-
match "something" do
|
153
|
-
say "#{user} said something in room #{room}"
|
154
|
-
say "#{user} said something in room #{room}", 237872
|
155
|
-
say "#{user} said something in room #{room}", "System Administration"
|
156
|
-
end
|
157
|
-
|
158
|
-
#
|
159
|
-
# A list of commands is available as command_list this matcher uses it
|
160
|
-
# to format a help text
|
161
|
-
#
|
162
|
-
match "help" do
|
163
|
-
max_command_length = command_list.map{|cl| cl.first.to_s }.max_by(&:size).size
|
164
|
-
format_string = "%#{max_command_length + 1}s"
|
165
|
-
formatted_commands = command_list.map{|action, conds| "#{sprintf(format_string, action)} | #{conds.size == 0 ? '' : conds.inspect}"}
|
166
|
-
say <<-EOS
|
167
|
-
#{sprintf("%-#{max_command_length + 1}s", "Command match")} | Conditions
|
168
|
-
--------------------------------------------------------------------------------
|
169
|
-
#{formatted_commands.join("\n")}
|
170
|
-
EOS
|
96
|
+
scamp.match /^say (?<yousaid>.+)$/ do |room, msg|
|
97
|
+
room.say "You said #{msg.matches.yousaid}"
|
171
98
|
end
|
172
99
|
end
|
173
100
|
|
174
|
-
# Connect and join some rooms
|
175
|
-
scamp.connect!([293788, "Monitoring"])
|
176
101
|
```
|
177
102
|
|
178
|
-
|
103
|
+
Scamp will also run _all_ match blocks that an input string matches, you can make Scamp only run the first block it matches by passing in :first\_match\_only => true:
|
179
104
|
|
180
105
|
``` ruby
|
181
|
-
:
|
182
|
-
|
183
|
-
|
184
|
-
:conditions => {:user => "some string"}
|
185
|
-
:conditions => {:user => 123456}
|
186
|
-
|
187
|
-
say "#{user} said something in room #{room}", 237872
|
188
|
-
say "#{user} said something in room #{room}", "System Administration"
|
106
|
+
Scamp.new :first_match_only => true do |scamp|
|
107
|
+
end
|
189
108
|
```
|
190
109
|
|
191
|
-
|
110
|
+
## Adapters
|
192
111
|
|
193
|
-
|
194
|
-
scamp = Scamp.new(:api_key => "YOUR API KEY", :subdomain => "yoursubdomain", :ignore_self => true)
|
195
|
-
```
|
112
|
+
### Adapter channels
|
196
113
|
|
197
|
-
|
114
|
+
### Writing an adapter
|
198
115
|
|
199
|
-
``` ruby
|
200
|
-
scamp = Scamp.new(:api_key => "YOUR API KEY", :subdomain => "yoursubdomain", :first_match_only => true)
|
201
|
-
```
|
202
116
|
|
203
|
-
|
117
|
+
## Plugins
|
204
118
|
|
205
|
-
|
206
|
-
|
207
|
-
|
119
|
+
### Writing plugins
|
120
|
+
|
121
|
+
* TODO
|
208
122
|
|
209
|
-
Scamp will now require commands to begin with 'Bot: ' (or whatever you have specified), and will strip out this prefix before handing the message onto your match block.
|
210
123
|
|
211
124
|
## TODO
|
212
125
|
|
126
|
+
* Get messages working back to adapters
|
213
127
|
* Allow multiple values for conditions, eg: :conditions => {:user => ["Some User", "Some Other User"]}
|
214
128
|
|
215
129
|
## How to contribute
|
@@ -230,7 +144,8 @@ Take a look at the TODO list or known issues for some inspiration if you need it
|
|
230
144
|
|
231
145
|
## Authors
|
232
146
|
|
233
|
-
* Will Jessop
|
147
|
+
* [Will Jessop](http://willj.net/)
|
148
|
+
* [Adam Holt](http://adamholt.co.uk/)
|
234
149
|
|
235
150
|
## Thanks
|
236
151
|
|
@@ -238,8 +153,6 @@ First class support, commits and pull requests, thanks guys!
|
|
238
153
|
|
239
154
|
* [Caius Durling](http://caius.name/)
|
240
155
|
* Sudara Williams of [Ramen Music](http://ramenmusic.com)
|
241
|
-
* [Dom Hodgson](http://www.thehodge.co.uk/) (for the name)
|
242
|
-
* Pull requests: @mheffner
|
243
156
|
|
244
157
|
## License
|
245
158
|
|
data/examples/v2.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), '../lib')
|
2
|
+
|
3
|
+
require 'scamp'
|
4
|
+
require 'scamp/adapter'
|
5
|
+
require 'scamp/message'
|
6
|
+
require 'scamp/plugin'
|
7
|
+
|
8
|
+
class PingPlugin < Scamp::Plugin
|
9
|
+
match /^ping/, :say_pong
|
10
|
+
|
11
|
+
def say_pong channel, msg
|
12
|
+
channel.say "pong"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class TestAdapter < Scamp::Adapter
|
17
|
+
class Context
|
18
|
+
def say msg
|
19
|
+
puts msg
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def connect!
|
24
|
+
EventMachine::PeriodicTimer.new(@opts[:delay]) do
|
25
|
+
msg = Scamp::Message.new(self, :body => "ping")
|
26
|
+
context = TestAdapter::Context.new
|
27
|
+
push [context, msg]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Scamp.new do |bot|
|
33
|
+
bot.adapter :test, TestAdapter, :delay => 1
|
34
|
+
bot.adapter :another, TestAdapter, :delay => 5
|
35
|
+
|
36
|
+
bot.plugin PingPlugin, :on => [:test]
|
37
|
+
|
38
|
+
bot.connect!
|
39
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Scamp
|
2
|
+
class Adapter
|
3
|
+
attr_accessor :bot
|
4
|
+
|
5
|
+
def initialize(bot, opts={})
|
6
|
+
@bot = bot
|
7
|
+
@opts = opts
|
8
|
+
end
|
9
|
+
|
10
|
+
def matches_required_format?(msg)
|
11
|
+
return true unless msg
|
12
|
+
return true unless bot.required_format
|
13
|
+
if bot.required_format.is_a? String
|
14
|
+
msg.index(bot.required_format) == 0
|
15
|
+
elsif bot.required_format.is_a? Regexp
|
16
|
+
msg.match bot.required_format
|
17
|
+
else
|
18
|
+
raise ArgumentError, "You passed a :required_format that isn't a string or regexp, dont't know how to match it!"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def strip_prefix(msg)
|
23
|
+
# We only strip required prefxes if they are strings, and strip_prefix is set
|
24
|
+
return msg unless bot.required_format.is_a?(String) && bot.strip_prefix
|
25
|
+
msg.sub(bot.required_format, '').strip unless msg.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def subscribe &block
|
29
|
+
channel.subscribe &block
|
30
|
+
end
|
31
|
+
|
32
|
+
def push(msg)
|
33
|
+
channel.push msg
|
34
|
+
end
|
35
|
+
alias_method :<<, :push
|
36
|
+
|
37
|
+
def connect!
|
38
|
+
raise NotImplementedError, "connect! must be implemented"
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def channel
|
44
|
+
@channel ||= EM::Channel.new
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/scamp/matcher.rb
CHANGED
@@ -1,106 +1,30 @@
|
|
1
1
|
class Scamp
|
2
2
|
class Matcher
|
3
|
-
attr_accessor :conditions, :trigger, :action, :bot, :required_prefix
|
4
|
-
|
3
|
+
attr_accessor :on, :conditions, :trigger, :action, :bot, :required_prefix
|
4
|
+
|
5
5
|
def initialize(bot, params = {})
|
6
|
-
params ||= {}
|
7
6
|
params[:conditions] ||= {}
|
7
|
+
params[:on] ||= bot.adapters.keys
|
8
|
+
raise ArgumentError, "matcher must have a trigger" unless params[:trigger]
|
9
|
+
raise ArgumentError, "matcher must have a action" unless params[:action]
|
8
10
|
params.each { |k,v| send("#{k}=", v) }
|
9
11
|
@bot = bot
|
10
12
|
end
|
11
|
-
|
12
|
-
def attempt(msg)
|
13
|
-
|
14
|
-
|
15
|
-
if match
|
16
|
-
if match.is_a? MatchData
|
17
|
-
run(msg, match)
|
18
|
-
else
|
19
|
-
run(msg)
|
20
|
-
end
|
13
|
+
|
14
|
+
def attempt(channel, context, msg)
|
15
|
+
if listening?(channel) && msg.matches?(trigger) && msg.valid?(conditions)
|
16
|
+
run(context, msg)
|
21
17
|
return true
|
22
18
|
end
|
23
|
-
false
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def triggered_by(message_text)
|
29
|
-
if message_text && required_prefix
|
30
|
-
message_text = handle_prefix(message_text)
|
31
|
-
return false unless message_text
|
32
|
-
end
|
33
|
-
if trigger.is_a? String
|
34
|
-
return true if trigger == message_text
|
35
|
-
elsif trigger.is_a? Regexp
|
36
|
-
return trigger.match message_text
|
37
|
-
else
|
38
|
-
bot.logger.warn "Don't know what to do with #{trigger.inspect} at #{__FILE__}:#{__LINE__}"
|
39
|
-
end
|
40
|
-
false
|
19
|
+
return false
|
41
20
|
end
|
42
|
-
|
43
|
-
def
|
44
|
-
|
45
|
-
if required_prefix.is_a? String
|
46
|
-
if required_prefix == message_text[0...required_prefix.length]
|
47
|
-
message_text.gsub(required_prefix,'')
|
48
|
-
else
|
49
|
-
false
|
50
|
-
end
|
51
|
-
elsif required_prefix.is_a? Regexp
|
52
|
-
if required_prefix.match message_text
|
53
|
-
message_text.gsub(required_prefix,'')
|
54
|
-
else
|
55
|
-
false
|
56
|
-
end
|
57
|
-
else
|
58
|
-
false
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def run(msg, match = nil)
|
63
|
-
action_run = Action.new(bot, action, msg)
|
64
|
-
action_run.matches = match if match
|
65
|
-
action_run.run
|
21
|
+
|
22
|
+
def run(context, msg)
|
23
|
+
action.call(context, msg)
|
66
24
|
end
|
67
|
-
|
68
|
-
def conditions_satisfied_by(msg)
|
69
|
-
bot.logger.debug "Checking message against #{conditions.inspect}"
|
70
25
|
|
71
|
-
|
72
|
-
|
73
|
-
conditions.each do |item, cond|
|
74
|
-
bot.logger.debug "Checking #{item} against #{cond}"
|
75
|
-
bot.logger.debug "msg is #{msg.inspect}"
|
76
|
-
if cond.is_a? Integer
|
77
|
-
# bot.logger.debug "item is #{msg[{:room => :room_id, :user => :user_id}[item]]}"
|
78
|
-
return false unless msg[{:room => :room_id, :user => :user_id}[item]] == cond
|
79
|
-
elsif cond.is_a? String
|
80
|
-
case item
|
81
|
-
when :room
|
82
|
-
return false unless bot.room_name_for(msg[:room_id]) == cond
|
83
|
-
when :user
|
84
|
-
return false unless bot.username_for(msg[:user_id]) == cond
|
85
|
-
end
|
86
|
-
bot.logger.error "Don't know how to deal with a match item of #{item}, cond #{cond}"
|
87
|
-
elsif cond.is_a? Array
|
88
|
-
case item
|
89
|
-
when :room, :rooms
|
90
|
-
return cond.select {|e| e.is_a? Integer }.include?(msg[{:room => :room_id}[item]]) ||
|
91
|
-
cond.select {|e| e.is_a? String }.include?(bot.room_name_for(msg[:room_id]))
|
92
|
-
end
|
93
|
-
bot.logger.error "Don't know how to deal with a match item of #{item}, cond #{cond}"
|
94
|
-
elsif cond.is_a? Symbol
|
95
|
-
case item
|
96
|
-
when :type
|
97
|
-
return (cond == :text && msg[:type] == "TextMessage") ||
|
98
|
-
(cond == :paste && msg[:type] == "PasteMessage")
|
99
|
-
end
|
100
|
-
bot.logger.error "Don't know how to deal with a match item of #{item}, cond #{cond}"
|
101
|
-
end
|
102
|
-
end
|
103
|
-
true
|
26
|
+
def listening?(channel)
|
27
|
+
on.include?(channel)
|
104
28
|
end
|
105
29
|
end
|
106
30
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Scamp
|
2
|
+
class Matches
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize matches
|
6
|
+
@matches = matches
|
7
|
+
@matches.names.each do |name|
|
8
|
+
self.define_singleton_method name.to_sym do
|
9
|
+
matches[name.to_sym]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def [] index
|
15
|
+
@matches[1..-1][index]
|
16
|
+
end
|
17
|
+
|
18
|
+
def each
|
19
|
+
@matches[1..-1].each {|match| yield match }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'scamp/matches'
|
2
|
+
|
3
|
+
class Scamp
|
4
|
+
class Message
|
5
|
+
attr_reader :adapter, :match
|
6
|
+
|
7
|
+
def initialize(adapter, args={})
|
8
|
+
@adapter = adapter
|
9
|
+
args.each do |arg,value|
|
10
|
+
self.define_singleton_method arg do
|
11
|
+
value
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def valid? conditions
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def matches? trigger
|
21
|
+
match? trigger, body
|
22
|
+
end
|
23
|
+
|
24
|
+
def matches
|
25
|
+
Scamp::Matches.new(match) if match
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def match?(trigger, message)
|
31
|
+
if trigger.is_a? String
|
32
|
+
return true if trigger == message
|
33
|
+
elsif trigger.is_a? Regexp
|
34
|
+
return true if (@match = trigger.match message)
|
35
|
+
end
|
36
|
+
return false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/scamp/plugin.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
class Scamp
|
2
|
+
class Plugin
|
3
|
+
def self.matchers
|
4
|
+
@matchers ||= []
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.match trigger, method
|
8
|
+
self.matchers << [trigger, method]
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :bot, :options
|
12
|
+
|
13
|
+
def initialize bot, opts={}
|
14
|
+
@bot = bot
|
15
|
+
@options = opts
|
16
|
+
|
17
|
+
attach_matchers
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def matcher_options
|
22
|
+
{
|
23
|
+
:on => options[:on]
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def attach_matchers
|
28
|
+
self.class.matchers.each do |trigger, method_name|
|
29
|
+
@bot.match trigger, matcher_options, &Proc.new(&method(method_name))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/scamp/version.rb
CHANGED