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