Class: Rebot::Bot

Inherits:
Object
  • Object
show all
Defined in:
lib/rebot/bot.rb

Defined Under Namespace

Classes: Identity, InvalidToken

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(token:) ⇒ Bot

Returns a new instance of Bot.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/rebot/bot.rb', line 9

def initialize(token:)
  @token = token
  @identity = nil
  @api = ::Slack::Client.new(token: @token)

  @im_channel_ids = []
  @channel_ids    = []
  @group_ids      = []

  @message_count  = 0

  @ims            = []

  @convos         = []

  @connected = false
  @running = false
end

Instance Attribute Details

#identityObject (readonly)

Returns the value of attribute identity.



3
4
5
# File 'lib/rebot/bot.rb', line 3

def identity
  @identity
end

#tokenObject (readonly)

Returns the value of attribute token.



3
4
5
# File 'lib/rebot/bot.rb', line 3

def token
  @token
end

Class Method Details

.after(&block) ⇒ Object



196
197
198
# File 'lib/rebot/bot.rb', line 196

def after(&block)
  afters.push(block)
end

.aftersObject



188
189
190
# File 'lib/rebot/bot.rb', line 188

def afters
  @afters ||= []
end

.before(&block) ⇒ Object



200
201
202
# File 'lib/rebot/bot.rb', line 200

def before(&block)
  befores.push(block)
end

.beforesObject



192
193
194
# File 'lib/rebot/bot.rb', line 192

def befores
  @befores ||= []
end

.callbacks_for(type) ⇒ Object



160
161
162
163
164
165
166
# File 'lib/rebot/bot.rb', line 160

def callbacks_for(type)
  callbacks = @callbacks[type.to_sym] || []
  if superclass.respond_to?(:callbacks_for)
    callbacks += superclass.callbacks_for(type)
  end
  callbacks
end

.hears(pattern, &block) ⇒ Object



174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/rebot/bot.rb', line 174

def hears(pattern, &block)
  callback = Proc.new do |message|
    pattern = pattern.is_a?(String) ? Regexp.new(pattern, true) : pattern
    if match_data = pattern.match(message.text)
      debug "I heard #{pattern}"
      instance_exec(message, *match_data.captures, &block)
      false
    end
  end

  on(:dm, &callback)
  on(:mention, &callback)
end

.on(type, &block) ⇒ Object



168
169
170
171
172
# File 'lib/rebot/bot.rb', line 168

def on(type, &block)
  @callbacks ||= {}
  @callbacks[type.to_sym] ||= []
  @callbacks[type.to_sym] << block
end

Instance Method Details

#call(method, args) ⇒ Object



81
82
83
84
# File 'lib/rebot/bot.rb', line 81

def call(method, args)
  args.symbolize_keys!
  @api.send(method, args)
end

#connected?Boolean

Returns:

  • (Boolean)


137
138
139
# File 'lib/rebot/bot.rb', line 137

def connected?
  @connected
end

#conversation_ended(convo) ⇒ Object



155
156
157
# File 'lib/rebot/bot.rb', line 155

def conversation_ended(convo)
  @convos.delete(convo)
end

#reply(text_or_options) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/rebot/bot.rb', line 67

def reply(text_or_options)
  channel = @last_received_message.channel

  if text_or_options.is_a?(String)
    options = { channel: channel, text: text_or_options }
  elsif text_or_options.is_a?(Hash)
    options = text_or_options.merge(channel: channel)
  else
    raise "unreachable"
  end

  say(options)
end

#say(message) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/rebot/bot.rb', line 28

def say(message)
  @message_count += 1
  slack_message = {
    :id       => @message_count,
    :type     => "message",

    :channel      => message[:channel],
    :text         => message[:text] || "", # slack-web-api gem does not allow nil for text,
    :username     => message[:username],
    :parse        => message[:parse],
    :link_names   => message[:link_names],
    :attachments  => (message[:attachments] ? JSON.dump(message[:attachments]) : nil),
    :unfurl_links => message[:unfurl_links],
    :unfurl_media => message[:unfurl_media],
    :icon_url     => message[:icon_url],
    :icon_emoji   => message[:icon_emoji],
    :as_user      => message[:as_user] || true
  }

  #if (message[:icon_url] || message[:icon_emoji] || message[:username] )
  #  slack_message[:as_user] = false
  #else
  #  slack_message[:as_user] = message[:as_user] || true
  #end

  # These options are not supported by the RTM
  # so if they are specified, we use the web API to send messages.
  if slack_message[:attachments] || slack_message[:icon_emoji] || slack_message[:username] || slack_message[:icon_url]
    @api.chat_postMessage(slack_message)
  else
    @ws.send(JSON.dump(slack_message))
  end
end

#startObject



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/rebot/bot.rb', line 86

def start
  unless auth_test['ok']
    log "Error connecting bot (token: #{token}) to Slack: #{auth_test}"
    return
  end

  # TODO: it should be async
  rtm_start = @api.post('rtm.start')
  @identity = Identity.new(rtm_start['self']['name'], rtm_start['self']['id'])
  @ws = Faye::WebSocket::Client.new(rtm_start['url'], nil, ping: 60)

  @running = true
  @ws.on :open do |event|
    @connected = true
    log "connected to '#{team}'"
    load_im_channels
    load_channels
  end

  @ws.on :message do |event|
    begin
      debug event.data
      handle_event(event)
    rescue => e
      log error: e
      log backtrace: e.backtrace
      Rollbar.error(e)
    end
  end

  @ws.on :close do |event|
    log "disconnected"
    @connected = false
    @auth_test = nil
    if @running
      start
    end
  end

  EM.add_periodic_timer(1) do
    @convos.each { |convo| convo.tick }
  end
end

#start_conversation(name = nil, *args, &block) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/rebot/bot.rb', line 141

def start_conversation(name = nil, *args, &block)
  if name
    convo_block = Rebot.find_conversation(name)
  elsif block_given?
    convo_block = block
  else
    raise "Pass registered conversation name or block"
  end

  convo = Conversation.new(self, @last_received_message)
  @convos.push(convo)
  convo.start(convo_block, *args)
end

#stopObject



130
131
132
133
134
135
# File 'lib/rebot/bot.rb', line 130

def stop
  log "closing connection"
  @running = false
  @ws.close
  log "closed"
end

#to_sObject



223
224
225
# File 'lib/rebot/bot.rb', line 223

def to_s
  "<#{self.class.name} token:#{token}>"
end

#typingObject



62
63
64
65
# File 'lib/rebot/bot.rb', line 62

def typing
  @message_count += 1
  @ws.send(JSON.dump(channel: @last_received_message.channel, id: @message_count, type: "typing"))
end