:default => 25,
:validate => Proc.new { |v| (0..100).include? v },
:desc => "Percentage chance of markov plugin chipping in")
- Config.register Config::ArrayValue.new('markov.ignore_users',
+ Config.register Config::ArrayValue.new('markov.ignore',
:default => [],
- :desc => "Hostmasks of users to be ignored")
+ :desc => "Hostmasks and channel names markov should NOT learn from (e.g. idiot*!*@*, #privchan).")
+ Config.register Config::IntegerValue.new('markov.max_words',
+ :default => 50,
+ :validate => Proc.new { |v| (0..100).include? v },
+ :desc => "Maximum number of words the bot should put in a sentence")
def initialize
super
@bot.config['markov.probability'] = @registry['probability']
@registry.delete('probability')
end
+ if @bot.config['markov.ignore_users']
+ debug "moving markov.ignore_users to markov.ignore"
+ @bot.config['markov.ignore'] = @bot.config['markov.ignore_users'].dup
+ @bot.config.delete('markov.ignore_users'.to_sym)
+ end
+ @learning_queue = Queue.new
+ @learning_thread = Thread.new do
+ while s = @learning_queue.pop
+ learn s
+ sleep 0.5
+ end
+ end
+ @learning_thread.priority = -1
+ end
+
+ def cleanup
+ debug 'closing learning thread'
+ @learning_queue.push nil
+ @learning_thread.join
+ debug 'learning thread closed'
end
def generate_string(word1, word2)
- # limit to max of 50 words
+ # limit to max of markov.max_words words
output = word1 + " " + word2
# try to avoid :nonword in the first iteration
word1, word2 = word2, word3
end
- 49.times do
+ (@bot.config['markov.max_words'] - 1).times do
wordlist = @registry["#{word1} #{word2}"]
break if wordlist.empty?
word3 = wordlist[rand(wordlist.length)]
def status(m,params)
if @bot.config['markov.enabled']
- m.reply "markov is currently enabled, #{probability?}% chance of chipping in"
+ reply = _("markov is currently enabled, %{p}% chance of chipping in") % { :p => probability? }
+ l = @learning_queue.length
+ reply << (_(", %{l} messages in queue") % {:l => l}) if l > 0
else
- m.reply "markov is currently disabled"
+ reply = _("markov is currently disabled")
end
+ m.reply reply
end
- def ignore?(user=nil)
- return false unless user
- @bot.config['markov.ignore_users'].each do |mask|
- return true if user.matches?(mask)
+ def ignore?(m=nil)
+ return false unless m
+ return true if m.address? or m.private?
+ @bot.config['markov.ignore'].each do |mask|
+ return true if m.channel.downcase == mask.downcase
+ return true if m.source.matches?(mask)
end
return false
end
user = params[:option]
case action
when 'remove':
- if @bot.config['markov.ignore_users'].include? user
- s = @bot.config['markov.ignore_users']
+ if @bot.config['markov.ignore'].include? user
+ s = @bot.config['markov.ignore']
s.delete user
- @bot.config['ignore_users'] = s
+ @bot.config['ignore'] = s
m.reply "#{user} removed"
else
m.reply "not found in list"
end
when 'add':
if user
- if @bot.config['markov.ignore_users'].include?(user)
+ if @bot.config['markov.ignore'].include?(user)
m.reply "#{user} already in list"
else
- @bot.config['markov.ignore_users'] = @bot.config['markov.ignore_users'].push user
+ @bot.config['markov.ignore'] = @bot.config['markov.ignore'].push user
m.reply "#{user} added to markov ignore list"
end
else
- m.reply "give the name of a person to ignore"
+ m.reply "give the name of a person or channel to ignore"
end
when 'list':
- m.reply "I'm ignoring #{@bot.config['markov.ignore_users'].join(", ")}"
+ m.reply "I'm ignoring #{@bot.config['markov.ignore'].join(", ")}"
else
- m.reply "have markov ignore the input from a hostmask. usage: markov ignore add <mask>; markov ignore remove <mask>; markov ignore list"
+ m.reply "have markov ignore the input from a hostmask or a channel. usage: markov ignore add <mask or channel>; markov ignore remove <mask or channel>; markov ignore list"
end
end
return unless should_talk
word1, word2 = message.split(/\s+/)
+ return unless word1 and word2
line = generate_string(word1, word2)
return unless line
- return if line == message
+ # we do nothing if the line we return is just an initial substring
+ # of the line we received
+ return if message.index(line) == 0
@bot.timer.add_once(delay) {
- m.reply line
+ m.reply line, :nick => false, :to => :public
}
end
def chat(m, params)
line = generate_string(params[:seed1], params[:seed2])
if line != "#{params[:seed1]} #{params[:seed2]}"
- m.reply line
+ m.reply line
else
m.reply "I can't :("
end
m.reply "I can't :("
end
end
-
- def listen(m)
- return unless m.kind_of?(PrivMessage) && m.public?
- return if m.address?
- return if ignore? m.source
+
+ def message(m)
+ return if ignore? m
# in channel message, the kind we are interested in
- message = clean_str m.message
+ message = clean_str m.plainmessage
if m.action?
message = "#{m.sourcenick} #{message}"
end
-
+
+ @learning_queue.push message
+ random_markov(m, message) unless m.replied?
+ end
+
+ def learn(message)
+ # debug "learning #{message}"
wordlist = message.split(/\s+/)
return unless wordlist.length >= 2
word1, word2 = :nonword, :nonword
end
k = "#{word1} #{word2}"
@registry[k] = @registry[k].push(:nonword)
-
- return if m.replied?
- random_markov(m, message)
end
end
plugin.map 'chat', :action => "rand_chat"
plugin.map 'markov probability [:probability]', :action => "probability",
:requirements => {:probability => /^\d+%?$/}
+
+plugin.default_auth('ignore', false)
+plugin.default_auth('probability', false)
+