boty 0.1.0 → 0.1.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +18 -1
- data/README.md +39 -3
- data/Rakefile +1 -1
- data/boty.gemspec +9 -5
- data/lib/boty.rb +2 -1
- data/lib/boty/action.rb +26 -35
- data/lib/boty/action_description.rb +24 -0
- data/lib/boty/bot.rb +36 -25
- data/lib/boty/dsl.rb +3 -3
- data/lib/boty/eventable.rb +4 -3
- data/lib/boty/http.rb +3 -4
- data/lib/boty/locale.rb +12 -13
- data/lib/boty/logger.rb +14 -3
- data/lib/boty/rspec.rb +15 -16
- data/lib/boty/session.rb +7 -8
- data/lib/boty/slack.rb +11 -3
- data/lib/boty/slack/channel.rb +2 -1
- data/lib/boty/slack/chat.rb +5 -1
- data/lib/boty/slack/rtm.rb +1 -1
- data/lib/boty/slack/url.rb +10 -5
- data/lib/boty/slack/user.rb +2 -1
- data/lib/boty/slack/users.rb +1 -1
- data/lib/boty/version.rb +1 -1
- data/script/knows.rb +10 -9
- data/script/pug.rb +5 -1
- data/spec/boty/bot_spec.rb +89 -72
- data/spec/boty/cli_spec.rb +5 -5
- data/spec/boty/dsl_spec.rb +12 -13
- data/spec/boty/rspec_spec.rb +2 -1
- data/spec/boty/script_loader_spec.rb +8 -6
- data/spec/boty/session_spec.rb +2 -2
- data/spec/boty/slack/chat_spec.rb +18 -18
- data/spec/boty/slack/im_spec.rb +4 -4
- data/spec/boty/slack/message_spec.rb +11 -9
- data/spec/boty/slack/rtm_spec.rb +3 -3
- data/spec/boty/slack/url_spec.rb +5 -5
- data/spec/boty/slack/users_spec.rb +23 -23
- data/spec/happy_path_spec.rb +19 -18
- data/spec/script/i18n_spec.rb +18 -10
- data/spec/script/knows_spec.rb +8 -7
- data/spec/script/pug_spec.rb +27 -10
- data/spec/script/remember_spec.rb +27 -21
- data/spec/spec_helper.rb +4 -3
- data/spec/support/em_support.rb +1 -3
- data/spec/support/faraday_support.rb +0 -1
- data/spec/support/faye_support.rb +9 -6
- data/spec/support/file_system_matchers.rb +4 -4
- data/spec/support/logger_support.rb +9 -12
- data/spec/support/session_support.rb +26 -15
- data/spec/support/slack_support.rb +9 -6
- data/spec/support/template_project_support.rb +24 -23
- data/spec/support/thor_support.rb +3 -3
- data/template/project/%bot_name%.rb +4 -1
- data/template/project/spec/spec_helper.rb +4 -2
- metadata +21 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7102960a8cdaa6f3a18a7015c1338f2c62a28b7
|
4
|
+
data.tar.gz: dfd326ea4c467506825ac473f47636682e366bab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bab25a32347e1c4e6cb9cc3b8f995fc4d971f094072ef6c5e54018e0d50b5fe37d8c86c9be5e4291a8e4c823cad802ffc2d8f86603a36141eed1ac4adfa7b0da
|
7
|
+
data.tar.gz: fb8d9bfa67bcbf7f624b69dc4f7866e7280ccb3be1a655c7117a124f26147ab7002bec1ec1f6736154ac0a57d33173a0f1a4a50e81d707ac703655586328c007
|
data/.rubocop.yml
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
boty (0.1.
|
4
|
+
boty (0.1.1)
|
5
5
|
eventmachine
|
6
6
|
faraday
|
7
7
|
faye-websocket
|
@@ -11,6 +11,9 @@ PATH
|
|
11
11
|
GEM
|
12
12
|
remote: https://rubygems.org/
|
13
13
|
specs:
|
14
|
+
ast (2.1.0)
|
15
|
+
astrolabe (1.3.1)
|
16
|
+
parser (~> 2.2)
|
14
17
|
byebug (8.2.0)
|
15
18
|
diff-lcs (1.2.5)
|
16
19
|
dotenv (2.0.2)
|
@@ -23,6 +26,10 @@ GEM
|
|
23
26
|
websocket-driver (>= 0.5.1)
|
24
27
|
i18n (0.7.0)
|
25
28
|
multipart-post (2.0.0)
|
29
|
+
parser (2.2.3.0)
|
30
|
+
ast (>= 1.1, < 3.0)
|
31
|
+
powerpack (0.1.1)
|
32
|
+
rainbow (2.0.0)
|
26
33
|
rake (10.4.2)
|
27
34
|
rspec (3.4.0)
|
28
35
|
rspec-core (~> 3.4.0)
|
@@ -37,7 +44,16 @@ GEM
|
|
37
44
|
diff-lcs (>= 1.2.0, < 2.0)
|
38
45
|
rspec-support (~> 3.4.0)
|
39
46
|
rspec-support (3.4.0)
|
47
|
+
rubocop (0.35.1)
|
48
|
+
astrolabe (~> 1.3)
|
49
|
+
parser (>= 2.2.3.0, < 3.0)
|
50
|
+
powerpack (~> 0.1)
|
51
|
+
rainbow (>= 1.99.1, < 3.0)
|
52
|
+
ruby-progressbar (~> 1.7)
|
53
|
+
tins (<= 1.6.0)
|
54
|
+
ruby-progressbar (1.7.5)
|
40
55
|
thor (0.19.1)
|
56
|
+
tins (1.6.0)
|
41
57
|
websocket-driver (0.6.3)
|
42
58
|
websocket-extensions (>= 0.1.0)
|
43
59
|
websocket-extensions (0.1.2)
|
@@ -53,6 +69,7 @@ DEPENDENCIES
|
|
53
69
|
fakefs
|
54
70
|
rake (~> 10.0)
|
55
71
|
rspec
|
72
|
+
rubocop
|
56
73
|
|
57
74
|
BUNDLED WITH
|
58
75
|
1.10.6
|
data/README.md
CHANGED
@@ -642,7 +642,7 @@ implementation is fairly simple. Let's use it as an example of how to write your
|
|
642
642
|
own adapter.
|
643
643
|
|
644
644
|
You can extend the ruby _Logger_ class and worry yourself on write the `#add`
|
645
|
-
|
645
|
+
override:
|
646
646
|
|
647
647
|
```ruby
|
648
648
|
class Multi < ::Logger
|
@@ -667,7 +667,7 @@ adapters passed as parameters for the constructor.
|
|
667
667
|
For more information on the `#add` parameters, [check the ruby doc](http://ruby-doc.org/stdlib-2.1.0/libdoc/logger/rdoc/Logger.html#method-i-add).
|
668
668
|
|
669
669
|
_Multi_ also allows you to change the level for all the underlying adapters at
|
670
|
-
once, the `#level=`
|
670
|
+
once, the `#level=` overriten implementation is like this:
|
671
671
|
|
672
672
|
```ruby
|
673
673
|
def level=(level)
|
@@ -679,7 +679,34 @@ end
|
|
679
679
|
|
680
680
|
### I18n
|
681
681
|
|
682
|
-
|
682
|
+
The descriptions for the commands and listeners that ship with `Boty` can be
|
683
|
+
customized via the [I18n gem mechanics](https://github.com/svenfuchs/i18n).
|
684
|
+
`Boty` ships with translations for `:en` and `:pt-br`. If you want to override
|
685
|
+
those messages, you can take a look at the files on [`locale`](https://github.com/ricardovaleriano/boty/tree/master/locale).
|
686
|
+
|
687
|
+
I'll recomend that you just copy and paste the file that you want to customize
|
688
|
+
on the `locale` dir of your project, and them make the editions that you want.
|
689
|
+
|
690
|
+
Of course, you can add translations for any language that you want on your
|
691
|
+
`locale` dir. And even add any translation that you want for your own
|
692
|
+
command descriptions.
|
693
|
+
|
694
|
+
To instruct your bot about which language to use, set the `Boty.locale`
|
695
|
+
configuration and you're done.
|
696
|
+
|
697
|
+
The `bot` executable created on your project generated by `boty new` have the
|
698
|
+
following line before the session start:
|
699
|
+
|
700
|
+
```ruby
|
701
|
+
Boty.locale = ARGV.pop || :en
|
702
|
+
```
|
703
|
+
|
704
|
+
This means that you can start your bot with a command line argument to tell
|
705
|
+
which is the idiom that this session should use. This allows you to have the
|
706
|
+
same bot running in different sessions with different idioms. The following
|
707
|
+
usage is totally fine:
|
708
|
+
|
709
|
+
./bot pt-br
|
683
710
|
|
684
711
|
## Development
|
685
712
|
|
@@ -691,8 +718,17 @@ To install this gem onto your local machine, run `bundle exec rake install`.
|
|
691
718
|
|
692
719
|
### The local ./bin/bot
|
693
720
|
|
721
|
+
The project have a `./bin/bot` executable that should be the product of
|
722
|
+
compiling the `template/project/bot.tt` erb file.
|
723
|
+
This is an easy way to just run the bot using the same logic that a project
|
724
|
+
generated by `bot new` will use to run the bot.
|
725
|
+
It's highly recomendable that you test your changes using this approach before
|
726
|
+
submit a `PR` or generate a new release. =)
|
727
|
+
|
694
728
|
### Code guidelines
|
695
729
|
|
730
|
+
**todo: add some**
|
731
|
+
|
696
732
|
## Contributing<a name="contributing" />
|
697
733
|
|
698
734
|
Bug reports and pull requests are very welcome on GitHub at
|
data/Rakefile
CHANGED
data/boty.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
lib = File.expand_path(
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
4
|
+
require "boty/version"
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "boty"
|
@@ -9,12 +9,15 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Ricardo Valeriano"]
|
10
10
|
spec.email = ["ricardo.valeriano@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary = %
|
13
|
-
spec.description = %
|
12
|
+
spec.summary = %(Boty is a pretty bot specially tailored for Slack.)
|
13
|
+
spec.description = %(Boty is intendted to be a framework for construction of
|
14
|
+
automated Slack Bots for your needs.)
|
14
15
|
spec.homepage = "http://github.com/ricardovaleriano/boty"
|
15
16
|
spec.license = "MIT"
|
16
17
|
|
17
|
-
spec.files = `git ls-files -z`.split("\x0").reject {
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject {|f|
|
19
|
+
f.match(%r{^(features)/})
|
20
|
+
}
|
18
21
|
spec.bindir = "exe"
|
19
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
23
|
spec.require_paths = ["lib"]
|
@@ -32,4 +35,5 @@ Gem::Specification.new do |spec|
|
|
32
35
|
spec.add_development_dependency "rspec"
|
33
36
|
spec.add_development_dependency "dotenv"
|
34
37
|
spec.add_development_dependency "fakefs"
|
38
|
+
spec.add_development_dependency "rubocop"
|
35
39
|
end
|
data/lib/boty.rb
CHANGED
@@ -13,7 +13,7 @@ require "faye/websocket"
|
|
13
13
|
require "i18n"
|
14
14
|
require "faraday"
|
15
15
|
|
16
|
-
|
16
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
17
17
|
|
18
18
|
module Boty
|
19
19
|
def self.locale=(lang)
|
@@ -29,6 +29,7 @@ require "boty/version"
|
|
29
29
|
require "boty/logger"
|
30
30
|
require "boty/slack"
|
31
31
|
require "boty/session"
|
32
|
+
require "boty/action_description"
|
32
33
|
require "boty/action"
|
33
34
|
require "boty/script_loader"
|
34
35
|
require "boty/dsl"
|
data/lib/boty/action.rb
CHANGED
@@ -1,53 +1,44 @@
|
|
1
1
|
module Boty
|
2
|
+
# Public: Wrap the idea of something that should happen when some regex is
|
3
|
+
# matched.
|
4
|
+
#
|
5
|
+
#
|
2
6
|
class Action
|
3
7
|
include Boty::Logger
|
4
8
|
attr_reader :regex, :desc, :action
|
5
9
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
if description.nil?
|
12
|
-
@description = command
|
13
|
-
else
|
14
|
-
@command, @description = command, description
|
15
|
-
end
|
16
|
-
|
17
|
-
@regex = regex
|
18
|
-
end
|
19
|
-
|
20
|
-
def command
|
21
|
-
return @command if @command
|
22
|
-
|
23
|
-
match = /\?(i?)-(mx|mix):(.*)\)/.match @regex.to_s
|
24
|
-
"/#{match[3]}/#{match[1]}"
|
10
|
+
def initialize(bot, regex, description, &action)
|
11
|
+
if description
|
12
|
+
description.regex = regex
|
13
|
+
else
|
14
|
+
description = ActionDescription.new(nil, regex: regex)
|
25
15
|
end
|
26
|
-
end
|
27
16
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
regex: regex)
|
33
|
-
@regex, @desc, @action = regex, description, action
|
17
|
+
@dsl = DSL.new bot
|
18
|
+
@regex = regex
|
19
|
+
@desc = description
|
20
|
+
@action = action
|
34
21
|
end
|
35
22
|
|
36
|
-
def
|
23
|
+
def this?(regex, block)
|
37
24
|
same_regex = regex == self.regex
|
38
|
-
block ? same_regex && block ==
|
25
|
+
block ? same_regex && block == action : same_regex
|
39
26
|
end
|
40
27
|
|
41
|
-
def execute(
|
42
|
-
|
43
|
-
if match = message.match!(regex)
|
44
|
-
matches = Array(match)
|
45
|
-
matches.shift
|
46
|
-
dsl.instance_exec(*matches, &action)
|
47
|
-
end
|
28
|
+
def execute(message)
|
29
|
+
action_call message.match!(regex)
|
48
30
|
rescue => e
|
49
31
|
logger.error e.message
|
50
32
|
raise e
|
51
33
|
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def action_call(match)
|
38
|
+
return unless match
|
39
|
+
matches = Array(match)
|
40
|
+
matches.shift
|
41
|
+
@dsl.instance_exec(*matches, &action)
|
42
|
+
end
|
52
43
|
end
|
53
44
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Boty
|
2
|
+
class ActionDescription
|
3
|
+
attr_reader :command, :description
|
4
|
+
attr_writer :regex
|
5
|
+
|
6
|
+
def initialize(command, description: nil, regex: nil)
|
7
|
+
if description.nil?
|
8
|
+
@description = command
|
9
|
+
else
|
10
|
+
@command = command
|
11
|
+
@description = description
|
12
|
+
end
|
13
|
+
|
14
|
+
@regex = regex
|
15
|
+
end
|
16
|
+
|
17
|
+
def command
|
18
|
+
return @command if @command
|
19
|
+
return unless @regex
|
20
|
+
match = /\?(i?)-(mx|mix):(.*)\)/.match @regex.to_s
|
21
|
+
@command = "/#{match[3]}/#{match[1]}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/boty/bot.rb
CHANGED
@@ -8,10 +8,14 @@ module Boty
|
|
8
8
|
|
9
9
|
def initialize(bot_info)
|
10
10
|
Locale.reload
|
11
|
-
@raw_info
|
11
|
+
@raw_info = bot_info
|
12
|
+
@id = bot_info["id"]
|
13
|
+
@name = bot_info["name"]
|
14
|
+
|
12
15
|
@listeners ||= []
|
13
16
|
@commands ||= []
|
14
17
|
@brain ||= {}
|
18
|
+
|
15
19
|
on :message, &method(:message_handler)
|
16
20
|
ScriptLoader.new(self).load
|
17
21
|
end
|
@@ -38,7 +42,8 @@ module Boty
|
|
38
42
|
end
|
39
43
|
|
40
44
|
def desc(command, description = nil)
|
41
|
-
@current_desc =
|
45
|
+
@current_desc = ActionDescription.new command,
|
46
|
+
description: description
|
42
47
|
end
|
43
48
|
|
44
49
|
def say(message, api_parameters = {})
|
@@ -49,33 +54,33 @@ module Boty
|
|
49
54
|
end
|
50
55
|
|
51
56
|
def im(text, destiny: nil, to: nil, user_id: nil)
|
52
|
-
|
53
|
-
|
57
|
+
destiny = User(user_id) || user_by_name(destiny, to)
|
58
|
+
if destiny
|
59
|
+
logger.debug do "Sending #{text} to #{destiny.name}." end
|
54
60
|
Slack.chat.post_im destiny.id, text
|
55
61
|
else
|
56
|
-
logger.debug
|
62
|
+
logger.debug do "User not found, refusing to send im." end
|
57
63
|
end
|
58
64
|
end
|
59
65
|
|
60
66
|
# TODO: return an Action object instead of a hash
|
61
67
|
def know_how
|
62
|
-
|
63
|
-
|
64
|
-
hsh.merge!(desc.command => desc.description)
|
65
|
-
}
|
68
|
+
actions = Array(@commands) + Array(@listeners)
|
69
|
+
actions.sort_by { |action| action.desc.command || "_" }
|
66
70
|
end
|
67
71
|
|
68
72
|
private
|
69
73
|
|
70
74
|
def remove_action(collection, regex = nil, block = nil, command: nil)
|
71
75
|
collection.delete_if do |action|
|
72
|
-
action.desc.command == command || action.
|
76
|
+
action.desc.command == command || action.this?(regex, block)
|
73
77
|
end
|
74
78
|
end
|
75
79
|
|
76
80
|
def user_by_name(destiny, to)
|
77
|
-
|
78
|
-
|
81
|
+
to ||= destiny
|
82
|
+
if to
|
83
|
+
Slack.users.by_name to
|
79
84
|
else
|
80
85
|
@trigger_message.user
|
81
86
|
end
|
@@ -83,34 +88,40 @@ module Boty
|
|
83
88
|
|
84
89
|
def create_action(regex, &block)
|
85
90
|
regex = Regexp.new(regex) if regex.is_a? String
|
86
|
-
Boty::Action.new(regex, @current_desc, &block).tap {
|
91
|
+
Boty::Action.new(self, regex, @current_desc, &block).tap {
|
87
92
|
@current_desc = nil
|
88
93
|
}
|
89
94
|
end
|
90
95
|
|
91
96
|
def message_from_bot_itself?(data)
|
92
|
-
data["user"] ==
|
97
|
+
data["user"] == id || data["user"] == name
|
93
98
|
end
|
94
99
|
|
95
|
-
def
|
100
|
+
def valid_mention?(data)
|
96
101
|
return false if message_from_bot_itself? data
|
97
|
-
|
102
|
+
|
103
|
+
if /(<@#{id}|#{name}>)/ =~ data["text"]
|
104
|
+
true
|
105
|
+
else
|
106
|
+
false
|
107
|
+
end
|
98
108
|
end
|
99
109
|
|
100
110
|
def message_handler(data)
|
101
111
|
unless data["text"]
|
102
|
-
return logger.debug "Non text message, just ignoring."
|
112
|
+
return logger.debug do "Non text message, just ignoring." end
|
103
113
|
end
|
114
|
+
actions = valid_mention?(data) ? @commands : @listeners
|
115
|
+
execute_all Message.new(data), actions
|
116
|
+
end
|
104
117
|
|
105
|
-
|
106
|
-
@trigger_message =
|
107
|
-
|
108
|
-
|
109
|
-
action.execute self, @trigger_message
|
110
|
-
end
|
111
|
-
ensure
|
112
|
-
@trigger_message = nil
|
118
|
+
def execute_all(message, actions)
|
119
|
+
@trigger_message = message
|
120
|
+
Array(actions).each do |action|
|
121
|
+
action.execute @trigger_message
|
113
122
|
end
|
123
|
+
ensure
|
124
|
+
@trigger_message = nil
|
114
125
|
end
|
115
126
|
end
|
116
127
|
end
|
data/lib/boty/dsl.rb
CHANGED
@@ -7,14 +7,14 @@ module Boty
|
|
7
7
|
INSTANCES = {}
|
8
8
|
private_constant :INSTANCES
|
9
9
|
class << self
|
10
|
-
|
10
|
+
alias_method :original_constructor, :new
|
11
11
|
end
|
12
12
|
|
13
13
|
attr_accessor :bot
|
14
14
|
|
15
15
|
extend Forwardable
|
16
|
-
def_delegators :bot,
|
17
|
-
|
16
|
+
def_delegators :bot,
|
17
|
+
:desc, :respond, :name, :brain, :know_how, :im, :say, :match
|
18
18
|
def_delegators :message, :user, :channel
|
19
19
|
|
20
20
|
def self.new(bot)
|