ant-bot 0.1.0
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 +7 -0
- data/lib/ant/bot.rb +7 -0
- data/lib/ant/bot/adapters/base.rb +16 -0
- data/lib/ant/bot/adapters/debug.rb +145 -0
- data/lib/ant/bot/adapters/telegram.rb +38 -0
- data/lib/ant/bot/base.rb +164 -0
- data/lib/ant/bot/command_definition.rb +50 -0
- data/lib/ant/bot/message.rb +25 -0
- data/lib/ant/bot/version.rb +7 -0
- metadata +205 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a4e8ae082331aa86f94717547ed3ac9a4fd97182269363d3e280260d9cac9971
|
4
|
+
data.tar.gz: 2e19ddde3d123d08770e89c6b3a33ea8f745c365c812df04400e339a95763543
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d80353dd1bb1a77abfefbdbe7855981f119fd32f1de1c967b7644f6f4d98a0953b7c44e6ac4357c44a05c53e89f99237bcd68ad4e8bc59d959cd620048ec8c26
|
7
|
+
data.tar.gz: a3056348c47d1b6d7e4057dbc4dffafff1cd792201ac42d73efe038187fb49ffb1bd193af9bd8954f587f84c4744d1c33a4cdf58fe63d5e9919da8f8c9b89312
|
data/lib/ant/bot.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ant
|
4
|
+
module Bot
|
5
|
+
# Implements a factory singleton for building bot adapters
|
6
|
+
module Adapter
|
7
|
+
extend Ant::DRY::ResourceInjector
|
8
|
+
|
9
|
+
# builds the abstract adapter
|
10
|
+
def self.from_config(configs)
|
11
|
+
require_relative configs['name']
|
12
|
+
resource(configs['name']).new(configs)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ant
|
4
|
+
module Bot
|
5
|
+
# :nodoc: #
|
6
|
+
module Adapter
|
7
|
+
# :nodoc: #
|
8
|
+
# Wraps a debugging message inside a class.
|
9
|
+
class DebugMessage < Ant::Bot::Message
|
10
|
+
# It receives a string with the raw text and the id of the channel
|
11
|
+
def initialize(text, channel)
|
12
|
+
@text = text
|
13
|
+
@channel = channel
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the channel id
|
17
|
+
def channel_id
|
18
|
+
"debug_message__#{@channel}"
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the message contents
|
22
|
+
def raw_message
|
23
|
+
@text
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# This class simulates a message chat with a user.
|
28
|
+
class Channel
|
29
|
+
# It is build from
|
30
|
+
# an array of raw messages, the name of the channel and the config
|
31
|
+
# to enable debug messages
|
32
|
+
def initialize(messages, name, echo)
|
33
|
+
@state = :open
|
34
|
+
@pending_messages = messages
|
35
|
+
@name = name
|
36
|
+
@echo = echo
|
37
|
+
end
|
38
|
+
|
39
|
+
# Checks if there are messages open or that has not been answered
|
40
|
+
def open?
|
41
|
+
@state == :open
|
42
|
+
end
|
43
|
+
|
44
|
+
# Checks if there are still messages in the channel
|
45
|
+
def empty?
|
46
|
+
@pending_messages.empty?
|
47
|
+
end
|
48
|
+
|
49
|
+
# returns the next message in the buffer
|
50
|
+
def read_message
|
51
|
+
@state = :closed
|
52
|
+
DebugMessage.new(@pending_messages.shift, @name)
|
53
|
+
end
|
54
|
+
|
55
|
+
def send_data(message)
|
56
|
+
return unless @echo
|
57
|
+
|
58
|
+
puts "Sending message to channel: #{@name}"
|
59
|
+
puts message
|
60
|
+
end
|
61
|
+
|
62
|
+
def echo=(toogle)
|
63
|
+
@echo = toogle
|
64
|
+
end
|
65
|
+
|
66
|
+
# receives the answer from the bot
|
67
|
+
def answer(message)
|
68
|
+
send_data(message)
|
69
|
+
@state = :open
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# This adapter is intended to be used on unit tests and development.
|
75
|
+
class Debug
|
76
|
+
# Exception for stoping the loop of messages
|
77
|
+
class NoMoreMessageException < Ant::Exceptions::AntError
|
78
|
+
def initialize
|
79
|
+
super('There are no messages left')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# It receives a hash with the configurations:
|
84
|
+
# - name: the name of the channel
|
85
|
+
# - channels a key value, where the key is a name and the value the
|
86
|
+
# list of the messages in the channel.
|
87
|
+
# - echo: a flag to enable debug messages.
|
88
|
+
def initialize(configs)
|
89
|
+
@channels = {}
|
90
|
+
configs['channels'].each do |name, messages|
|
91
|
+
@channels[name] = Channel.new(messages, name, configs['echo'])
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Interface for receiving message
|
96
|
+
def read_message
|
97
|
+
# take the first message from the first open message,
|
98
|
+
# then rotate the array
|
99
|
+
loop do
|
100
|
+
raise NoMoreMessageException if @channels.values.all?(&:empty?)
|
101
|
+
|
102
|
+
msg = @channels.values.find(&:open?)
|
103
|
+
return msg.read_message if msg
|
104
|
+
|
105
|
+
# :nocov: #
|
106
|
+
sleep(1)
|
107
|
+
# :nocov: #
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# removes prefix from channel id
|
112
|
+
def channel(name)
|
113
|
+
@channels[name.gsub('debug_message__', '')]
|
114
|
+
end
|
115
|
+
|
116
|
+
# interface for sending messages
|
117
|
+
def send_message(channel_name, contents)
|
118
|
+
channel(channel_name).answer(contents)
|
119
|
+
end
|
120
|
+
|
121
|
+
# interface for sending video
|
122
|
+
def send_video(channel_name, video_url)
|
123
|
+
channel(channel_name).answer("VIDEO: #{video_url}")
|
124
|
+
end
|
125
|
+
|
126
|
+
# interface for sending uadio
|
127
|
+
def send_audio(channel_name, audio_url)
|
128
|
+
channel(channel_name).answer("AUDIO: #{audio_url}")
|
129
|
+
end
|
130
|
+
|
131
|
+
# interface for sending image
|
132
|
+
def send_image(channel_name, image_url)
|
133
|
+
channel(channel_name).answer("IMG: #{image_url}")
|
134
|
+
end
|
135
|
+
|
136
|
+
# changes echo config
|
137
|
+
def echo=(toogle)
|
138
|
+
@channels.each { |_, channel| channel.echo = toogle }
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
register('debug', Debug)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ant
|
4
|
+
module Bot
|
5
|
+
module Adapter
|
6
|
+
# Interface for connecting with telegram api
|
7
|
+
# TODO: Implement this
|
8
|
+
class Telegram
|
9
|
+
def initialize(configs); end
|
10
|
+
|
11
|
+
# Interface for receiving message
|
12
|
+
def read_message
|
13
|
+
raise
|
14
|
+
end
|
15
|
+
|
16
|
+
# interface for sending messages
|
17
|
+
def send_message(_channel, _contents)
|
18
|
+
raise
|
19
|
+
end
|
20
|
+
|
21
|
+
# interface for sending video
|
22
|
+
def send_video(_channel, _video_url)
|
23
|
+
raise
|
24
|
+
end
|
25
|
+
|
26
|
+
# interface for sending uadio
|
27
|
+
def send_audio(_channel, _audio_url)
|
28
|
+
raise
|
29
|
+
end
|
30
|
+
|
31
|
+
# interface for sending image
|
32
|
+
def send_image(_channel, _image_url)
|
33
|
+
raise
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/ant/bot/base.rb
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ant/dry/daemon'
|
4
|
+
require 'ant/bot/adapters/base'
|
5
|
+
require 'ant/storage'
|
6
|
+
require_relative 'command_definition'
|
7
|
+
|
8
|
+
require 'ant/logger'
|
9
|
+
|
10
|
+
module Ant
|
11
|
+
module Bot
|
12
|
+
# Base class for bot implementation. It wraps the threads execution, the
|
13
|
+
# provider and the state storage inside an object.
|
14
|
+
class Base
|
15
|
+
include Ant::Storage::Datasource
|
16
|
+
include Ant::Logger
|
17
|
+
# Configurations needed:
|
18
|
+
# - pool_size: number of threads created in execution
|
19
|
+
# - provider: a configuration for a thread provider.
|
20
|
+
# See supported adapters
|
21
|
+
# - name: The bot name
|
22
|
+
# - repository: Configurations about the state storage
|
23
|
+
def initialize(configs)
|
24
|
+
@pool_size = configs['pool_size']
|
25
|
+
@provider = Ant::Bot::Adapter.from_config(configs['provider'])
|
26
|
+
@commands = Ant::Bot::CommandDefinition.new
|
27
|
+
|
28
|
+
# TODO: move this to config
|
29
|
+
@repository = Ant::Storage::Repository.from_config(
|
30
|
+
nil,
|
31
|
+
{ 'name' => 'json',
|
32
|
+
'schema_name' => configs['name'],
|
33
|
+
'storage' => 'storage/$name',
|
34
|
+
'primary_key' => 'channel_id' },
|
35
|
+
{}
|
36
|
+
)
|
37
|
+
@factory = Ant::Storage::Factory.new(EmptyModel)
|
38
|
+
@factory.register(:default, :json)
|
39
|
+
@factory.register(:json, @repository)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Starts the bot execution, this is a blocking call.
|
43
|
+
def run
|
44
|
+
@pool = Array.new(@pool_size) do
|
45
|
+
# TODO: Create a subclass with the context execution
|
46
|
+
Ant::DRY::Daemon.new(@pool_size, true) do
|
47
|
+
message = @provider.read_message
|
48
|
+
process_message(message)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
# TODO: Implement an interface for killing the process
|
52
|
+
@pool.each(&:run)
|
53
|
+
# :nocov: #
|
54
|
+
@pool.each(&:await)
|
55
|
+
# :nocov: #
|
56
|
+
end
|
57
|
+
|
58
|
+
# Process a single message, this method can be overwriten to enable
|
59
|
+
# more complex implementations of commands. It receives a message object.
|
60
|
+
def process_message(message)
|
61
|
+
run_simple_command!(message)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Executes a command with the easiest definition. It runs a state machine:
|
65
|
+
# - If the message is a command, set the status to asking params
|
66
|
+
# - If the message is a param, stores it
|
67
|
+
# - If the command is ready to be executed, trigger it.
|
68
|
+
def run_simple_command!(message)
|
69
|
+
load_state!(message.channel_id)
|
70
|
+
log_debug('loaded state', message: message.to_h, state: @state.to_h)
|
71
|
+
if message.command?
|
72
|
+
self.command = message
|
73
|
+
else
|
74
|
+
add_param(message)
|
75
|
+
end
|
76
|
+
if command_ready?
|
77
|
+
run_command!
|
78
|
+
else
|
79
|
+
ask_param(next_missing_param)
|
80
|
+
end
|
81
|
+
save_state!
|
82
|
+
end
|
83
|
+
|
84
|
+
# DSL method for adding simple commands
|
85
|
+
def register_command(name, params, &block)
|
86
|
+
@commands.register_command(name, params, block)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Method for triggering command
|
90
|
+
def run_command!
|
91
|
+
current_command_object.execute(current_params)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Checks if the command is ready to be executed
|
95
|
+
def command_ready?
|
96
|
+
cmd = current_command_object
|
97
|
+
cmd.ready?(current_params)
|
98
|
+
end
|
99
|
+
|
100
|
+
# loads parameters from state
|
101
|
+
def current_params
|
102
|
+
@state[:params] || {}
|
103
|
+
end
|
104
|
+
|
105
|
+
# Loads command from state
|
106
|
+
def current_command_object
|
107
|
+
command = @state[:cmd]
|
108
|
+
@commands[command]
|
109
|
+
end
|
110
|
+
|
111
|
+
# returns the current_channel from where the message was sent
|
112
|
+
def current_channel
|
113
|
+
@state[:channel_id]
|
114
|
+
end
|
115
|
+
|
116
|
+
# stores the command into state
|
117
|
+
def command=(cmd)
|
118
|
+
log_debug('Message set as command', command: cmd)
|
119
|
+
|
120
|
+
@state[:cmd] = cmd.raw_message
|
121
|
+
@state[:params] = {}
|
122
|
+
end
|
123
|
+
|
124
|
+
# validates which is the following parameter required
|
125
|
+
def next_missing_param
|
126
|
+
current_command_object.next_missing_param(current_params)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Sends a message to get the next parameter from the user
|
130
|
+
def ask_param(param)
|
131
|
+
log_debug('I\'m going to ask the next param', param: param)
|
132
|
+
@provider.send_message(current_channel,
|
133
|
+
"I need you to tell me #{param}")
|
134
|
+
@state[:requested_param] = param
|
135
|
+
end
|
136
|
+
|
137
|
+
# Stores a parameter into the status
|
138
|
+
def add_param(value)
|
139
|
+
log_debug('Received new param',
|
140
|
+
param: @state[:requested_param].to_sym,
|
141
|
+
value: value)
|
142
|
+
|
143
|
+
@state[:params][@state[:requested_param].to_sym] = value.raw_message
|
144
|
+
end
|
145
|
+
|
146
|
+
# Loads the state from storage
|
147
|
+
def load_state!(channel)
|
148
|
+
@state = load_state(channel)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Private implementation for load message
|
152
|
+
def load_state(channel)
|
153
|
+
@factory.get(channel)
|
154
|
+
rescue Ant::Storage::Exceptions::ObjectNotFound
|
155
|
+
@factory.create(channel_id: channel, params: {})
|
156
|
+
end
|
157
|
+
|
158
|
+
# Saves the state into storage
|
159
|
+
def save_state!
|
160
|
+
@state.store
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ant
|
4
|
+
module Bot
|
5
|
+
# Object that wraps a command, it is analogus to a route definition.
|
6
|
+
# it currently only gets a param list, but it will be extended to a more
|
7
|
+
# complex DSL.
|
8
|
+
class Command
|
9
|
+
# Receives a list of params as symbols and the lambda with the block.
|
10
|
+
def initialize(params, block)
|
11
|
+
@params = params
|
12
|
+
@block = block
|
13
|
+
end
|
14
|
+
|
15
|
+
# Calls the block with the params list. Fails if there is a missing param
|
16
|
+
def execute(params)
|
17
|
+
raise 'NotReady' unless ready?(params)
|
18
|
+
|
19
|
+
@block.call(params)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Checks if the params object given contains all the needed values
|
23
|
+
def ready?(current_params)
|
24
|
+
@params.all? { |key| current_params.key?(key) }
|
25
|
+
end
|
26
|
+
|
27
|
+
# Finds the first empty param from the given parameter
|
28
|
+
def next_missing_param(current_params)
|
29
|
+
@params.find { |key| !current_params.key?(key) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Wraps a collection of commands.
|
34
|
+
class CommandDefinition
|
35
|
+
def initialize
|
36
|
+
@commands = {}
|
37
|
+
end
|
38
|
+
|
39
|
+
# Stores an operation definition
|
40
|
+
def register_command(name, params, block)
|
41
|
+
@commands[name] = Command.new(params, block)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns a command with the name
|
45
|
+
def [](name)
|
46
|
+
@commands[name]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ant/dry/daemon'
|
4
|
+
require 'ant/bot/adapters/base'
|
5
|
+
|
6
|
+
module Ant
|
7
|
+
module Bot
|
8
|
+
# Base implementation for messages from distinct providers
|
9
|
+
class Message
|
10
|
+
# Converts the messages into a hash
|
11
|
+
def to_h
|
12
|
+
{
|
13
|
+
text: raw_message,
|
14
|
+
channel: channel_id
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns true when the received message is a command. Convention states
|
19
|
+
# that messages should start with '/' to be considered commands
|
20
|
+
def command?
|
21
|
+
raw_message.start_with?('/')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,205 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ant-bot
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gilberto Vargas
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-10-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ant-core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: ant-logger
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.1'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: ant-storage
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.1'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.11'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '5.11'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mocha
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.8'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.8'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.12'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.12'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rack-minitest
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rake
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '12.3'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '12.3'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rdoc
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '6.1'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '6.1'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: simplecov
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0.16'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0.16'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: webmock
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '3.5'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '3.5'
|
167
|
+
description: Provides a framework for building bots with ruby
|
168
|
+
email:
|
169
|
+
- tachoguitar@gmail.com
|
170
|
+
executables: []
|
171
|
+
extensions: []
|
172
|
+
extra_rdoc_files: []
|
173
|
+
files:
|
174
|
+
- lib/ant/bot.rb
|
175
|
+
- lib/ant/bot/adapters/base.rb
|
176
|
+
- lib/ant/bot/adapters/debug.rb
|
177
|
+
- lib/ant/bot/adapters/telegram.rb
|
178
|
+
- lib/ant/bot/base.rb
|
179
|
+
- lib/ant/bot/command_definition.rb
|
180
|
+
- lib/ant/bot/message.rb
|
181
|
+
- lib/ant/bot/version.rb
|
182
|
+
homepage: https://github.com/tachomex/ant
|
183
|
+
licenses:
|
184
|
+
- MIT
|
185
|
+
metadata: {}
|
186
|
+
post_install_message:
|
187
|
+
rdoc_options: []
|
188
|
+
require_paths:
|
189
|
+
- lib
|
190
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
196
|
+
requirements:
|
197
|
+
- - ">="
|
198
|
+
- !ruby/object:Gem::Version
|
199
|
+
version: '0'
|
200
|
+
requirements: []
|
201
|
+
rubygems_version: 3.0.3
|
202
|
+
signing_key:
|
203
|
+
specification_version: 4
|
204
|
+
summary: Provides a framework for building bots with ruby
|
205
|
+
test_files: []
|