TODO don’t write unchanged config to disk
[six.git] / plugins / phrases.rb
blob7571e62353a1d28d17e05187b727c9fbaff1b240
2 # Phrases plugin for CyBot.
3 # Ciarán Walsh 13/5/07
5 # Recognises patterns and responds with a stored phrase
7 class Phrases < PluginBase
8   def initialize(*args)
9     @brief_help = 'Repeats stored phrases'
10     super(*args)
11   end
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
19     end
20     return nil
21   end
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
30     vars = {}
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 }
35     end
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 }
41   end
43   # Checks whether the user is allowed to use this plugin
44   # Informs them and returns false if not 
45   def authed?(irc)
46     if !$user.caps(irc, 'phrases', 'op', 'owner').any?
47       irc.reply "You aren't allowed to use this command"
48       return false
49     end
50     true
51   end
53   # Display a phrase for a given pattern
54   # Usage: $get <pattern>
55   def cmd_get(irc, phrase)
56     return unless authed?(irc)
57     
58     if phrase.nil? or phrase.strip.empty?
59       irc.reply 'USAGE: get <phrase>'
60       return
61     end
62     pattern, text = find_matching_phrase(phrase)
64     if pattern
65       irc.reply "#{pattern.inspect} => #{text}"
66     else
67       irc.reply "No phrase matched '#{phrase}'"
68     end
69   end
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+'
82       return
83     end
85     if pattern =~ %r|/(.+)/([eimnosux]*)|
86       begin
87         pat = Regexp.new($1, $2.empty? ? nil : $2)
88         @phrases[pat] = text
89       rescue Exception => e
90         irc.reply "Error compiling pattern"
91         return
92       end
93     else
94       @phrases[pattern] = text
95     end
96     irc.puts 'Phrase stored'
97   end
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>'
105       return
106     end
108     if pattern =~ %r|/(.+)/([eimnosux]*)|
109       begin
110         pattern = Regexp.new($1, $2.empty? ? nil : $2)
111       rescue Exception => e
112         irc.reply "Error compiling pattern"
113         return
114       end
115     end
116     if @phrases.delete(pattern)
117       irc.reply "Phrase #{pattern.inspect} deleted"
118     else
119       irc.reply "Phrase #{pattern.inspect} not found"
120     end
121   end
122   
123   def cmd_reload(irc, line)
124     return unless authed?(irc)
125     load
126     irc.reply 'Phrases reloaded from disk'
127   end
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)
132     if save
133       irc.reply 'Phrases saved to disk'
134     else
135       irc.reply "Couldn't write phrases to disk"
136     end
137   end
138         help :save, "Save phrases to disk."
140   # Load/save the phrases data
141   # These seem to be called automatically at (un)load
142   def load
143     begin
144       @phrases = YAML.load_file(file_name('phrases.yml'))
145     rescue Exception => e
146       @phrases = {}
147     end
148     @phrases = {} unless @phrases.is_a? Hash
149   end
150   def save
151     begin
152       open_file("phrases.yml", 'w') do |f|
153         f.puts "# CyBot phrases plugin"
154         YAML.dump(@phrases, f)
155         f.puts
156       end
157       return true
158     rescue Exception => e
159       Kernel.puts e.message
160       Kernel.puts e.backtrace.join("\n")
161     end
162     false
163   end