socrates 0.1.16 → 0.1.17
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/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
|