lib/lita/handlers/markov.rb in lita-markov-1.0.2 vs lib/lita/handlers/markov.rb in lita-markov-1.1.0
- old
+ new
@@ -1,22 +1,32 @@
# Forward definition of Markov handler class
class Lita::Handlers::Markov < Lita::Handler; end
+require 'oj'
require 'lita/handlers/markov/engine'
module Lita::Handlers
class Markov
+ template_root File.expand_path('../../../../templates', __FILE__)
+
config :database_url, type: String, required: true
route(/.+/, :ingest, command: false)
route(/markov (.+)/, :generate, command: true, help: {
'markov USER' => 'Generate a markov chain from the given user.'
})
+ http.get '/markov/backlog', :backlog_form
+ http.post '/markov/upload_backlog', :upload_backlog
+
+ # Share the engine instance between all instances of the bot
+ def self.engine(instance)
+ @engine ||= Engine.new(instance.config.database_url)
+ end
def engine
- @engine ||= Engine.new config.database_url
+ self.class.engine(self)
end
def ingest(chat)
# Don't ingest messages addressed to ourselves
return if chat.command?
@@ -45,25 +55,70 @@
rescue Engine::EmptyDictionaryError
chat.reply "Looks like #{name} hasn't said anything!"
end
end
- def save_dictionary(name, dictionary)
- redis.set key_for_user(name), dictionary.to_json
+ def backlog_form(request, response)
+ render_backlog_form response
end
- def dictionary_for_user(name)
- key = key_for_user name
- dictionary = Dictionary.new name
- json = redis.get key
+ def upload_backlog(request, response)
+ t0 = Time.now
- dictionary.load_json(json) if json
+ response.headers['Content-Type'] = 'text/plain'
- dictionary
+ multipart = Rack::Multipart.parse_multipart request.env
+ tempfile = multipart.values.first[:tempfile]
+
+ begin
+ messages = Oj.load File.read(tempfile.path).strip, :mode => :strict
+ rescue Oj::ParseError => error
+ response.write error.message
+ return
+ end
+
+ messages.select! { |m| m['type'] == 'message' }
+
+ users = {}
+ find_user = proc do |id|
+ users[id] ||= Lita::User.fuzzy_find id
+ end
+
+ meta_tag_regex = /<(\w|[!|@])+>/
+
+ count = 0
+ messages.each do |message|
+ count += 1
+
+ begin
+ text = message['text'.freeze]
+ next unless text
+
+ user = find_user.call message['user'.freeze]
+ unless user
+ response.write "User not found for message ##{count}: #{message['user']}\n"
+ next
+ end
+
+ message = text.gsub meta_tag_regex, ''.freeze
+
+ engine.ingest user.id, message
+
+ if count % 1000 == 0
+ response.write "Processed #{count} messages\n"
+ end
+ rescue => error
+ response.write "Error writing message ##{count}: #{error.inspect}\n"
+ end
+ end
+
+ response.write "Processed #{count} total messages in #{Time.now - t0} seconds\n"
end
- def key_for_user(name)
- REDIS_KEY_PREFIX+name.downcase
+ private
+
+ def render_backlog_form(response)
+ response.write render_template('backlog_form')
end
Lita.register_handler self
end
end