The Python IRC Bot

Sopel tutorial, Part 3: Memory and URL info functions

NOTE: This guide is for Sopel 6.0+. If you are still using a version named “Willie”, we strongly encourage you to upgrade, as such old versions are no longer supported.

Communicating safely between plugins can be very useful. Sopel provides for this with its memory system. The intended use is for when you have volatile information which needs to be quickly and safely accessed and updated while the bot is running. In this part of the guide, we’re going to cover how to use it.

Memory basics

The bot object that gets passed to callables has the attribute memory, which works exactly like a plain old dict. (It’s really a SopelMemory object, but true to form, you don’t need to worry about how that works.) To see if a key is in the bot’s memory you use key in bot.memory, exactly like a plain old dict. If you want to access that key, you use bot.memory[key], exactly like a plain old dict. Keys can be strings (usually), but also numbers, tuples, etc., exactly like a plain old dict.

If you said “exactly like a plain old dict” before reading it just now, you’re definitely ready for an example.

Sample use: Keeping track of the last URL

One frequent use of memory is to keep track of the last URL that was seen in a channel. The bot currently ships with a .title command , found in, which will give the title or other URL information on the last URL posted in the channel. The plugin knows how to keep track of urls that other people say, but what about when Sopel itself says a URL, like as the result of the .duck command in, which gives the first link from a DuckDuckGo search of a given query? The answer is to put that link into memory.

What different memory keys exist and are used for is entirely by convention; the API spells out no special rules here. However, one of the ones used by the plugins the bot ships with is last_seen_url which, as you’d expect, contains the last seen URL. The key itself is a Python dict of channel names to the last URL seen in that channel. So when the .duck command wants to update it, it uses code like this:

    if 'last_seen_url' not in bot.memory:
        bot.memory['last_seen_url'] = SopelMemory()
    bot.memory['last_seen_url'][trigger.sender] = url

Where trigger.sender, as you’ll recall, is the channel (or nick, if a PM) the message came from, and url is the result from the search.

URL info functions

One of the things Sopel supports is advanced URL information. For example, Sopel can respond to a link to a YouTube video with not just the title, but the uploader, the time it was uploaded, the duration, and more. Here’s how it works. We only need to see four lines of it to get the gist; the rest is just retrieving the information from YouTube.

def ytinfo(bot, trigger, match):
    vid_id =

The first line gives Sopel a regex for URLs this function will handle - here we match both and links. The second line will seem a bit unusual compared to @rule and @command callables because of its third argument. When Sopel is calling this function, it will provide the regular expression match object in this third argument.

Want to learn about how to document (and test!) your plugin’s commands? Continue to part 4!