Skip to content

Latest commit

 

History

History
90 lines (63 loc) · 4.91 KB

How-to-write-a-plugin.md

File metadata and controls

90 lines (63 loc) · 4.91 KB

How to write a plugin

This document contains information about writing a Horta plugin.

General

Every plugin should be derived from the akka.actor.Actor trait because all Horta plugins integrate into Akka supervision tree and should be generally treated as actors.

To start your plugin with Horta you should add a corresponding akka.actor.Props entry to the ru.org.codingteam.horta.core.Core.plugins collection. See Akka documentation if you want to know more about akka.actor.Props.

Base types

It is a good idea to derive your plugin from the ru.org.codingteam.horta.plugins.BasePlugin type. This type provides some common plugin functionality. Inheritors should override name property. You also should override dao property if your plugin wants to store some data in the database (see the Database section below).

There are some base traits that help you implement shared plugin functionality such as command or message processing. These traits are described in the following sections.

CommandProcessor

Inherit from the ru.org.codingteam.horta.plugins.CommandProcessor trait if your plugin is going to process user commands. Command is a special message sent as a private message or as a multi-user chat message. Currently Horta has two syntax variants for commands: $syntax and syntax/. Read more about syntax variants in the user documentation.

To receive commands, your plugin should register them at core. Command registration is a declarative process. All you need to do is to prepare immutable ru.org.codingteam.horta.plugins.CommandDefinition objects and put them into commands property of your actor. CommandProcessor will take care of all the hidden machinery.

CommandDefinition allows you to set minimal access level for your command and to define its name (users will use it to invoke the command). CommandDefinition should also contain a so-called token. Token is an object used to determine which command was invoked. Horta core will send you back this token and command arguments.

Tokens meant to be Scala case objects. Be careful! Do not place case objects inside any classes. Scala will link the object and instance of the class, so every plugin instance will have its own token singleton. This behavior is known to cause all sorts of problems. You were warned.

MessageProcessor

If your plugin is supposed to receive all user messages, derive it from the ru.org.codingteam.horta.plugins.MessageProcessor trait. Override the processMessage method and do all the work there.

ParticipantProcessor

There is a ru.org.codingteam.horta.plugins.ParticipantProcessor trait for plugins which want to be notified of multi-user chat participant activity (users entering and leaving the chat). Derive from this trait and override the processParticipantJoin and processParticipantLeave methods if you want to process these messages.

RoomProcessor

The last - but not least - plugin trait is ru.org.codingteam.horta.plugins.RoomProcessor. It will notify the plugin when Horta enters and leaves various multi-user chats (and when some room-global events occur). Derive from the trait and override processRoomJoin, processRoomLeave and processRoomTopicChange methods to receive the notifications.

Database

If you want to persist some data in your plugin, you should use H2 database embedded in Horta.

Database structure

To define a database structure you should create a set of SQL scripts defining the data structure. All these SQL scripts should be stored in the src/main/resources/db/<plugin_name> directory (where <plugin_name> is the string that is defined in the name property of your plugin actor). We use FlyWay for automated data migrations. Be sure to check the basic documentation.

You should put scripts named V<number>__Script-definition.sql in your database directory. These scripts will be run automatically when your plugin accesses the database for the first time.

Data access

To access the data you should create a data access object. It should be derived from the ru.org.codingteam.horta.database.DAO trait. This trait provides a light protocol that your plugin should follow. Then publish your DAO to the system through overridden BasePlugin dao property.

After that, use asynchronous storage interface. Horta creates special store actor (you may access it with protected store property of a BasePlugin class). It will receive ru.org.codingteam.horta.database.StoreObject, ru.org.codingteam.horta.database.ReadObject and ru.org.codingteam.horta.database.DeleteObject messages and map them to calls of your DAO methods.

You should never try to create JDBC connections, data sources and such. Horta will take care of it and provide minimalistic interface through the DAO.