I created a Backend plugin for Python's ChatBot tool Errbot, so I'll write down how to make it.
Since the latest version of Errbot only supports Python3 series, this document also uses Python3 series.
A plugin that connects Errbot to a chat system (Slack, HipChat, etc.). Major chat systems such as Slack and HipChat have official Backend plugins. (So I don't think this document will be read unless there's a good deal ...)
I want the bot to talk about this! See http://errbot.io/en/latest/user_guide/plugin_development/index.html for how to create a normal plugin such as.
First, read the [Advanced] Backend development page as much as possible. It's not such a long document, but English ability, English ability.
Below is a brief explanation.
All Backend plugins inherit from the ʻErrBot class. Then, override the methods existing in this ʻErrBot
class as much as necessary and proceed with the implementation. Since the ʻErrBot class also inherits the
Backend` class, there are a lot of methods that need to be implemented unexpectedly.
Looking at the inherited class, there are many methods that describe NotImplementedError
, and the developer implements them according to the function of the chat system that he / she wants to support.
All Backend plugins need to manage ** user identifiers ** and ** user identifiers ** in chat rooms. The build_identifier
method is especially important and needs to return these identifier instances from a particular string.
Feel the usage of identifiers in the following template without worrying about the details.
Let's make a Backend plugin for the chat system called hoge.
It's been a long time to read on Qiita! For those who say, Github is also available. A setting example of config.py is also included. https://github.com/deko2369/errbot-backend-plugin-template
# -*- coding: utf-8 -*-
from errbot.backends.base import Message, ONLINE, Room, \
RoomOccupant, Identifier
from errbot.core import ErrBot
# Can't use __name__ because of Yapsy
log = logging.getLogger('errbot.backends.hoge')
#Load the Hoge chat system library(Library does not exist)
try:
import HogeChatClient
except ImportError:
log.exception("Could not start the hoge backend")
log.fatal(
"You need to install the HogeChatClient package in order "
"to use the Hoge backend. "
"You should be able to install this package using: "
"pip install HogeChatClient"
)
sys.exit(1)
class HogeUser(Identifier):
"""
A class that represents a user of a chat system
Build the Backend class without instantiating this class directly_In the identifier method
Create an object
ref. http://errbot.io/en/latest/errbot.backends.base.html#errbot.backends.base.Identifier
"""
def __init__(self, username, bot):
"""
Initialize user
username specifies the name used in the chat system
"""
self._username = username
self._bot = bot
@property
def username(self):
"""
Returns the user's name
"""
self return._username
class HogeRoomOccupant(RoomOccupant, HogeUser):
"""
A class that represents a user in a chat system chat room
ref. http://errbot.io/en/latest/errbot.backends.base.html#errbot.backends.base.RoomOccupant
"""
def __init__(self, username, roomname, bot):
"""
Initialize users in a particular chat room
"""
super().__init__(username, bot)
self._room = HogeRoom(roomname, bot)
@property
def room(self):
"""
Returns room information
"""
return self._room
class HogeBackend(ErrBot):
"""
Backend class body
I will write the actual interaction of the chat system here
"""
def __init__(self, config):
"""
Initial setting
"""
super().__init__(config)
identity = config.BOT_IDENTIY
self.token = identity.get('token', None)
if not self.token:
log.fatal(
'You need to set your token in the BOT_IDENTITY setting '
'in your config.py .'
)
sys.exit(1)
#Initialize client by specifying token
self.client = HogeChatClient.Client(self.token)
#Create an identifier for the bot itself
self.bot_identifier = HogeUser('BOT NAME', self)
def build_reply(self, mess, text=None, private=False):
"""
Compose a reply message
"""
#Build a message
response = self.build_message(text)
#Reply Source Identifier
response.frm = self.bot_identifier
#Reply to Identifier
response.to = mess.frm
return response
def prefix_groupchat_reply(self, message, identifier):
"""
Template of reply message to group chat
"""
message.body = '@%s %s' % (identifier.username, message.text)
def build_message(self, text):
"""
Creating a message object
"""
return super().build_message(text)
def build_identifier(self, text_repf):
"""
Creating an Identifier object
Hoge chat system builds Identifier in the following format
user: @<username>
Users in chat rooms: @<username>#<roomname>
"""
text = text_repr.strip()
if text.startswith('@') and '#' not in text:
return HogeUser(text.split('@')[1], self)
elif '#' in text:
username, roomname = text.split('#')
return HogeRoomOccupant(username.split('@')[1], roomname, self)
raise RuntimeError('Unrecognized identifier: %s' % text)
def serve_once(self):
"""
Method to receive new message from chat system and process
This serve_The once method is called regularly by ErrBot
Serve to a similar overridden method_There is also forever
ref. http://errbot.io/en/latest/errbot.backends.base.html#errbot.backends.base.Backend.serve_forever
"""
#Get new messages
mess = self.client.new_messages()
#Process the acquired messages in order
#The message also contains the username and the room name spoken
for msg in mess:
#Build a Message object
m = Message(msg)
m.frm = HogeRoomOccupant(msg.username, msg.roomname, self)
m.to = HogeRoom(msg.roomname, self)
#Call the message callback
self.callback_message(m)
# @<username>Callback if contains_Also call mention
#Note that detailed implementation is omitted
if '@' in msg:
mentions = [HogeUser(username, self), ...]
self.callback_mention(m, mentions)
def send_message(self, mess):
"""
Implementation of the send part to the chat system
"""
self.client.send(mess.body)
def connect(self):
"""
Return the chat system library connection
"""
return self.client
def query_room(self, room)
"""
Process to return HogeRoom object from room string
"""
r = self.client.room_info(room)
return HogeRoom(r.name, self)
@property
def mode(self):
"""
A unique string that indicates the current backend
"""
return 'hoge'
@property
def rooms(self):
"""
Return the Room instance that the bot is in
"""
return []
def change_presense(self, status=ONLINE, message=''):
"""
Process called when the bot's entry status changes
"""
super().change_presence(status=status, message=message)
class HogeRoom(Room):
"""
Definition of a chat room in the Hoge chat system
Implement the ability for bots to join and create chat rooms
Impossible to implement if the chat system client does not provide such functionality...
ref. http://errbot.io/en/latest/errbot.backends.base.html#errbot.backends.base.Room
"""
def __init__(self, name, bot):
self._name = name
self._bot = bot
def join(self, username=None, password=None):
"""
bot joins room
"""
self._bot.client.join_room(self._name)
def leave(self, reason=None):
"""
bot leaves from room
"""
self._bot.client.leave_room(self._name)
def create(self):
"""
bot creates a room
"""
self._bot.client.create_room(self._name)
def destroy(self):
"""
bot destroys a room
"""
self._bot.client.destroy_room(self._name)
@property
def exists(self):
"""
Whether the room exists
"""
return self._bot.client.exist_room(self._name)
@property
def joined(self):
"""
Whether the bot is joining the room
"""
return self._bot.client.is_joined(self._name)
@property
def topic(self):
"""
Get room topic
"""
return self._bot.client.room_info(self._name).topic
@topic.setter
def topic(self, topic):
"""
Set room topic
"""
return self._bot.client.set_room_topic(self._name, topic)
@property
def occupants(self):
"""
Get the Identifier of the user who exists in the room
"""
return [HogeUser(name, self._bot) \
for name in self._bot.client.get_room_usernames(self._name)]
def invite(self, *args):
"""
Invite users to the room
"""
for ident in args:
self._bot.client.invite(self._name, ident.username)
The side using Errbot is easy, but the developer who creates a bridge (Backend) with each chat system has a hard time w
Recommended Posts