]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - lib/rbot/message.rb
move rbot into lib - still rearranging for packaging/installation
[user/henk/code/ruby/rbot.git] / lib / rbot / message.rb
1 module Irc
2
3   # base user message class, all user messages derive from this
4   # (a user message is defined as having a source hostmask, a target
5   # nick/channel and a message part)
6   class BasicUserMessage
7     
8     # associated bot
9     attr_reader :bot
10     
11     # when the message was received
12     attr_reader :time
13
14     # hostmask of message source
15     attr_reader :source
16     
17     # nick of message source
18     attr_reader :sourcenick
19     
20     # url part of message source
21     attr_reader :sourceaddress
22     
23     # nick/channel message was sent to
24     attr_reader :target
25     
26     # contents of the message
27     attr_accessor :message
28
29     # has the message been replied to/handled by a plugin?
30     attr_accessor :replied
31
32     # instantiate a new Message
33     # bot::      associated bot class
34     # source::   hostmask of the message source
35     # target::   nick/channel message is destined for
36     # message::  message part
37     def initialize(bot, source, target, message)
38       @time = Time.now
39       @bot = bot
40       @source = source
41       @address = false
42       @target = target
43       @message = BasicUserMessage.stripcolour message
44       @replied = false
45
46       # split source into consituent parts
47       if source =~ /^((\S+)!(\S+))$/
48         @sourcenick = $2
49         @sourceaddress = $3
50       end
51       
52       if target && target.downcase == @bot.nick.downcase
53         @address = true
54       end
55       
56     end
57     
58     # returns true if the message was addressed to the bot.
59     # This includes any private message to the bot, or any public message
60     # which looks like it's addressed to the bot, e.g. "bot: foo", "bot, foo",
61     # a kick message when bot was kicked etc.
62     def address?
63       return @address
64     end
65
66     # has this message been replied to by a plugin?
67     def replied?
68       return @replied
69     end
70
71     # strip mIRC colour escapes from a string
72     def BasicUserMessage.stripcolour(string)
73       return "" unless string
74       ret = string.gsub(/\cC\d\d?(?:,\d\d?)?/, "")
75       #ret.tr!("\x00-\x1f", "")
76       ret
77     end
78
79   end
80
81   # class for handling IRC user messages. Includes some utilities for handling
82   # the message, for example in plugins.
83   # The +message+ member will have any bot addressing "^bot: " removed
84   # (address? will return true in this case)
85   class UserMessage < BasicUserMessage
86     
87     # for plugin messages, the name of the plugin invoked by the message
88     attr_reader :plugin
89     
90     # for plugin messages, the rest of the message, with the plugin name
91     # removed
92     attr_reader :params
93
94     # convenience member. Who to reply to (i.e. would be sourcenick for a
95     # privately addressed message, or target (the channel) for a publicly
96     # addressed message
97     attr_reader :replyto
98
99     # channel the message was in, nil for privately addressed messages
100     attr_reader :channel
101     
102     # for PRIVMSGs, true if the message was a CTCP ACTION (CTCP stuff
103     # will be stripped from the message)
104     attr_reader :action
105     
106     # instantiate a new UserMessage
107     # bot::      associated bot class
108     # source::   hostmask of the message source
109     # target::   nick/channel message is destined for
110     # message::  message part
111     def initialize(bot, source, target, message)
112       super(bot, source, target, message)
113       @target = target
114       @private = false
115       @plugin = nil
116       @action = false
117       
118       if target.downcase == @bot.nick.downcase
119         @private = true
120         @address = true
121         @channel = nil
122         @replyto = @sourcenick
123       else
124         @replyto = @target
125         @channel = @target
126       end
127
128       # check for option extra addressing prefixes, e.g "|search foo", or
129       # "!version" - first match wins
130       bot.addressing_prefixes.each {|mprefix|
131         if @message.gsub!(/^#{Regexp.escape(mprefix)}\s*/, "")
132           @address = true
133           break
134         end
135       }
136       
137       # even if they used above prefixes, we allow for silly people who
138       # combine all possible types, e.g. "|rbot: hello", or 
139       # "/msg rbot rbot: hello", etc
140       if @message.gsub!(/^\s*#{bot.nick}\s*([:;,>]|\s)\s*/, "")
141         @address = true
142       end
143       
144       if(@message =~ /^\001ACTION\s(.+)\001/)
145         @message = $1
146         @action = true
147       end
148       
149       # free splitting for plugins
150       @params = @message.dup
151       if @params.gsub!(/^\s*(\S+)[\s$]*/, "")
152         @plugin = $1.downcase
153         @params = nil unless @params.length > 0
154       end
155     end
156
157     # returns true for private messages, e.g. "/msg bot hello"
158     def private?
159       return @private
160     end
161
162     # returns true if the message was in a channel
163     def public?
164       return !@private
165     end
166
167     def action?
168       return @action
169     end
170
171     # convenience method to reply to a message, useful in plugins. It's the
172     # same as doing:
173     # <tt>@bot.say m.replyto, string</tt>
174     # So if the message is private, it will reply to the user. If it was
175     # in a channel, it will reply in the channel.
176     def reply(string)
177       @bot.say @replyto, string
178       @replied = true
179     end
180
181     # convenience method to reply "okay" in the current language to the
182     # message
183     def okay
184       @bot.say @replyto, @bot.lang.get("okay")
185     end
186
187   end
188
189   # class to manage IRC PRIVMSGs
190   class PrivMessage < UserMessage
191   end
192   
193   # class to manage IRC NOTICEs
194   class NoticeMessage < UserMessage
195   end
196
197   # class to manage IRC KICKs
198   # +address?+ can be used as a shortcut to see if the bot was kicked,
199   # basically, +target+ was kicked from +channel+ by +source+ with +message+
200   class KickMessage < BasicUserMessage
201     # channel user was kicked from
202     attr_reader :channel
203     
204     def initialize(bot, source, target, channel, message="")
205       super(bot, source, target, message)
206       @channel = channel
207     end
208   end
209
210   # class to pass IRC Nick changes in. @message contains the old nickame,
211   # @sourcenick contains the new one.
212   class NickMessage < BasicUserMessage
213     def initialize(bot, source, oldnick, newnick)
214       super(bot, source, oldnick, newnick)
215     end
216   end
217
218   class QuitMessage < BasicUserMessage
219     def initialize(bot, source, target, message="")
220       super(bot, source, target, message)
221     end
222   end
223
224   class TopicMessage < BasicUserMessage
225     # channel topic
226     attr_reader :topic
227     # topic set at (unixtime)
228     attr_reader :timestamp
229     # topic set on channel
230     attr_reader :channel
231
232     def initialize(bot, source, channel, timestamp, topic="")
233       super(bot, source, channel, topic)
234       @topic = topic
235       @timestamp = timestamp
236       @channel = channel
237     end
238   end
239
240   # class to manage channel joins
241   class JoinMessage < BasicUserMessage
242     # channel joined
243     attr_reader :channel
244     def initialize(bot, source, channel, message="")
245       super(bot, source, channel, message)
246       @channel = channel
247       # in this case sourcenick is the nick that could be the bot
248       @address = (sourcenick.downcase == @bot.nick.downcase)
249     end
250   end
251   
252   # class to manage channel parts
253   # same as a join, but can have a message too
254   class PartMessage < JoinMessage
255   end
256 end