Class: SkillActions

Inherits:
Object
  • Object
show all
Includes:
GoogleCalendarAbilities, MqttAbilities, SlackApiAbilities, SlackMessageAbilities, SlackQuestionAbilities, SlackRubyBot::Loggable, TimerAbilities
Defined in:
src/core/skill_actions.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from TimerAbilities

#schedule

Methods included from SlackQuestionAbilities

#ask_bool, #ask_options, #ask_string, #ask_time, #confirm

Methods included from SlackMessageAbilities

#react_with, #say

Methods included from SlackApiAbilities

#slack

Methods included from MqttAbilities

#mqtt

Methods included from GoogleCalendarAbilities

#google_calendar

Class Method Details

.listen_for(pattern, priority: 20) {|event| ... } ⇒ void

This method returns an undefined value.

Start listening for text in any channel the bot is invited to

Only one listener (across listen_for and on_intent) is called for a given message. The one that is chosen depends on their relative priorities.

Examples:

listen_for 'hi' do |event|
  say 'hello'
end
listen_for(/hi|yo|hell?o|hey/) do
  say 'hey there'
end

Parameters:

  • pattern (String, Regex)

    The text or pattern to listen for.

  • priority (Integer)

    Priority in relation to other listeners. The listener with more priority is preferred.

Yield Parameters:

  • event (MessageEvent)

    Called when a message matching the pattern is received.



83
84
85
# File 'src/core/skill_actions.rb', line 83

def listen_for(pattern, priority: 20, &block)
  skill.on_message(pattern, priority, &block)
end

.on_intent(intent, priority: 10) {|event| ... } ⇒ void

This method returns an undefined value.

Register a handler for a specific Wit.ai intent

See teach for how to configure intents.

Only one listener (across listen_for and on_intent) is called for a given message. The one that is chosen depends on their relative priorities.

Parameters:

  • intent (String)

    The intent to listen for.

  • priority (Integer)

    Priority in relation to other listeners. The listener with more priority is preferred.

Yield Parameters:

  • event (MessageEvent)

    Called when a message with this intent is received.



100
101
102
# File 'src/core/skill_actions.rb', line 100

def on_intent(intent, priority: 10, &block)
  skill.on_intent(intent, priority, &block)
end

.on_mqtt_message(topic, priority: 10) {|event| ... } ⇒ void

This method returns an undefined value.

Register a handler to be called when an MQTT message is received on a specific topic

Examples:

on_mqtt_message '/co2-athens/temp/temp' do |event|
  in_channel '#random-temperature' do
    say "It's getting hot in Athens" if event.data > 27
  end
end

Parameters:

  • topic (String, Array<String>)

    A topic to subscribe to.

  • priority (Integer)

    Priority relative to other on_reaction listeners.

Yield Parameters:



135
136
137
138
139
140
141
142
143
# File 'src/core/skill_actions.rb', line 135

def on_mqtt_message(topic, priority: 10, &block)
  unless skill.app.mqtt
    logger.error "Cannot subscribe to MQTT topic #{topic}, no MQTT connection is configured"
    return
  end

  skill.app.mqtt.subscribe(topic)
  skill.on_mqtt_message(topic, priority, &block)
end

.on_reaction(reactions, priority: 10, added: true, removed: false) {|event| ... } ⇒ void

This method returns an undefined value.

Register a handler for a reaction on any message in a channel the bot is a member of

Examples:

on_reaction '+1' do |event|
  react_with '-1' unless event.message_from_self?
end

Parameters:

  • reactions (Array<String>)

    A list of reactions to listen for. Reactions can include : or not. Example: [':+1:', 'zayo'].

  • priority (Integer)

    Priority relative to other on_reaction listeners.

  • added (Boolean)

    Trigger this listener when a reaction from the list is added.

  • removed (Boolean)

    Trigger this listener when a reaction from the list is removed.

Yield Parameters:



118
119
120
# File 'src/core/skill_actions.rb', line 118

def on_reaction(reactions, priority: 10, added: true, removed: false, &block)
  skill.on_reaction(reactions, priority, added: added, removed: removed, &block)
end

.on_start { ... } ⇒ void

This method returns an undefined value.

Provide a block to be called when the skill is started

The block is called as soon as Zayo starts and is connected to Slack. This makes it safe to directly send messages from this hook.

Note that the interaction here is started with empty context. This means that to use methods such as SlackMessageAbilities#say, you need to first provide a channel with #in_channel.

A skill may have only one start handler at a given time.

Examples:

on_start do
  in_channel '#random-zayo' do
    say ':wave:'
  end
end
EVERY_WEEKDAY_AT_9 = '0 9 * * 1-5'

on_start do
  schedule.cron EVERY_WEEKDAY_AT_9, :say_good_morning
end

def say_good_morning
  in_channel '#random-pleasantries' do
    say 'Good morning, everyone!'
  end
end

Yields:

  • []



46
47
48
# File 'src/core/skill_actions.rb', line 46

def on_start(&block)
  skill.on_start(&block)
end

.on_stop { ... } ⇒ void

TODO:

Not yet implemented

This method returns an undefined value.

Provide a block to be called when the skill is stopped

A skill may have only one stop handler at a given time.

Yields:

  • []



58
59
60
# File 'src/core/skill_actions.rb', line 58

def on_stop(&block)
  skill.on_stop(&block)
end

.strings(*keys) ⇒ String, ...

Get a string from the strings.yml file

Examples:

Given the following strings.yml

greeting: 'Hello'
greetings:
  morning: 'Good Morning'
  evening: 'Good Evening'

Getting a single-level string

strings(:greeting) # => Hello

Getting a nested string

strings(:greetings, :morning) # => Good Morning

Parameters:

  • key (String, Symbol, Array<String>)

    The path to the string in the strings.yml file.

Returns:

  • (String, nil, Object)

    The value associated with this key



161
162
163
# File 'src/core/skill_actions.rb', line 161

def strings(*keys)
  skill.app.strings.dig(*keys.map(&:to_s))
end

.teach(&block) ⇒ Object Also known as: learn

TODO:

Document this



166
167
168
169
170
# File 'src/core/skill_actions.rb', line 166

def teach(&block)
  samples = WitUpdateService::Samples.new.define(&block)

  skill.wit_samples = samples
end

Instance Method Details

#analyze_message(text) ⇒ Object



242
243
244
# File 'src/core/skill_actions.rb', line 242

def analyze_message(text)
  @app.request_wit_data(text)
end

#any_string(*keys) ⇒ Object



250
251
252
253
254
255
256
257
258
# File 'src/core/skill_actions.rb', line 250

def any_string(*keys)
  responses = strings(*keys)

  if responses.is_a? Array
    responses.sample
  else
    responses
  end
end

#await_next_responseObject



267
268
269
270
271
# File 'src/core/skill_actions.rb', line 267

def await_next_response
  channel, thread = response_defaults

  @interaction.await_next_response(channel, thread)
end

#contextObject



182
183
184
# File 'src/core/skill_actions.rb', line 182

def context
  @interaction.context
end

#humanize(stuff, *args) ⇒ Object



260
261
262
263
264
265
# File 'src/core/skill_actions.rb', line 260

def humanize(stuff, *args)
  case stuff
  when Date, Time, DateTime then HumanTime.new(stuff).humanize(*args)
  else stuff
  end
end

#in_channel(channel) { ... } ⇒ Object

Switch the current context to a different Slack channel

Inside the block, commands such as SlackMessageAbilities#say, SlackMessageAbilities#react_with and SlackQuestionAbilities#ask_string will send messages on this channel.

Examples:

in_channel '#random' do
  say 'This is sent to #random'

  in_channel '#random-food' do
    say "I'm hungry!"
  end

  say 'This is also sent to #random'
end

Parameters:

  • channel (String)

    The channel to switch the context to. May be either a channel name (e.g. random or #random), or a Slack channel ID (e.g. D1239C13).

Yields:

  • []

Returns:

  • (Object)

    Whatever has been returned from the block.



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'src/core/skill_actions.rb', line 222

def in_channel(channel)
  last_context = @interaction.context
  new_context = last_context.clone

  new_context.channel = Channel.new(@app, find_channel_id(channel))
  new_context.thread = nil
  new_context.initial_message = nil
  new_context.last_message = nil

  @interaction.context = new_context

  yield
ensure
  @interaction.context = last_context
end

#initial_channelObject

TODO: Make this an actual channel, not the id



187
188
189
# File 'src/core/skill_actions.rb', line 187

def initial_channel
  context.channel.id
end

#initial_threadObject

TODO: Make this an actual thread, not the id



192
193
194
# File 'src/core/skill_actions.rb', line 192

def initial_thread
  context.thread ? context.thread.id : nil
end

#interaction_idObject



196
197
198
# File 'src/core/skill_actions.rb', line 196

def interaction_id
  @interaction.id
end

#storage(&block) ⇒ Object



238
239
240
# File 'src/core/skill_actions.rb', line 238

def storage(&block)
  @app.storage.for_skill(@skill, &block)
end

#strings(*keys) ⇒ Object



246
247
248
# File 'src/core/skill_actions.rb', line 246

def strings(*keys)
  @app.strings.dig(*keys.flatten(1).map(&:to_s))
end