Kopachris / seshet

Modular, dynamic Python IRC bot
BSD 3-Clause "New" or "Revised" License
1 stars 1 forks source link

IRC user and channel lists #2

Open Kopachris opened 9 years ago

Kopachris commented 9 years ago

IRC Channel objects defined by ircutils3.protocol currently consist of a normalized (lowercase) channel name and a list of user names. To more effectively handle user list changes and other events, channels should have at least the following information associated with them:

Additionally, it might be useful to maintain a log of the last 100 or so events (or only messages) that have occurred in a given channel for spam protection and use by modules. A method, SeshetChannel.add_event(self, event) would maintain the log, removing old entries and adding new ones. Additional methods would be extremely useful for searching the log by user or message substring, optionally limiting the search to the last x entries or last y minutes.

The user list of a channel should consist of a mapping of normalized (lowercase) nicknames to user objects. ircutils3.protocol defines a User object, but it is not used by ircutils3.client in any meaningful way. Our user objects should have:

Just as it may be useful to maintain a channel log, it may also be useful to maintain a user log. The user log would be segregated by channel using a mapping of channel name to list of events, and the user log would normally be searched from the channel object. For example:

bot.channels['#botwar'].search_user_log('Kopachris', 'foo', 10)

would retrieve bot.channels['#botwar'].users['kopachris'].log[-10:] and search for the string 'foo'. Caching recent events in this way will cut down on database queries by modules which operate on recent, non-current events.

Finally, it would also make sense to allow user objects to handle their own state. This means the user object would be responsible for updating channel objects on join, part, quit, or nick change by having the bot's main event handlers call a user object's respective methods. For example:

def on_join(self, e):
    self.log('JOIN', e.source, '', e.target, e.user+'@'+e.host)
    if e.source in self.users:
        self.users[e.source].join(self.channels[e.target])
    else:
       # add user to self.users first
    ...

User.join(target) would then add the channel object to its own channel list and add a reference to itself in the channel object's user list.

Kopachris commented 9 years ago

It might also be a good idea to subclass UserDict or DefaultDict for the bot instance's channels and users lists, overriding __getitem__ and __setitem__ to convert all keys to lowercase strings (to make caps-insensitive) and validate channel names and nicknames.