socrates 0.1.16 → 0.1.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/exe/socrates +8 -2
- data/lib/socrates/adapters/adapter.rb +63 -0
- data/lib/socrates/adapters/console.rb +13 -31
- data/lib/socrates/adapters/memory.rb +3 -23
- data/lib/socrates/adapters/slack.rb +13 -33
- data/lib/socrates/bots/cli.rb +3 -1
- data/lib/socrates/core/dispatcher.rb +2 -2
- data/lib/socrates/core/state.rb +3 -3
- data/lib/socrates/sample_states.rb +23 -0
- data/lib/socrates/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73a8be96fc0b04e14a3137c1ad12ab9a7bcecd88
|
4
|
+
data.tar.gz: 1b55c1e1a2422ce84e3a60d2317b44876862cfbb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4049f03b482773651d22cc6fa3dfb29d055fc1762d35a99b4fb7592fd8c1567240e6d552cb11712988df4e6173d73004ddee39b47470cfad32dd33a88c5f99c
|
7
|
+
data.tar.gz: 1dcaca7bed84ac8fb3219959ecf7fbec8fe5d52c66749842012d7252d64074a521fff2f9a972fcab92cf99e009a3e022f3f7d43bac5ef2c40effde5c6bb51923
|
data/exe/socrates
CHANGED
@@ -34,7 +34,7 @@ option_parser = OptionParser.new do |parser|
|
|
34
34
|
end
|
35
35
|
option_parser.parse!
|
36
36
|
|
37
|
-
def run_command(options)
|
37
|
+
def run_command(options) # rubocop:disable Metrics/MethodLength
|
38
38
|
storage =
|
39
39
|
case options[:storage]
|
40
40
|
when "redis"
|
@@ -54,9 +54,15 @@ def run_command(options)
|
|
54
54
|
|
55
55
|
case (adapter = options[:adapter])
|
56
56
|
when "console"
|
57
|
-
|
57
|
+
adapter = Socrates::Adapters::Console.new
|
58
|
+
adapter.add_user(id: 1, name: "joe", first: "Joe", last: "Smith", email: "joe@example.com")
|
59
|
+
adapter.add_user(id: 2, name: "rachel", first: "Rachel", last: "Doe", email: "rachel@example.com")
|
60
|
+
|
61
|
+
Socrates::Bots::CLI.new(adapter: adapter, state_factory: Socrates::SampleStates::StateFactory.new).start
|
62
|
+
|
58
63
|
when "slack"
|
59
64
|
Socrates::Bots::Slack.new(state_factory: Socrates::SampleStates::StateFactory.new).start
|
65
|
+
|
60
66
|
else
|
61
67
|
puts "Unknown adapter '#{adapter}'"
|
62
68
|
exit 1
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "socrates/adapters/stubs"
|
2
|
+
|
3
|
+
module Socrates
|
4
|
+
module Adapters
|
5
|
+
module Adapter
|
6
|
+
def client_id_from(_context: nil, _user: nil)
|
7
|
+
raise NotImplementedError
|
8
|
+
end
|
9
|
+
|
10
|
+
def channel_from(_context: nil, _user: nil)
|
11
|
+
raise NotImplementedError
|
12
|
+
end
|
13
|
+
|
14
|
+
def queue_message(session, message, send_now: false)
|
15
|
+
raise ArgumentError, "session is required" unless session.present?
|
16
|
+
raise ArgumentError, "session.channel is required" unless session.channel.present?
|
17
|
+
|
18
|
+
session.messages[session.channel] << message
|
19
|
+
flush_session(session, channel: session.channel) if send_now
|
20
|
+
end
|
21
|
+
|
22
|
+
def queue_direct_message(session, message, recipient)
|
23
|
+
raise ArgumentError, "recipient is required" unless recipient.present?
|
24
|
+
raise ArgumentError, "recipient.if is required" unless recipient.id.present?
|
25
|
+
|
26
|
+
dm_channel = channel_from(user: recipient)
|
27
|
+
|
28
|
+
session.messages[dm_channel] << message
|
29
|
+
end
|
30
|
+
|
31
|
+
def flush_session(session, channel: nil)
|
32
|
+
session.messages.select { |c, _| channel.nil? || channel == c }.each do |c, messages|
|
33
|
+
send_message(c, messages.join("\n\n"))
|
34
|
+
messages.clear
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def send_message(_channel, _message)
|
39
|
+
raise NotImplementedError
|
40
|
+
end
|
41
|
+
|
42
|
+
def user_from(_context:)
|
43
|
+
raise NotImplementedError
|
44
|
+
end
|
45
|
+
|
46
|
+
def users_list(*)
|
47
|
+
raise NotImplementedError
|
48
|
+
end
|
49
|
+
|
50
|
+
def lookup_user(_email:)
|
51
|
+
raise NotImplementedError
|
52
|
+
end
|
53
|
+
|
54
|
+
def lookup_email(*)
|
55
|
+
raise NotImplementedError
|
56
|
+
end
|
57
|
+
|
58
|
+
def users_channel(_user)
|
59
|
+
raise NotImplementedError
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -1,12 +1,13 @@
|
|
1
|
+
require "socrates/adapters/adapter"
|
1
2
|
require "socrates/adapters/stubs"
|
2
3
|
|
3
4
|
module Socrates
|
4
5
|
module Adapters
|
5
6
|
class Console
|
7
|
+
include Socrates::Adapters::Adapter
|
6
8
|
include StubUserDirectory
|
7
9
|
|
8
10
|
CLIENT_ID = "CONSOLE"
|
9
|
-
CHANNEL = "C1"
|
10
11
|
|
11
12
|
def initialize(name: "@socrates")
|
12
13
|
super()
|
@@ -22,41 +23,22 @@ module Socrates
|
|
22
23
|
def channel_from(context: nil, user: nil)
|
23
24
|
raise ArgumentError, "Must provide one of :context or :user" if context.nil? && user.nil?
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
session.messages[session.channel] << message
|
32
|
-
flush_session(session, channel: session.channel) if send_now
|
33
|
-
end
|
34
|
-
|
35
|
-
def send_direct_message(session, message, recipient)
|
36
|
-
raise ArgumentError, "User is required" unless recipient.present?
|
37
|
-
|
38
|
-
name =
|
39
|
-
if recipient.respond_to?(:name)
|
40
|
-
recipient.name
|
41
|
-
elsif recipient.respond_to?(:id)
|
42
|
-
recipient.id
|
43
|
-
else
|
44
|
-
recipient
|
45
|
-
end
|
46
|
-
|
47
|
-
session.messages[name] << message
|
48
|
-
end
|
49
|
-
|
50
|
-
def flush_session(session, channel: nil) # TODO: Dry this up? Session? Included module?
|
51
|
-
session.messages.select { |c, _| channel.nil? || channel == c }.each do |c, messages|
|
52
|
-
_send_message(c, messages.join("\n\n"))
|
53
|
-
messages.clear
|
26
|
+
if context&.fetch(:channel).present?
|
27
|
+
context[:channel]
|
28
|
+
elsif user.present?
|
29
|
+
display_user(user)
|
30
|
+
else
|
31
|
+
"?"
|
54
32
|
end
|
55
33
|
end
|
56
34
|
|
57
35
|
private
|
58
36
|
|
59
|
-
def
|
37
|
+
def display_user(user)
|
38
|
+
(user&.name || user&.id || user)&.upcase
|
39
|
+
end
|
40
|
+
|
41
|
+
def send_message(channel, message)
|
60
42
|
puts "\n#{colorize(channel, "34;1")}: #{message}"
|
61
43
|
end
|
62
44
|
|
@@ -1,8 +1,10 @@
|
|
1
|
+
require "socrates/adapters/adapter"
|
1
2
|
require "socrates/adapters/stubs"
|
2
3
|
|
3
4
|
module Socrates
|
4
5
|
module Adapters
|
5
6
|
class Memory
|
7
|
+
include Socrates::Adapters::Adapter
|
6
8
|
include StubUserDirectory
|
7
9
|
|
8
10
|
CLIENT_ID = "MEMORY"
|
@@ -28,28 +30,6 @@ module Socrates
|
|
28
30
|
user.nil? ? CHANNEL : users_channel(user)
|
29
31
|
end
|
30
32
|
|
31
|
-
def send_message(session, message, send_now: false)
|
32
|
-
raise ArgumentError, "Channel is required" unless session.channel.present?
|
33
|
-
|
34
|
-
session.messages[session.channel] << message
|
35
|
-
flush_session(session, channel: session.channel) if send_now
|
36
|
-
end
|
37
|
-
|
38
|
-
def send_direct_message(session, message, recipient)
|
39
|
-
raise ArgumentError, "Recipient is required" unless recipient.present?
|
40
|
-
|
41
|
-
im_channel = users_channel(recipient)
|
42
|
-
|
43
|
-
session.messages[im_channel] << message
|
44
|
-
end
|
45
|
-
|
46
|
-
def flush_session(session, channel: nil) # TODO: Dry this up? Session? Included module?
|
47
|
-
session.messages.select { |c, _| channel.nil? || channel == c }.each do |c, messages|
|
48
|
-
_send_message(c, messages.join("\n\n"))
|
49
|
-
messages.clear
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
33
|
#
|
54
34
|
# Methods for fetching messages and dms in specs...
|
55
35
|
#
|
@@ -72,7 +52,7 @@ module Socrates
|
|
72
52
|
|
73
53
|
private
|
74
54
|
|
75
|
-
def
|
55
|
+
def send_message(channel, message)
|
76
56
|
@history[channel] << message
|
77
57
|
end
|
78
58
|
|
@@ -1,8 +1,11 @@
|
|
1
1
|
require "active_support/core_ext/object"
|
2
|
+
require "socrates/adapters/adapter"
|
2
3
|
|
3
4
|
module Socrates
|
4
5
|
module Adapters
|
5
6
|
class Slack
|
7
|
+
include Socrates::Adapters::Adapter
|
8
|
+
|
6
9
|
def initialize(real_time_client)
|
7
10
|
@real_time_client = real_time_client
|
8
11
|
end
|
@@ -29,38 +32,6 @@ module Socrates
|
|
29
32
|
raise ArgumentError, "Must provide one of context or user"
|
30
33
|
end
|
31
34
|
|
32
|
-
def user_from(context:)
|
33
|
-
raise ArgumentError, "context cannot be nil" if context.nil?
|
34
|
-
raise ArgumentError, "Expected context to respond to :user" unless context.respond_to?(:user)
|
35
|
-
|
36
|
-
client = @real_time_client.web_client
|
37
|
-
info = client.users_info(user: context.user)
|
38
|
-
info.present? ? info.user : nil
|
39
|
-
end
|
40
|
-
|
41
|
-
def send_message(session, message, send_now: false)
|
42
|
-
raise ArgumentError, "session is required" unless session.present?
|
43
|
-
raise ArgumentError, "session.channel is required" unless session.channel.present?
|
44
|
-
|
45
|
-
session.messages[session.channel] << message
|
46
|
-
flush_session(session, channel: session.channel) if send_now
|
47
|
-
end
|
48
|
-
|
49
|
-
def send_direct_message(session, message, recipient)
|
50
|
-
raise ArgumentError, "Expected recipient to respond to :id" unless recipient.respond_to?(:id)
|
51
|
-
|
52
|
-
im_channel = lookup_im_channel(recipient)
|
53
|
-
|
54
|
-
session.messages[im_channel] << message
|
55
|
-
end
|
56
|
-
|
57
|
-
def flush_session(session, channel: nil) # TODO: Dry this up? Session? Included module?
|
58
|
-
session.messages.select { |c, _| channel.nil? || channel == c }.each do |c, messages|
|
59
|
-
_send_message(c, messages.join("\n\n"))
|
60
|
-
messages.clear
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
35
|
def users_list(include_deleted: false, include_bots: false)
|
65
36
|
client = @real_time_client.web_client
|
66
37
|
|
@@ -70,6 +41,15 @@ module Socrates
|
|
70
41
|
end
|
71
42
|
end
|
72
43
|
|
44
|
+
def user_from(context:)
|
45
|
+
raise ArgumentError, "context cannot be nil" if context.nil?
|
46
|
+
raise ArgumentError, "Expected context to respond to :user" unless context.respond_to?(:user)
|
47
|
+
|
48
|
+
client = @real_time_client.web_client
|
49
|
+
info = client.users_info(user: context.user)
|
50
|
+
info.present? ? info.user : nil
|
51
|
+
end
|
52
|
+
|
73
53
|
# Note: this triggers a call to the Slack API which makes it ill-suited for use within a loop.
|
74
54
|
def lookup_user(email:)
|
75
55
|
users_list.members.find { |user| email == user.profile&.email }
|
@@ -85,7 +65,7 @@ module Socrates
|
|
85
65
|
|
86
66
|
private
|
87
67
|
|
88
|
-
def
|
68
|
+
def send_message(channel, message)
|
89
69
|
@real_time_client.message(text: message, channel: channel)
|
90
70
|
end
|
91
71
|
|
data/lib/socrates/bots/cli.rb
CHANGED
@@ -46,7 +46,7 @@ module Socrates
|
|
46
46
|
persist_state_data(session.client_id, state_data)
|
47
47
|
|
48
48
|
# Send our initial message if one was passed to us.
|
49
|
-
@adapter.
|
49
|
+
@adapter.queue_direct_message(session, message, user) if message.present?
|
50
50
|
|
51
51
|
do_dispatch(session, nil)
|
52
52
|
true
|
@@ -172,7 +172,7 @@ module Socrates
|
|
172
172
|
@logger.warn "Error while processing action #{state.data.state_id}/#{state.data.state_action}: #{e.message}"
|
173
173
|
@logger.warn e
|
174
174
|
|
175
|
-
@adapter.
|
175
|
+
@adapter.queue_message(session, @error_message, send_now: true)
|
176
176
|
|
177
177
|
state.data.clear
|
178
178
|
state.data.state_id = nil
|
data/lib/socrates/core/state.rb
CHANGED
@@ -48,14 +48,14 @@ module Socrates
|
|
48
48
|
return if message.empty?
|
49
49
|
|
50
50
|
@logger.info %Q(#{@session.channel} send: "#{format_for_logging(message)}")
|
51
|
-
@adapter.
|
51
|
+
@adapter.queue_message(@session, message, send_now: send_now)
|
52
52
|
end
|
53
53
|
|
54
|
-
def send_message(to:, message:)
|
54
|
+
def send_message(to:, message:) # TODO: direct_message? send_dm?
|
55
55
|
displayable_to = to.respond_to?(:id) ? to.id : to
|
56
56
|
|
57
57
|
@logger.info %Q(#{@session.channel} send direct to #{displayable_to}: "#{format_for_logging(message)}")
|
58
|
-
@adapter.
|
58
|
+
@adapter.queue_direct_message(@session, message, to)
|
59
59
|
end
|
60
60
|
|
61
61
|
def transition_to(state_id, action: nil, data: {})
|
@@ -31,6 +31,8 @@ module Socrates
|
|
31
31
|
transition_to :help
|
32
32
|
when "age"
|
33
33
|
transition_to :ask_for_name
|
34
|
+
when "dms"
|
35
|
+
transition_to :dms
|
34
36
|
when "error"
|
35
37
|
transition_to :raise_error
|
36
38
|
else
|
@@ -47,6 +49,7 @@ module Socrates
|
|
47
49
|
Thanks for asking! I can do these things for you...
|
48
50
|
|
49
51
|
• `age` - Calculate your age from your birth date.
|
52
|
+
• `dms` - Sends a direct messages to two other users.
|
50
53
|
• `error` - Start a short error path that raises an error.
|
51
54
|
• `help` - Tell you what I can do for you.
|
52
55
|
|
@@ -167,6 +170,26 @@ module Socrates
|
|
167
170
|
end
|
168
171
|
end
|
169
172
|
|
173
|
+
class Dms
|
174
|
+
include Socrates::Core::State
|
175
|
+
|
176
|
+
def ask
|
177
|
+
respond message: "I will send whatever you type to two other users as direct messages."
|
178
|
+
end
|
179
|
+
|
180
|
+
def listen(message)
|
181
|
+
users = @adapter.users_list.members.sample(2)
|
182
|
+
|
183
|
+
users.each do |user|
|
184
|
+
send_message(to: user, message: "Message: #{message}")
|
185
|
+
end
|
186
|
+
|
187
|
+
respond message: "Direct messages sent!"
|
188
|
+
|
189
|
+
end_conversation
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
170
193
|
class RaiseError
|
171
194
|
include Socrates::Core::State
|
172
195
|
|
data/lib/socrates/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: socrates
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christian Nelson
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -170,6 +170,7 @@ files:
|
|
170
170
|
- circle.yml
|
171
171
|
- exe/socrates
|
172
172
|
- lib/socrates.rb
|
173
|
+
- lib/socrates/adapters/adapter.rb
|
173
174
|
- lib/socrates/adapters/console.rb
|
174
175
|
- lib/socrates/adapters/memory.rb
|
175
176
|
- lib/socrates/adapters/slack.rb
|