Added installation files
This commit adds a convenient installation script for Linux and also adds a description on how to install the bot. Furthermore, a very simple example plugin is added. This way, new users can easily discover the possibilities of this plugin. Finally, the default character "Peter"---which is used within Alcuinus---is removed, and a more generic character is added.
This commit is contained in:
parent
3a85bd368f
commit
0d32c727fa
53
README.md
53
README.md
@ -1,33 +1,72 @@
|
|||||||
The core of this chatbot is based on [github.com/shawnanastasio/python-matrix-bot-api](https://github.com/shawnanastasio/python-matrix-bot-api/) which was published under GPL-3.0. It is heavily modified to create an API to easily add plugins. This bot is intended to operate on the [Matrix network](https://matrix.org).
|
The core of this chatbot is based on [github.com/shawnanastasio/python-matrix-bot-api](https://github.com/shawnanastasio/python-matrix-bot-api/) which was published under GPL-3.0. It is heavily modified to create an API to easily add plugins. This bot is intended to operate on the [Matrix network](https://matrix.org).
|
||||||
|
|
||||||
This code has two purposes. Firstly, and mainly, it serves as virtual assistent in the Matrix based communication platform of members of the Dutch student association [Alcuinus](https://alcuinus.nl). Secondly, the bot's easy to use API makes the development of a simple plugin an approachable first project for new members of Alcuinus' IT working groups during their training.
|
This bot was orginally created to serve two purposes. Firstly, and mainly, it serves as virtual assistent in the Matrix based communication platform of members of the Dutch student association [Alcuinus](https://alcuinus.nl). Secondly, the bot's easy to use API makes the development of a simple plugin an approachable first project for new members of Alcuinus' IT working groups during their training.
|
||||||
|
|
||||||
## Content
|
## Content
|
||||||
* [Installation & Requirements](#installation-requirements)
|
* [Installation & Requirements](#installation-requirements)
|
||||||
|
* [Automatic installation (Linux)](#automatic-installation-linux)
|
||||||
|
* [Manual installation](#manual-installation)
|
||||||
* [Plugins](#plugins)
|
* [Plugins](#plugins)
|
||||||
* [List of available plugins](#list-of-available-plugins)
|
* [List of available plugins](#list-of-available-plugins)
|
||||||
* [API](#api)
|
* [API](#api)
|
||||||
* [Mandatory files](#mandatory-files)
|
* [Mandatory/recommended files](#mandatory-recommended-files)
|
||||||
* [Help template](#help-template)
|
* [Help template](#help-template)
|
||||||
* [Plugin class template](#plugin-class-template)
|
* [Plugin class template](#plugin-class-template)
|
||||||
* [Additional tips](#additional-tips)
|
* [Additional tips](#additional-tips)
|
||||||
|
|
||||||
## Installation & Requirements:
|
## Installation & Requirements:
|
||||||
...
|
First, clone this repository:
|
||||||
|
```
|
||||||
|
git clone https://git.dennispotter.eu/Dennis/matrix-chatbot
|
||||||
|
```
|
||||||
|
In order for the bot framework to work, Python 3, [virtualenv](https://virtualenv.pypa.io/en/latest/), and [pip](https://pypi.org/project/pip/) must be installed on your computer or server.
|
||||||
|
|
||||||
|
### Automatic installation (Linux)
|
||||||
|
On Linux, the bash script `install.sh` can be used to install the bot.
|
||||||
|
```
|
||||||
|
install.sh : Creates a virtualenv, an initial config.json, and installs
|
||||||
|
all required packages
|
||||||
|
install.sh service: Runs ./install and additionally adds a systemd service.
|
||||||
|
This command will ask you for root credentials!
|
||||||
|
install.sh help : Prints this message.
|
||||||
|
```
|
||||||
|
### Manual installation
|
||||||
|
Create a virtual environment by entering the directory and running:
|
||||||
|
```
|
||||||
|
virtualenv .
|
||||||
|
```
|
||||||
|
Enter the virtual environment
|
||||||
|
```
|
||||||
|
source bin/activate
|
||||||
|
```
|
||||||
|
and install all required packages
|
||||||
|
```
|
||||||
|
pip3 install -r requirements.txt
|
||||||
|
```
|
||||||
|
Now, you need to create a configuration file `config.json`. The template `config.json.template` can be used for this purpose.
|
||||||
|
|
||||||
|
Finally, the bot can be started by executing the following command within the virtual environment:
|
||||||
|
|
||||||
|
```
|
||||||
|
./run.py
|
||||||
|
```
|
||||||
|
|
||||||
## Plugins
|
## Plugins
|
||||||
The bot has different plugins that can be activated by sending `[Keyword in bot's config.json] [Keyword(s) in plugin's config.json]` to a room in which the bot is present. Below, under [List of available plugins](list-of-available-plugins), you can first find a list of already available plugins. Then, under [API](#api), you can find a description on how to develop a new plugin.
|
The bot has different plugins that can be activated by sending `[Keyword in bot's config.json] [Keyword(s) in plugin's config.json]` to a room in which the bot is present. Below, under [List of available plugins](list-of-available-plugins), you can first find a list of already available plugins. Then, under [API](#api), you can find a description on how to develop a new plugin.
|
||||||
|
|
||||||
### List of available plugins:
|
### List of available plugins:
|
||||||
* [Admidio events plugin](src/branch/master/plugins/events)
|
* [Hello plugin](src/branch/master/plugins/events): An example plugin that interacts with users that send "Hello bot" to the bot.
|
||||||
|
* [Admidio events plugin](src/branch/master/plugins/events): a plugin that interacts with an [Admidio](https://admidio.org) installation.
|
||||||
|
|
||||||
### API
|
### API
|
||||||
To interact with rooms, the [Matrix Python SDK](http://matrix-org.github.io/matrix-python-sdk/<Paste>) can be used.
|
To interact with rooms, the [Matrix Python SDK](http://matrix-org.github.io/matrix-python-sdk/<Paste>) can be used.
|
||||||
|
|
||||||
#### Mandatory files
|
#### Mandatory/recommended files
|
||||||
To create a plugin, a few mandatory files must be present. The tree below shows the general structure of a plugin. A new plugin must be placed in a directory with the same name. The main class (more on that later) of the plugin must be defined in a Python file with the same name within that directory. The event may not use bot's main configuration file. All configuration must be placed in a separate `config.json`.
|
To create a plugin, a few mandatory or recommended files must be present. The tree below shows the general structure of a plugin. A new plugin must be placed in a directory with the same name. The main class (more on that later) of the plugin must be defined in a Python file with the same name within that directory. The event may not use bot's main configuration file. All configuration must be placed in a separate `config.json`.
|
||||||
|
|
||||||
A subdirectory `messages` is used to store messages. Within this directory, a file `help` must be present. The content of this file must be returned with a method of the plugin class (more on that later). Furthermore, for every language a file `messages.<language>.json` with all messages should exist.
|
A subdirectory `messages` is used to store messages. Within this directory, a file `help` may be present. The content of this file must be returned with a method of the plugin class (more on that later). Furthermore, for every language a file `messages.<language>.json` with all messages should exist.
|
||||||
|
|
||||||
|
The help file is not mandatory. If no help message for a plugin should appear when sending a help request to the bot, this file can be ommitted. The Plugin's `help()` method should return 0 in that case.
|
||||||
```
|
```
|
||||||
.
|
.
|
||||||
└── plugins
|
└── plugins
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"bot_credentials": {
|
|
||||||
"username": "",
|
|
||||||
"password": "",
|
|
||||||
"server": ""
|
|
||||||
},
|
|
||||||
|
|
||||||
"character": {
|
|
||||||
"name": "Peter",
|
|
||||||
"avatar": "images/profilepic.jpg",
|
|
||||||
"avatar_mime": "image/jpeg"
|
|
||||||
},
|
|
||||||
|
|
||||||
"plugins": [
|
|
||||||
"events"
|
|
||||||
]
|
|
||||||
}
|
|
17
config.json.template
Normal file
17
config.json.template
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"bot_credentials": {
|
||||||
|
"username": "${uservar}",
|
||||||
|
"password": "${passvar}",
|
||||||
|
"server": "${servervar}"
|
||||||
|
},
|
||||||
|
|
||||||
|
"character": {
|
||||||
|
"name": "Bot",
|
||||||
|
"avatar": "images/default_avatar.png",
|
||||||
|
"avatar_mime": "image/png"
|
||||||
|
},
|
||||||
|
|
||||||
|
"plugins": [
|
||||||
|
"hello"
|
||||||
|
]
|
||||||
|
}
|
BIN
images/default_avatar.png
Normal file
BIN
images/default_avatar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 106 KiB |
128
install.sh
Executable file
128
install.sh
Executable file
@ -0,0 +1,128 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Installation script for matrix-chatbot
|
||||||
|
#
|
||||||
|
# @author Dennis Potter <dennis@dennispotter.eu>
|
||||||
|
# @copyright 2019, Dennis Potter
|
||||||
|
# @license GNU General Public License (version 3)
|
||||||
|
#
|
||||||
|
# matrix-chatbot
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
##################################################################################
|
||||||
|
|
||||||
|
# This script does the following:
|
||||||
|
# - create virtualenv
|
||||||
|
# - install requirements of main bot
|
||||||
|
# - create initial config.json
|
||||||
|
# - (optional) create systemd service
|
||||||
|
|
||||||
|
if [[ $1 == help ]]; then
|
||||||
|
echo "Help:"
|
||||||
|
echo "install.sh : Creates a virtualenv, an initial config.json, and installs"
|
||||||
|
echo " all required packages"
|
||||||
|
echo "install.sh service: Runs ./install and additionally adds a systemd service."
|
||||||
|
echo " This command will ask you for root credentials!"
|
||||||
|
echo "install.sh help : Prints this message."
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Define directory of chatbot
|
||||||
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||||
|
|
||||||
|
# Check if user is superuser
|
||||||
|
if [[ "$EUID" -eq 0 ]]; then
|
||||||
|
echo "ERR: Please do not run this script as super user!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# Create function to check availability of software
|
||||||
|
#################################################################
|
||||||
|
function availability {
|
||||||
|
if [[ ! $(command -v $1) ]]; then
|
||||||
|
echo "ERR: '$1' is not available but required. Please install it!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# Create virtualenv
|
||||||
|
#################################################################
|
||||||
|
# Check whether virtualenv is present
|
||||||
|
availability virtualenv
|
||||||
|
|
||||||
|
# Create virtualenv
|
||||||
|
virtualenv $DIR
|
||||||
|
|
||||||
|
# Enter virtualenv
|
||||||
|
source $DIR/bin/activate
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# Install requirements
|
||||||
|
#################################################################
|
||||||
|
# Check whether pip3 is present
|
||||||
|
availability pip3
|
||||||
|
|
||||||
|
# Install requirements
|
||||||
|
pip3 install -r requirements.txt
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# Create config.json
|
||||||
|
#################################################################
|
||||||
|
echo ""
|
||||||
|
echo "############################################################################"
|
||||||
|
echo "This step will generate a configuration file. The resulting bot will be very"
|
||||||
|
echo "simple and is only able to respond to the message "Hello bot". However, it"
|
||||||
|
echo "forms the perfect base for further development."
|
||||||
|
echo ""
|
||||||
|
echo "In the following steps, an _existing_ user must be provided. If you did not"
|
||||||
|
echo "yet create a user for your bot, please do so now!"
|
||||||
|
echo "############################################################################"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [[ -f $DIR/config.json ]]; then
|
||||||
|
read -p "$DIR/config.json already exists. Should I overwrite it? [y/n]: " ow
|
||||||
|
|
||||||
|
if [[ $ow != y ]]; then
|
||||||
|
echo "ERR: Cannot write to $DIR/config.json!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
read -p 'Matrix homeserver: ' servervar
|
||||||
|
read -p 'Matrix username: ' uservar
|
||||||
|
read -p 'Matrix password: ' passvar
|
||||||
|
|
||||||
|
sed -e "s/\${servervar}/${servervar}/"\
|
||||||
|
-e "s/\${uservar}/${uservar}/"\
|
||||||
|
-e "s/\${passvar}/${passvar}/"\
|
||||||
|
$DIR/config.json.template > $DIR/config.json
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# Configure service
|
||||||
|
#################################################################
|
||||||
|
if [[ $1 != service ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo useradd -r mchatbot
|
||||||
|
|
||||||
|
sed -e "s/\${DIR}/${DIR}/"\
|
||||||
|
$DIR/matrix-chatbot.service.template > $DIR/matrix-chatbot.service
|
||||||
|
|
||||||
|
sudo mv $DIR/matrix-chatbot.service /etc/systemd/system/matrix-chatbot.service
|
||||||
|
|
||||||
|
sudo systemctl enable matrix-chatbot.service
|
||||||
|
sudo systemctl start matrix-chatbot.service
|
14
matrix-chatbot.service.template
Normal file
14
matrix-chatbot.service.template
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Matrix chatbot
|
||||||
|
After=multi-user.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
Restart=always
|
||||||
|
RestartSec=3
|
||||||
|
User=mchatbot
|
||||||
|
WorkingDirectory=${DIR}
|
||||||
|
ExecStart=${DIR}/bin/python run.py
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
@ -15,6 +15,7 @@ HELP_LOCATION = os.path.join(os.path.dirname(__file__), 'help')
|
|||||||
private_message = "Hey {}! Ik heb je even een privébericht gestuurd 🙂"
|
private_message = "Hey {}! Ik heb je even een privébericht gestuurd 🙂"
|
||||||
|
|
||||||
def eprint(*args, **kwargs):
|
def eprint(*args, **kwargs):
|
||||||
|
'''Print error messages to stderr'''
|
||||||
print(*args, file=sys.stderr, **kwargs)
|
print(*args, file=sys.stderr, **kwargs)
|
||||||
|
|
||||||
class MatrixBotAPI:
|
class MatrixBotAPI:
|
||||||
@ -159,7 +160,11 @@ class MatrixBotAPI:
|
|||||||
help_text = open(HELP_LOCATION, mode="r").read()
|
help_text = open(HELP_LOCATION, mode="r").read()
|
||||||
|
|
||||||
for plugin in self.plugins:
|
for plugin in self.plugins:
|
||||||
|
try:
|
||||||
help_text += plugin.help()
|
help_text += plugin.help()
|
||||||
|
except TypeError:
|
||||||
|
# The plugin probably returned 0, ignore it
|
||||||
|
pass
|
||||||
|
|
||||||
self.send_message_private_public(room, event, help_text)
|
self.send_message_private_public(room, event, help_text)
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ __author__ = "Dennis Potter"
|
|||||||
__copyright__ = "Copyright 2019, Dennis Potter"
|
__copyright__ = "Copyright 2019, Dennis Potter"
|
||||||
__credits__ = ["Dennis Potter"]
|
__credits__ = ["Dennis Potter"]
|
||||||
__license__ = "GPL-3.0"
|
__license__ = "GPL-3.0"
|
||||||
__version__ = "1.0.1"
|
__version__ = "0.5.0"
|
||||||
__maintainer__ = "Dennis Potter"
|
__maintainer__ = "Dennis Potter"
|
||||||
__email__ = "dennis@dennispotter.eu"
|
__email__ = "dennis@dennispotter.eu"
|
||||||
|
|
||||||
@ -16,14 +16,19 @@ import MySQLdb as mysql
|
|||||||
|
|
||||||
from matrix_bot_api.mregex_handler import MRegexHandler
|
from matrix_bot_api.mregex_handler import MRegexHandler
|
||||||
|
|
||||||
|
EVENTS_DATA_DIR = os.path.join(os.path.dirname(__file__),
|
||||||
|
'../../data/events')
|
||||||
|
DATA_LOCATION = os.path.join(os.path.dirname(__file__),
|
||||||
|
'../../data/events/data.db')
|
||||||
CONFIG_LOCATION = os.path.join(os.path.dirname(__file__), 'config.json')
|
CONFIG_LOCATION = os.path.join(os.path.dirname(__file__), 'config.json')
|
||||||
HELP_LOCATION = os.path.join(os.path.dirname(__file__), 'messages/help')
|
HELP_LOCATION = os.path.join(os.path.dirname(__file__), 'messages/help')
|
||||||
MESSAGES_LOCATION = os.path.join(os.path.dirname(__file__),
|
MESSAGES_LOCATION = os.path.join(os.path.dirname(__file__),
|
||||||
'messages/messages.dutch.json')
|
'messages/messages.dutch.json')
|
||||||
|
|
||||||
class Plugin:
|
class Plugin:
|
||||||
""" Description of event plugin """
|
""" This plugin grabs events from Admidio (https://admidio.org)
|
||||||
|
and lets users interact with the data
|
||||||
|
"""
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
# Load the configuration
|
# Load the configuration
|
||||||
with open(CONFIG_LOCATION) as json_data:
|
with open(CONFIG_LOCATION) as json_data:
|
||||||
@ -61,7 +66,7 @@ class Plugin:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# Try to make a new directory
|
# Try to make a new directory
|
||||||
os.mkdir("data/events")
|
os.mkdir(EVENTS_DATA_DIR)
|
||||||
|
|
||||||
# Define query to INSERT event table to SQLite DB
|
# Define query to INSERT event table to SQLite DB
|
||||||
sql = """CREATE TABLE 'events' (
|
sql = """CREATE TABLE 'events' (
|
||||||
@ -69,7 +74,7 @@ class Plugin:
|
|||||||
'datetime_posted' datetime);"""
|
'datetime_posted' datetime);"""
|
||||||
|
|
||||||
# Open, execute, commit, and close SQLite database
|
# Open, execute, commit, and close SQLite database
|
||||||
sqlite_db = sqlite3.connect('data/events/data.db')
|
sqlite_db = sqlite3.connect(DATA_LOCATION)
|
||||||
sqlite_cursor = sqlite_db.cursor()
|
sqlite_cursor = sqlite_db.cursor()
|
||||||
sqlite_cursor.execute(sql)
|
sqlite_cursor.execute(sql)
|
||||||
sqlite_db.commit()
|
sqlite_db.commit()
|
||||||
@ -120,7 +125,7 @@ class Plugin:
|
|||||||
results = mysql_cursor.fetchall()
|
results = mysql_cursor.fetchall()
|
||||||
|
|
||||||
# Open SQLite database
|
# Open SQLite database
|
||||||
sqlite_db = sqlite3.connect('data/events/data.db')
|
sqlite_db = sqlite3.connect(DATA_LOCATION)
|
||||||
|
|
||||||
sqlite_cursor = sqlite_db.cursor()
|
sqlite_cursor = sqlite_db.cursor()
|
||||||
|
|
1
plugins/hello/README.md
Normal file
1
plugins/hello/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
This is an example plugin with only a single callback. When a user says "Hello bot" in a room in which te bot is present, the user replies with "Hello \<username\>!".
|
25
plugins/hello/hello.py
Normal file
25
plugins/hello/hello.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
from matrix_bot_api.mregex_handler import MRegexHandler
|
||||||
|
import os
|
||||||
|
|
||||||
|
HELP_LOCATION = os.path.join(os.path.dirname(__file__), 'messages/help')
|
||||||
|
|
||||||
|
class Plugin:
|
||||||
|
""" This is an example plugin with only a single callback. When
|
||||||
|
a user says "Hello bot" in a room in which te bot is present,
|
||||||
|
the user replies with "Hello <username>!".
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, bot):
|
||||||
|
# Define sensitivity
|
||||||
|
self.handler = []
|
||||||
|
|
||||||
|
self.handler.append(MRegexHandler("Hello bot", self.info_callback))
|
||||||
|
|
||||||
|
# Save parent bot
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
def info_callback(self, room, event):
|
||||||
|
room.send_text(f"Hello {event['sender']}!")
|
||||||
|
|
||||||
|
def help(self):
|
||||||
|
return open(HELP_LOCATION, mode="r").read()
|
5
plugins/hello/messages/help
Normal file
5
plugins/hello/messages/help
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<h5><i>Hello</i></h5>
|
||||||
|
This is an example help message of an example plugin. This message is made up in HTML.
|
||||||
|
<ul>
|
||||||
|
<li><i>bot</i>: greet me with "Hello bot". I will greet you back.</li>
|
||||||
|
</ul>
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
matrix-client>=0.3.2
|
23
run.py
23
run.py
@ -3,14 +3,27 @@
|
|||||||
This is Peter. Peter is using the Python Matrix Bot API
|
This is Peter. Peter is using the Python Matrix Bot API
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
__author__ = "Dennis Potter"
|
||||||
|
__copyright__ = "Copyright 2019, Dennis Potter"
|
||||||
|
__credits__ = ["Dennis Potter"]
|
||||||
|
__license__ = "GPL-3.0"
|
||||||
|
__version__ = "0.5.0"
|
||||||
|
__maintainer__ = "Dennis Potter"
|
||||||
|
__email__ = "dennis@dennispotter.eu"
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
|
||||||
# Bot API import
|
# Bot API import
|
||||||
from matrix_bot_api.matrix_bot_api import MatrixBotAPI
|
from matrix_bot_api.matrix_bot_api import MatrixBotAPI
|
||||||
|
|
||||||
|
CONFIG_LOCATION = os.path.join(os.path.dirname(__file__), 'config.json')
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# Load the configuration
|
# Load the configuration
|
||||||
with open('config.json') as json_data:
|
with open(CONFIG_LOCATION) as json_data:
|
||||||
config = json.load(json_data)
|
config = json.load(json_data)
|
||||||
|
|
||||||
# Create an instance of the MatrixBotAPI
|
# Create an instance of the MatrixBotAPI
|
||||||
@ -19,11 +32,11 @@ def main():
|
|||||||
# Start polling
|
# Start polling
|
||||||
bot.start_polling()
|
bot.start_polling()
|
||||||
|
|
||||||
# Infinitely read stdin to stall main thread while the bot runs in other
|
# Stall this thread while the bot runs in other threads. On ^C, this will
|
||||||
# threads.
|
# indicate to all threads that they should cancel
|
||||||
try:
|
try:
|
||||||
while True:
|
forever = threading.Event();
|
||||||
input()
|
forever.wait()
|
||||||
except:
|
except:
|
||||||
bot.cancel = True
|
bot.cancel = True
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user