Class: Irc::Bot::Plugins::BotModule
- Inherits:
-
Object
- Object
- Irc::Bot::Plugins::BotModule
- Defined in:
- /home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb,
/home/apoc/projects/ruby/rbot/lib/rbot/core/utils/extends.rb,
/home/apoc/projects/ruby/rbot/lib/rbot/core/utils/filters.rb
Overview
BotModule is the base class for the modules that enhance the rbot
functionality. Rather than subclassing BotModule, however, one should
subclass either CoreBotModule (reserved for system modules) or Plugin
(for user plugins).
A BotModule interacts with Irc events by defining one or more of the following
methods, which get called as appropriate when the corresponding Irc event
happens.
map(template, options)::
map!(template, options)::
map is the new, cleaner way to respond to specific message formats without
littering your plugin code with regexps, and should be used instead of
#register() and #privmsg() (see below) when possible.
The difference between map and map! is that map! will not register the new
command as an alternative name for the plugin.
Examples:
plugin.map 'karmastats', :action => 'karma_stats'
# while in the plugin...
def karma_stats(m, params)
m.reply "..."
end
# the default action is the first component
plugin.map 'karma'
# attributes can be pulled out of the match string
plugin.map 'karma for :key'
plugin.map 'karma :key'
# while in the plugin...
def karma(m, params)
item = params[:key]
m.reply 'karma for #{item}'
end
# you can setup defaults, to make parameters optional
plugin.map 'karma :key', :defaults => {:key => 'defaultvalue'}
# the default auth check is also against the first component
# but that can be changed
plugin.map 'karmastats', :auth => 'karma'
# maps can be restricted to public or private message:
plugin.map 'karmastats', :private => false
plugin.map 'karmastats', :public => false
See MessageMapper#map for more information on the template format and the
allowed options.
listen(UserMessage)::
Called for all messages of any type. To
differentiate them, use message.kind_of? It'll be
either a PrivMessage, NoticeMessage, KickMessage,
QuitMessage, PartMessage, JoinMessage, NickMessage,
etc.
ctcp_listen(UserMessage)::
Called for all messages that contain a CTCP command.
Use message.ctcp to get the CTCP command, and
message.message to get the parameter string. To reply,
use message.ctcp_reply, which sends a private NOTICE
to the sender.
message(PrivMessage)::
Called for all PRIVMSG. Hook on this method if you
need to handle PRIVMSGs regardless of whether they are
addressed to the bot or not, and regardless of
privmsg(PrivMessage)::
Called for a PRIVMSG if the first word matches one
the plugin #register()ed for. Use m.plugin to get
that word and m.params for the rest of the message,
if applicable.
unreplied(PrivMessage)::
Called for a PRIVMSG which has not been replied to.
notice(NoticeMessage)::
Called for all Notices. Please notice that in general
should not be replied to.
kick(KickMessage)::
Called when a user (or the bot) is kicked from a
channel the bot is in.
invite(InviteMessage)::
Called when the bot is invited to a channel.
join(JoinMessage)::
Called when a user (or the bot) joins a channel
part(PartMessage)::
Called when a user (or the bot) parts a channel
quit(QuitMessage)::
Called when a user (or the bot) quits IRC
nick(NickMessage)::
Called when a user (or the bot) changes Nick
modechange(ModeChangeMessage)::
Called when a User or Channel mode is changed
topic(TopicMessage)::
Called when a user (or the bot) changes a channel
topic
welcome(WelcomeMessage)::
Called when the welcome message is received on
joining a server succesfully.
motd(MotdMessage)::
Called when the Message Of The Day is fully
recevied from the server.
connect:: Called when a server is joined successfully, but
before autojoin channels are joined (no params)
set_language(String)::
Called when the user sets a new language
whose name is the given String
save:: Called when you are required to save your plugin's
state, if you maintain data between sessions
cleanup:: called before your plugin is "unloaded", prior to a
plugin reload or bot quit - close any open
files/connections or flush caches here
Direct Known Subclasses
Instance Attribute Summary (collapse)
-
- (Object) bot
readonly
the associated bot.
-
- (Object) handler
readonly
the message map handler.
-
- (Object) registry
readonly
the plugin registry.
Instance Method Summary (collapse)
-
- (Object) botmodule_class
Returns the symbol :BotModule.
-
- (Object) call_event(ev, *args)
Signal to other BotModules that an even happened.
-
- (Object) cleanup
Method called to cleanup before the plugin is unloaded.
-
- (Object) datafile(*fname)
Filename for a datafile built joining the botclass, plugin dirname and actual file name.
-
- (Object) default_auth(cmd, val, chan = "*")
Sets the default auth for command path cmd to val on channel chan: usually chan is either “*” for everywhere, public and private (in which case it can be omitted) or “?” for private communications.
-
- (Object) define_filter(filter, &block)
define a filter defaulting to the default filter group for this BotModule.
-
- (Object) dirname
Directory name to be joined to the botclass to access data files.
-
- (Object) do_map(silent, *args)
Auxiliary method called by #map and #map!.
-
- (Object) fake_message(string, opts = {})
Sometimes plugins need to create a new fake message based on an existing message: for example, this is done by alias, linkbot, reaction and remotectl.
-
- (Object) filter_group
read accessor for the default filter group for this BotModule.
-
- (Object) filter_group=(name)
write accessor for the default filter group for this BotModule.
-
- (Object) flush_registry
Method called to flush the registry, thus ensuring that the botmodule's permanent data is committed to disk.
-
- (Object) handle(m)
Handle an Irc::PrivMessage for which this BotModule has a map.
-
- (Object) help(plugin, topic)
Return a help string for your module.
-
- (BotModule) initialize
constructor
Initialise your bot module.
-
- (Object) load_filters(options = {})
load filters associated with the BotModule by looking in the path(s) specified by the :path option, defaulting to * Config::datadir/filters/.rb * botclass/filters/.rb (note that as we use #dirname() rather than #name(), since we're looking for datafiles; this is only relevant for the very few plugins whose dirname differs from name).
-
- (Object) map(*args)
call-seq: map(template, options).
-
- (Object) map!(*args)
call-seq: map!(template, options).
-
- (Object) name
Return an identifier for this plugin, defaults to a list of the message prefixes handled (used for error messages etc).
-
- (Object) priority
Changing the value of @priority directly will cause problems, Please use priority=.
-
- (Object) priority=(prio)
Define the priority of the module.
-
- (Object) propose_default_path(cmd)
Gets the default command path which would be given to command cmd.
-
- (Object) register(cmd, opts = {})
Register the plugin as a handler for messages prefixed cmd.
-
- (Object) to_s
Just calls name.
-
- (Object) to_sym
Intern the name.
-
- (Object) usage(m, params = {})
Default usage method provided as a utility for simple plugins.
Constructor Details
- (BotModule) initialize
Initialise your bot module. Always call super if you override this method, as important variables are set up for you:
- @bot
-
the rbot instance
- @registry
-
the botmodule's registry, which can be used to store permanent data (see Registry::Accessor for additional documentation)
Other instance variables which are defined and should not be overwritten byt the user, but aren't usually accessed directly, are:
- @manager
-
the plugins manager instance
- @botmodule_triggers
-
an Array of words this plugin #register()ed itself for
- @handler
-
the MessageMapper that handles this plugin's maps
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 182 def initialize @manager = Plugins::manager @bot = @manager.bot @priority = nil @botmodule_triggers = Array.new @handler = MessageMapper.new(self) @registry = @bot.registry_factory.create(@bot.path, self.class.to_s.gsub(/^.*::/, '')) @manager.add_botmodule(self) if self.respond_to?('set_language') self.set_language(@bot.lang.language) end end |
Instance Attribute Details
- (Object) bot (readonly)
the associated bot
155 156 157 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 155 def bot @bot end |
- (Object) handler (readonly)
the message map handler
161 162 163 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 161 def handler @handler end |
- (Object) registry (readonly)
the plugin registry
158 159 160 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 158 def registry @registry end |
Instance Method Details
- (Object) botmodule_class
Returns the symbol :BotModule
205 206 207 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 205 def botmodule_class :BotModule end |
- (Object) call_event(ev, *args)
Signal to other BotModules that an even happened.
236 237 238 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 236 def call_event(ev, *args) @bot.plugins.delegate('event_' + ev.to_s.gsub(/[^\w\?!]+/, '_'), *(args.push Hash.new)) end |
- (Object) cleanup
Method called to cleanup before the plugin is unloaded. If you overload this method to handle additional cleanup tasks, remember to call super() so that the default cleanup actions are taken care of as well.
221 222 223 224 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 221 def cleanup # debug "Closing #{@registry}" @registry.close end |
- (Object) datafile(*fname)
Filename for a datafile built joining the botclass, plugin dirname and actual file name
375 376 377 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 375 def datafile(*fname) @bot.path dirname, *fname end |
- (Object) default_auth(cmd, val, chan = "*")
Sets the default auth for command path cmd to val on channel chan: usually chan is either “*” for everywhere, public and private (in which case it can be omitted) or “?” for private communications
277 278 279 280 281 282 283 284 285 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 277 def default_auth(cmd, val, chan="*") case cmd when "*", "" c = nil else c = cmd end Auth::defaultbotuser.(propose_default_path(c), val) end |
- (Object) define_filter(filter, &block)
define a filter defaulting to the default filter group for this BotModule
166 167 168 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/core/utils/filters.rb', line 166 def define_filter(filter, &block) @bot.register_filter(filter, self.filter_group, &block) end |
- (Object) dirname
Directory name to be joined to the botclass to access data files. By default this is the plugin name itself, but may be overridden, for example by plugins that share their datafiles or for backwards compatibilty
369 370 371 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 369 def dirname name end |
- (Object) do_map(silent, *args)
Auxiliary method called by #map and #map!
259 260 261 262 263 264 265 266 267 268 269 270 271 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 259 def do_map(silent, *args) @handler.map(self, *args) # register this map map = @handler.last name = map.items[0] self.register name, :auth => nil, :hidden => silent @manager.register_map(self, map) unless self.respond_to?('privmsg') def self.privmsg(m) #:nodoc: handle(m) end end end |
- (Object) fake_message(string, opts = {})
Sometimes plugins need to create a new fake message based on an existing message: for example, this is done by alias, linkbot, reaction and remotectl.
This method simplifies the message creation, including a recursion depth check.
In the options you can specify the :bot, the :server, the :source, the :target, the message :class and whether or not to :delegate. To initialize these entries from an existing message, you can use :from
Additionally, if :from is given, the reply method of created message is overriden to reply to :from instead. The #in_thread attribute for created mesage is also copied from :from
If you don't specify a :from you should specify a :source.
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/core/utils/extends.rb', line 505 def (string, opts={}) if from = opts[:from] o = { :bot => from.bot, :server => from.server, :source => from.source, :target => from.target, :class => from.class, :delegate => true, :depth => from.recurse_depth + 1 }.merge(opts) else o = { :bot => @bot, :server => @bot.server, :target => @bot.myself, :class => PrivMessage, :delegate => true, :depth => 1 }.merge(opts) end raise RecurseTooDeep if o[:depth] > MAX_RECURSE_DEPTH new_m = o[:class].new(o[:bot], o[:server], o[:source], o[:target], string) new_m.recurse_depth = o[:depth] if from # the created message will reply to the originating message, but we # must remember to set 'replied' on the fake message too, to # prevent infinite loops that could be created for example with the reaction # plugin by setting up a reaction to ping with cmd:ping class << new_m self end.send(:define_method, :reply) do |*args| debug "replying to '#{from.}' with #{args.first}" from.reply(*args) new_m.replied = true end # the created message will follow originating message's in_thread new_m.in_thread = from.in_thread if from.respond_to?(:in_thread) end return new_m unless o[:delegate] method = o[:class].to_s.gsub(/^Irc::|Message$/,'').downcase method = 'privmsg' if method == 'priv' o[:bot].plugins.irc_delegate(method, new_m) end |
- (Object) filter_group
read accessor for the default filter group for this BotModule
155 156 157 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/core/utils/filters.rb', line 155 def filter_group @filter_group ||= name end |
- (Object) filter_group=(name)
write accessor for the default filter group for this BotModule
160 161 162 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/core/utils/filters.rb', line 160 def filter_group=(name) @filter_group = name end |
- (Object) flush_registry
Method called to flush the registry, thus ensuring that the botmodule's permanent data is committed to disk
212 213 214 215 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 212 def flush_registry # debug "Flushing #{@registry}" @registry.flush end |
- (Object) handle(m)
Handle an Irc::PrivMessage for which this BotModule has a map. The method is called automatically and there is usually no need to call it explicitly.
230 231 232 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 230 def handle(m) @handler.handle(m) end |
- (Object) help(plugin, topic)
Return a help string for your module. For complex modules, you may wish to
break your help into topics, and return a list of available topics if
topic
is nil. plugin
is passed containing the
matching prefix for this message - if your plugin handles multiple
prefixes, make sure you return the correct help for the prefix requested
313 314 315 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 313 def help(plugin, topic) "no help" end |
- (Object) load_filters(options = {})
load filters associated with the BotModule by looking in the path(s) specified by the :path option, defaulting to
-
Config::datadir/filters/<name>.rb
-
botclass/filters/<name>.rb
(note that as <name> we use #dirname() rather than #name(), since we're looking for datafiles; this is only relevant for the very few plugins whose dirname differs from name)
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/core/utils/filters.rb', line 177 def load_filters(={}) case [:path] when nil us = "#{self.dirname}.rb" paths = [ File.join(Config::datadir, 'filters', us), @bot.path('filters', us) ] when Array paths = [:path] else paths = [[:path]] end paths.each do |file| instance_eval(File.read(file), file) if File.exist?(file) end end |
- (Object) map(*args)
call-seq: map(template, options)
This is the preferred way to register the BotModule so that it responds to appropriately-formed messages on Irc.
245 246 247 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 245 def map(*args) do_map(false, *args) end |
- (Object) map!(*args)
call-seq: map!(template, options)
This is the same as map but doesn't register the new command as an alternative name for the plugin.
254 255 256 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 254 def map!(*args) do_map(true, *args) end |
- (Object) name
Return an identifier for this plugin, defaults to a list of the message prefixes handled (used for error messages etc)
294 295 296 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 294 def name self.class.to_s.downcase.sub(/^#<module:.*?>::/,"").sub(/(plugin|module)?$/,"") end |
- (Object) priority
Changing the value of @priority directly will cause problems, Please use priority=.
200 201 202 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 200 def priority @priority ||= 1 end |
- (Object) priority=(prio)
Define the priority of the module. During event delegation, lower priority modules will be called first. Default priority is 1
358 359 360 361 362 363 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 358 def priority=(prio) if @priority != prio @priority = prio @bot.plugins.mark_priorities_dirty end end |
- (Object) propose_default_path(cmd)
Gets the default command path which would be given to command cmd
288 289 290 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 288 def propose_default_path(cmd) [name, cmd].compact.join("::") end |
- (Object) register(cmd, opts = {})
Register the plugin as a handler for messages prefixed cmd.
This can be called multiple times for a plugin to handle multiple message prefixes.
This command is now superceded by the #map() command, which should be used instead whenever possible.
325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 325 def register(cmd, opts={}) raise ArgumentError, "Second argument must be a hash!" unless opts.kind_of?(Hash) who = @manager.who_handles?(cmd) if who raise "Command #{cmd} is already handled by #{who.botmodule_class} #{who}" if who != self return end if opts.has_key?(:auth) @manager.register(self, cmd, opts[:auth]) else @manager.register(self, cmd, propose_default_path(cmd)) end @botmodule_triggers << cmd unless opts.fetch(:hidden, false) end |
- (Object) to_s
Just calls name
299 300 301 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 299 def to_s name end |
- (Object) to_sym
Intern the name
304 305 306 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 304 def to_sym self.name.to_sym end |
- (Object) usage(m, params = {})
Default usage method provided as a utility for simple plugins. The MessageMapper uses 'usage' as its default fallback method.
343 344 345 346 347 348 349 350 351 352 353 354 |
# File '/home/apoc/projects/ruby/rbot/lib/rbot/plugins.rb', line 343 def usage(m, params = {}) if params[:failures].respond_to? :find friendly = params[:failures].find do |f| f.kind_of? MessageMapper::FriendlyFailure end if friendly m.reply friendly.friendly return end end m.reply(_("incorrect usage, ask for help using '%{command}'") % {:command => "#{@bot.nick}: help #{m.plugin}"}) end |