Skip to content

How to create a plugin

Daniel Kontšek edited this page Jul 24, 2016 · 22 revisions

Creating a core plugin

XMPP Extensions can be built into Ludolph core.

  1. In the ludolph/plugins directory create a new file with the name of your plugin, e.g. sample.py

  2. Inside that directory create a class with the same name as your file; it has to be a child of the LudolphPlugin class

     from ludolph.plugins.plugin import LudolphPlugin
    
     class Sample(LudolphPlugin):
         __version__ = __version__
         ...
    
  3. Each function with the @command decorator will be a Ludolph command

  4. Add a new section (it can be empty) named after your plugin file into the Ludolph configuration file; e.g. [sample]

  5. After reloading Ludolph you can use your plugin (check the log file in case of problems)

Creating a 3rd party plugin

Other extensions can be created as 3rd party plugins. Creating a 3rd party plugin is almost the same as creating a core plugin. One minor difference is that when registering with Ludolph configuration file use the whole python path for the section name (like a python import); e.g. [thirdparty.plugin.sample]

We have prepared a ludolph-skeleton repository that contains a hello_world plugin. Skeleton has a structure of a pip installable application (for hello_world installation see the repository README file). It contains a plugin with three sample commands, each using different decorators for sample usage.

Plugin naming convention

Project name = ludolph_<project>: where ludolph-<project> is a github and pypi package name.

Path to plugin = ludolph_<project>.<plugin>: where plugin is created from plugin class name, lower-cased and using underscores instead of spaces.

Plugin file structure convention

ludolph-skeleton           # Project name
├── LICENSE
├── MANIFEST.in
├── README.rst
├── ludolph_skeleton       # Python package
│   ├── __init__.py
│   └── hello_world.py     # Plugin name; the LudolphPlugin class must be called HelloWorld
└── setup.py

Plugin versions

Ludolph has a version command in its base set of commands. You can add version support to your plugin, by adding __version__ attribute into your plugin class.

from ludolph.plugins.plugin import LudolphPlugin
from sample_plugin import __version__

class SamplePlugin(LudolphPlugin):
    """
    Ludolph jabber bot sample plugin.
    """
    __version__ = __version__

Plugin initialization and cleanup

The preferred way to run some code during plugin initialization is to implement the __post_init__() method.

from ludolph.plugins.plugin import LudolphPlugin

class SamplePlugin(LudolphPlugin):
    __version__ = '1.0'
    foo = None

    def __post_init__(self):
        # You can read your plugin configuration here
        self.foo = self.config.get('foo, None)

    def __destroy__(self):
       # Do some cleanup here
       pass

In addition, you may also override the __init__(self, xmpp, config, reinit=False, **kwargs) method to do some early initialization stuff, e.g. check plugin dependencies. Just don't forget to call the parent __init__ method.

Persistent plugin data

Since Ludolph version 0.6.0 it is possible to enable a persistent DB file by setting the dbfile option in Ludolph's configuration file. Data are saved into the DB during the shutdown process and loaded when Ludolph starts. This offers the possibility not to loose data between restarts. Plugins can use this feature by setting the plugin instance attribute persistent_attrs to a collection of strings representing instance attribute names, that should be synced with the persistent DB. The values must be serializable by the pickle module.

from ludolph.command import command
from ludolph.plugins.plugin import LudolphPlugin

class SamplePlugin(LudolphPlugin):
    persistent_attrs = ('data',)
    data = None

    @command
    def some_command(self, msg):
        self.data = {'my': 'persistent data'}
        ...

Plugin commands

Please see the Commands wiki page.

Plugin webhooks and cronjobs

Please see the Webhooks and cron jobs wiki page.