2 # Phrases plugin for CyBot.
5 # Recognises patterns and responds with a stored phrase
7 class Phrases < PluginBase
9 @brief_help = 'Repeats stored phrases'
13 # Check a message against the phrase list
14 # Returns nil, or an array of the matching pattern and response text if one is found
15 def find_matching_phrase(msg)
16 return nil if msg[0] == ?$ # Ignore commands
17 @phrases.each do |(pattern, text)|
18 return [pattern, text.dup] if pattern === msg
23 # Called for all incoming channel messages
24 # Checks the message for a phrase match and replies
25 def hook_privmsg_chan(irc, msg)
26 pattern, text = find_matching_phrase(msg)
27 return unless pattern and text
29 # The hash of replacement variables that can be used in a response phrase
31 # Add the matches from the pattern to the replacement hash if applicable
32 if pattern.is_a? Regexp
33 pattern =~ msg # Why is this necessary??
34 Regexp.last_match.captures.each_with_index { |cap, index| vars['$' + (index+1).to_s] = cap }
36 vars['me'] = irc.server.nick
37 vars['you'] = irc.from.nick
39 vars.each_pair { |name, val| text.gsub!('[' + name + ']', val.to_s) }
40 irc.puts text#.gsub(/\[(.+?)\]/) { |match| vars.has_key?($1) ? vars[$1] : $1 }
43 # Checks whether the user is allowed to use this plugin
44 # Informs them and returns false if not
46 if !$user.caps(irc, 'phrases', 'op', 'owner').any?
47 irc.reply "You aren't allowed to use this command"
53 # Display a phrase for a given pattern
54 # Usage: $get <pattern>
55 def cmd_get(irc, phrase)
56 return unless authed?(irc)
58 if phrase.nil? or phrase.strip.empty?
59 irc.reply 'USAGE: get <phrase>'
62 pattern, text = find_matching_phrase(phrase)
65 irc.reply "#{pattern.inspect} => #{text}"
67 irc.reply "No phrase matched '#{phrase}'"
70 help :get, "Display a phrase for a given pattern. To set phrases use 'set'"
72 # Set the phrase for a pattern
73 # Usage: $set <pattern> => <phrase>
74 def cmd_set(irc, line)
75 return unless authed?(irc)
76 (pattern, text) = line.strip.split(/\s*=>\s*/, 2)
78 if !pattern || !text || pattern.empty? || text.empty?
79 irc.reply 'Usage: set <pattern> => <response phrase>'
80 irc.reply 'Pattern can be a constant phrase or a /rege/x'
81 irc.reply 'Response phrase can contain [variables]: me, you, $1+'
85 if pattern =~ %r|/(.+)/([eimnosux]*)|
87 pat = Regexp.new($1, $2.empty? ? nil : $2)
90 irc.reply "Error compiling pattern"
94 @phrases[pattern] = text
96 irc.puts 'Phrase stored'
98 help :set, "Set the phrase for a pattern.Usage: set <pattern> => <response phrase>. Pattern can be a constant phrase or a /rege/x./ Response phrase can contain [variables]: me, you, $1+."
100 def cmd_del(irc, pattern)
101 return unless authed?(irc)
103 if pattern.nil? or pattern.strip.empty?
104 irc.reply 'USAGE: del <pattern>'
108 if pattern =~ %r|/(.+)/([eimnosux]*)|
110 pattern = Regexp.new($1, $2.empty? ? nil : $2)
111 rescue Exception => e
112 irc.reply "Error compiling pattern"
116 if @phrases.delete(pattern)
117 irc.reply "Phrase #{pattern.inspect} deleted"
119 irc.reply "Phrase #{pattern.inspect} not found"
123 def cmd_reload(irc, line)
124 return unless authed?(irc)
126 irc.reply 'Phrases reloaded from disk'
128 help :reload, "Reloads all phrases from disk. Make sure to save any changes you've made first."
130 def cmd_save(irc, line)
131 return unless authed?(irc)
133 irc.reply 'Phrases saved to disk'
135 irc.reply "Couldn't write phrases to disk"
138 help :save, "Save phrases to disk."
140 # Load/save the phrases data
141 # These seem to be called automatically at (un)load
144 @phrases = YAML.load_file(file_name('phrases.yml'))
145 rescue Exception => e
148 @phrases = {} unless @phrases.is_a? Hash
152 open_file("phrases.yml", 'w') do |f|
153 f.puts "# CyBot phrases plugin"
154 YAML.dump(@phrases, f)
158 rescue Exception => e
159 Kernel.puts e.message
160 Kernel.puts e.backtrace.join("\n")