""" The channel handler handles the stored set of channels and how they are represented against the cmdhandler. If there is a channel named 'newbie', we want to be able to just write > newbie Hello! For this to work, 'newbie', the name of the channel, must be identified by the cmdhandler as a command name. The channelhandler stores all channels as custom 'commands' that the cmdhandler can import and look through. Warning - channel names take precedence over command names, so make sure to not pick clashing channel names. Unless deleting a channel you normally don't need to bother about the channelhandler at all - the create_channel method handles the update. To delete a channel cleanly, delete the channel object, then call update() on the channelhandler. Or use Channel.objects.delete() which does this for you. """ from src.comms.models import ChannelDB, Msg from src.commands import cmdset, command from src.utils import utils class ChannelCommand(command.Command): """ Channel Usage: This is a channel. If you have subscribed to it, you can send to it by entering its name or alias, followed by the text you want to send. """ # this flag is what identifies this cmd as a channel cmd # and branches off to the system send-to-channel command # (which is customizable by admin) is_channel = True key = "general" help_category = "Channel Names" locks = "cmd:all()" obj = None def parse(self): """ Simple parser """ channelname, msg = self.args.split(":", 1) # cmdhandler sends channame:msg here. self.args = (channelname.strip(), msg.strip()) def func(self): """ Create a new message and send it to channel, using the already formatted input. """ channelkey, msg = self.args caller = self.caller if not msg: self.msg("Say what?") return channel = ChannelDB.objects.get_channel(channelkey) if not channel: self.msg("Channel '%s' not found." % channelkey) return if not channel.has_connection(caller): string = "You are not connected to channel '%s'." self.msg(string % channelkey) return if not channel.access(caller, 'send'): string = "You are not permitted to send to channel '%s'." self.msg(string % channelkey) return channel.msg(msg, senders=self.caller, online=True) class ChannelHandler(object): """ Handles the set of commands related to channels. """ def __init__(self): self.cached_channel_cmds = [] self.cached_cmdsets = {} def __str__(self): return ", ".join(str(cmd) for cmd in self.cached_channel_cmds) def clear(self): """ Reset the cache storage. """ self.cached_channel_cmds = [] def _format_help(self, channel): "builds a doc string" key = channel.key aliases = channel.aliases.all() ustring = "%s " % key.lower() + "".join(["\n %s " % alias.lower() for alias in aliases]) desc = channel.db.desc string = \ """ Channel '%s' Usage (not including your personal aliases): %s %s """ % (key, ustring, desc) return string def add_channel(self, channel): """ Add an individual channel to the handler. This should be called whenever a new channel is created. To remove a channel, simply delete the channel object and run self.update on the handler. """ # map the channel to a searchable command cmd = ChannelCommand(key=channel.key.strip().lower(), aliases=channel.aliases.all(), locks="cmd:all();%s" % channel.locks, obj=channel) cmd.__doc__= self._format_help(channel) self.cached_channel_cmds.append(cmd) self.cached_cmdsets = {} def update(self): "Updates the handler completely." self.cached_channel_cmds = [] self.cached_cmdsets = {} for channel in ChannelDB.objects.get_all_channels(): self.add_channel(channel) def get_cmdset(self, source_object): """ Retrieve cmdset for channels this source_object has access to send to. """ if source_object in self.cached_cmdsets: return self.cached_cmdsets[source_object] else: # create a new cmdset holding all channels chan_cmdset = cmdset.CmdSet() chan_cmdset.key = '_channelset' chan_cmdset.priority = 10 chan_cmdset.duplicates = True for cmd in [cmd for cmd in self.cached_channel_cmds if cmd.access(source_object, 'send')]: chan_cmdset.add(cmd) self.cached_cmdsets[source_object] = chan_cmdset return chan_cmdset CHANNELHANDLER = ChannelHandler()