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