Jabber (XMPP) bot with extendability using Python plugins.
- Erlang R16B or newer
- Python 2.7.x
- autotools and rebar for building
git clone https://github.com/Mendor/urusai.git
cd urusai
make deps
make
Configuration example can be found in default.config.sample
. You may edit this file and rename it to default.config
later or create new configuration file based on this one. Look inside it for configuration details.
./start.sh default
Where default
is the base name for your configuration (default.config
in this case).
Send to the bot subscription from JID set as owner in configuration file. Then use the following commands for bot management (you may use either short or full names of them):
h[elp]
— show information about available commandsp[ing]
— pong!v[ersion]
— bot version informationu[ptime]
— bot and system uptimes[tatus] <YOUR_STATUS_MESSAGE>
— update status messageo[wner] l[ist]
— list of bot's ownerso[wner] a[dd] <JID>
— add to owners listo[wner] d[el] <JID>
— remove from owners list (warning: all the owners have the same rights, but the main owner cannot be deleted from the list)m[uc] j[oin] <MUC_ADDRESS> [<NICK>]
— join MUC, custom nick may be set on this stagem[uc] pj[oin] <MUC_ADDRESS> <PASSWORD>
— join password protected MUCm[uc] l[eave] <MUC_ADDRESS>
— leave MUCm[uc] n[ick] <MUC_ADDRESS>
— change bot's shown nick for this MUCm[uc] k[ick] <MUC_ADDRESS> <NICK>
— kick user from MUCm[uc] b[an] <MUC_ADDRESS> <JID>
— ban JID from MUCpl[ugins] l[ist]
— list of loaded plugins' triggers informationpl[ugins] r[eload]
— reload pluginsg[et] <KEY>
— get the value of field from the databasee[xec] <COMMAND>
— execute private message plugin commandrestart
— restart bot (command has no shortcut!)die
— kill bot (command has no shortcut!)
After the bot joined MUC, the owners of MUC can manage its behaviour sending private messages inside the room:
h[elp]
— show information about available commandsp[ing]
— guess, what?w
— the name of room you are inpl[ugins] l[ist]
— get list of loaded plugins and their statepl[ugins] t[oggle] <PLUGIN>
— toggle plugin enabled or disabledht[tp] s[tate]
— get the state of is message sending to this MUC via HTTP API allowedht[tp] t[oggle]
— enable or disable possibility of sending messages to this MUC via HTTP APIl[eave]
— force the bot to go out
Warning: the plugins are unloaded automatically after plugin module file deletion and reloading plugins by the bot owner or full bot restart, but if you delete a file, reload plugins, put the file back and then reload plugins again, it will become active for all the MUCs it has been active for before deletion.
All the plugins are stored in modules with .py
or .pyc
extension under plugins
directory. To make its management more easy, you may create subdirectories there and move plugin modules to them (multiple directory nesting level is allowed). There should be empty __init__.py
file under an every directory containing plugins you need to use.
The only strongly required import for plugin modules is urusai_plugin
.
# -*- coding: utf-8 -*-
import urusai_plugin
from datetime import datetime # module specific import
Plugin class name should start from 'plugin' and be inherited from one of the following classes:
urusai_plugin.Private
— to handle the messages sent to the bot directlyurusai_plugin.MucMessage
— to handle the messages sent to groupchatsurusai_plugin.MucPresence
— to handle presence changes in groupchats
class pluginTime(urusai_plugin.Private):
Plugin class' docstrings are used for generation of help
plugin output.
triggers
dict is strongly required class property. Every key in dict is regular expression (without 'r' prefix!) used for plugin action triggering, and every value is the name of method running when key regexp triggered. The only exceptions are presence-typed plugins which currently don't use regular expressions and should have the only key-value pair with any key.
triggers = { "^time": "Time" }
Trigger method name should start from 'trigger' and being preceded by @staticmethod
decorator.
Trigger method should has three parameters:
- 1st — JID or conference JID/nickname of message sender
- 2nd — real JID of sender (used only for MUC plugins) (if real JIDs are not accessible for bot's role, there will be empty string)
- 3rd — origin message body for
Private
andMucMessage
types and a tuple of (presenceType
,fromJid
,affiliation
,role
,newNick
) forMucPresence
one
presenceType
could has the following values:
join
— user joined MUCleave
— user left MUCkick
— user has been kicked from MUCban
— user has been banned from MUC
Method should return string with the message which will be send back to the user or MUC. If the string is ''
, nothing will be sent.
If this is MucMessage
plugin, it can also return the following tuples:
('mucmessage', return_string)
— just an analog of simple string return, posts the content ofreturn_string
variable to chat('privmessage', target, return_string)
— sends the content ofreturn_string
to JID intarget
variable('kick', target)
— kicks the user with the nickname fromtarget
variable from MUC('ban', target)
— bans the user with JID fromtarget
variable from MUC
@staticmethod
def triggerTime(fromName, fromJid, message):
return str(datetime.now())
All other classes and methods inside modules are not parsed and may be used for coding convenience.
Plugin method execution time is limited to 60 seconds.
Plugin management:
urusai_plugin.getAvailablePrivPlugins()
— get list of loaded plugins available in private messages as space separated stringurusai_plugin.getAvailablePlugins(muc)
— get list of loaded plugins available in specific MUC as space separated string
Bot's KV-database access:
urusai_plugin.dbGet(key)
— get the value by key from the databaseurusai_plugin.dbSet(key, value)
— put KV-pair to the database
For real plugin examples look plugins
directory of this repo.
Allows sending messages via bot from outer world. The default API URL is http://localhost:8011/api, port and location could be changed via configuration file.
To send message via bot you should send the following JSON in POST request body:
{"type": "message",
"target": "victim@jabber.org",
"body": "Hello from HTTP API"}
If you're sending valid JSON, you will receive:
{"result":"ok","message":"sent"}
Otherwise the result will be "error"
with the details in "message"
field.
Allowed types:
message
for direct message sendingplugin
to pass message body via plugin mechanism
Allowed targets:
jid@server.org
— send message directly to this JID (if you need this feature, you should enable appropriate option in configuration file)room@conference.server.org
— send message to MUC (if you're sendingplugin
typed message to MUC, MUC plugins will be applied); you should be joined MUC to send messages there (if you need this feature, MUC's owner should enable it)room@conference.server.org/Interlocutor
— send private message to user Interlocutor from MUC room@