class Ruboty::Adapters::LineBot

Public Instance Methods

init() click to toggle source
# File lib/ruboty/adapters/line_bot.rb, line 21
def init
  @queue = Queue.new
  @cached_contacts = {}
end
run() click to toggle source
# File lib/ruboty/adapters/line_bot.rb, line 15
def run
  init
  serve
  main_loop
end
say(message) click to toggle source
# File lib/ruboty/adapters/line_bot.rb, line 26
def say(message)
  client.send_text(
    to_mid: message[:original][:from_mid],
    text:   message[:body],
  )
end

Private Instance Methods

bind_address() click to toggle source
# File lib/ruboty/adapters/line_bot.rb, line 132
def bind_address
  ENV['WEBHOOK_BIND_ADDRESS'] || '0.0.0.0'
end
callback(env) click to toggle source
# File lib/ruboty/adapters/line_bot.rb, line 63
def callback(env)
  req = Rack::Request.new(env)

  unless req.request_method == 'POST'
    return [404, {}, ['Not found']]
  end

  signature = req.env['HTTP_X_LINE_CHANNELSIGNATURE']

  unless client.validate_signature(req.body.read, signature)
    return [400, {}, ['Bad Request']]
  end

  @queue.enq(req.env)

  [204, {}, []]
end
channel_id() click to toggle source
# File lib/ruboty/adapters/line_bot.rb, line 120
def channel_id
  ENV['LINE_CHANNEL_ID']
end
channel_mid() click to toggle source
# File lib/ruboty/adapters/line_bot.rb, line 128
def channel_mid
  ENV['LINE_CHANNEL_MID']
end
channel_secret() click to toggle source
# File lib/ruboty/adapters/line_bot.rb, line 124
def channel_secret
  ENV['LINE_CHANNEL_SECRET']
end
client() click to toggle source
# File lib/ruboty/adapters/line_bot.rb, line 35
def client
  @client ||= Line::Bot::Client.new do |config|
    config.channel_id     = channel_id
    config.channel_secret = channel_secret
    config.channel_mid    = channel_mid
  end
end
endpoint() click to toggle source
# File lib/ruboty/adapters/line_bot.rb, line 140
def endpoint
  ENV['WEBHOOK_ENDPOINT'] || '/callback'
end
main_loop() click to toggle source
# File lib/ruboty/adapters/line_bot.rb, line 81
def main_loop
  loop do
    request_from_queue.data.each do |event|
      next unless event.content.is_a?(Line::Bot::Message::Text)

      keys = [:id, :from_mid, :to_mid, :from_channel_id, :to_channel_id, :event_type, :created_time, :content]
      message = keys.each_with_object({}) {|key, hash| hash[key] = event.send(key) }

      unless contact = @cached_contacts[message[:from_mid]]
        contact = client.get_user_profile(message[:from_mid]).contacts.first
        @cached_contacts.update({
          contact.mid => {
            mid:            contact.mid,
            display_name:   contact.display_name,
            picture_url:    contact.picture_url,
            status_message: contact.status_message,
          }
        })
        contact = @cached_contacts[contact.mid]
      end

      message.update(
        body:      message[:content].content[:text],
        from:      message[:from_mid],
        from_name: contact[:display_name],
        to:        message[:to_mid],
        type:      message[:event_type],
      )
      Ruboty.logger.debug('Received:' + message.inspect)
      robot.receive(message)
    end
  end
end
port() click to toggle source
# File lib/ruboty/adapters/line_bot.rb, line 136
def port
  ENV['WEBHOOK_PORT'] || '4567'
end
request_from_queue() click to toggle source
# File lib/ruboty/adapters/line_bot.rb, line 115
def request_from_queue
  rack_raw_env = @queue.deq
  Line::Bot::Receive::Request.new(rack_raw_env)
end
serve() click to toggle source
# File lib/ruboty/adapters/line_bot.rb, line 43
def serve
  Thread.new do
    server.start
  end
  Thread.abort_on_exception = true
end
server() click to toggle source
# File lib/ruboty/adapters/line_bot.rb, line 50
def server
  return @server if @server

  @server = WEBrick::HTTPServer.new({
    BindAddress: bind_address,
    Port:        port,
    Logger:      Ruboty.logger,
  })
  @server.mount(endpoint, Rack::Handler::WEBrick, lambda(&method(:callback)))

  @server
end