diff --git a/.gitignore b/.gitignore index 2d05c5d..a3c76d6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,13 @@ # Config config.json +config.hjson *.db +# Generated directories +data/ +bin/ +include/ + # ---> Python # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/README.md b/README.md index 9f3a653..962a84f 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ In order for the bot framework to work, Python 3, [virtualenv](https://virtualen ### 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 +install.sh : Creates a virtualenv, an initial config.hjson, and installs all required packages install.sh service: Runs ./install and additionally adds a systemd service. This command will ask you for root credentials! @@ -43,7 +43,7 @@ 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. +Now, you need to create a configuration file `config.hjson`. The template `config.hjson.template` can be used for this purpose. Finally, the bot can be started by executing the following command within the virtual environment: @@ -52,7 +52,7 @@ Finally, the bot can be started by executing the following command within the vi ``` ## 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.hjson] [Keyword(s) in plugin's config.hjson]` 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: * [Hello plugin](src/branch/master/plugins/events): An example plugin that interacts with users that send "Hello bot" to the bot. @@ -63,9 +63,9 @@ The bot has different plugins that can be activated by sending `[Keyword in bot' To interact with rooms, the [Matrix Python SDK](http://matrix-org.github.io/matrix-python-sdk/) can be used. #### Mandatory/recommended files -To create a plugin, a few files must or can be present. The tree below shows the general structure of a plugin. A new plugin must be placed in a directory that has the name of that plugin. The main class (more on that later) of the plugin must be defined in a Python file with that same name. The plugin may not use bot's main configuration file. All configuration must be placed in a separate `config.json`. +To create a plugin, a few files must or can be present. The tree below shows the general structure of a plugin. A new plugin must be placed in a directory that has the name of that plugin. The main class (more on that later) of the plugin must be defined in a Python file with that same name. The plugin may not use bot's main configuration file. All configuration must be placed in a separate `config.hjson`. More information on Hjson can be found on [their website](https://hjson.org). -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..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..hjson` with all messages should exist. The optional file `requirements.txt` is used to define all dependencies. The framework will automatically install them before the first time the plugin is used. This happens even *before* the `setup()` function is invoked (more on that later). @@ -77,10 +77,10 @@ Although recommended, the help file is also not mandatory. If no help message fo │ ├── __init__.py │ ├── .py │ ├── README.md - │ ├── config.json + │ ├── config.hjson │ ├── requirements.txt │ └── messages - │ ├── messages..json + │ ├── messages..hjson │ └── help ├── ╎ @@ -126,22 +126,22 @@ The code below shows the template for a simple plugin with a few features. The n * The Plugin class must contain a method `help()` which only returns the content of `plugin1/messages/help` ```python -CONFIG_LOCATION = os.path.join(os.path.dirname(__file__), 'config.json') -HELP_LOCATION = os.path.join(os.path.dirname(__file__), 'help') -MESSAGES_LOCATION = os.path.join(os.path.dirname(__file__), - 'messages/messages.dutch.json') +CONFIG_LOCATION = os.path.join(os.path.dirname(__file__), 'config.hjson') +MESSAGES_DIR = os.path.join(os.path.dirname(__file__), 'messages') +HELP_LOCATION = MESSAGES_DIR + '/help' +MESSAGES_LOCATION = MESSAGES_DIR + /messages.dutch.hjson' class Plugin: """ Description of event plugin """ def __init__(self, bot): # Load the configuration - with open(CONFIG_LOCATION) as json_data: - self.config = json.load(json_data) + with open(CONFIG_LOCATION) as hjson_data: + self.config = hjson.load(hjson_data) # Load all messages for this plugin - with open(MESSAGES_LOCATION) as json_data: - self.messages = json.load(json_data) + with open(MESSAGES_LOCATION) as hjson_data: + self.messages = hjson.load(hjson_data) # Define sensitivity self.handler = [] diff --git a/config.json.template b/config.hjson.template similarity index 100% rename from config.json.template rename to config.hjson.template diff --git a/install.sh b/install.sh index 41dd0e0..a87c5ea 100755 --- a/install.sh +++ b/install.sh @@ -24,12 +24,12 @@ # This script does the following: # - create virtualenv # - install requirements of main bot -# - create initial config.json +# - create initial config.hjson # - (optional) create systemd service if [[ $1 == help ]]; then echo "Help:" - echo "install.sh : Creates a virtualenv, an initial config.json, and installs" + echo "install.sh : Creates a virtualenv, an initial config.hjson, 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!" @@ -79,7 +79,7 @@ availability pip3 pip3 install -r requirements.txt ################################################################# -# Create config.json +# Create config.hjson ################################################################# echo "" echo "############################################################################" @@ -96,11 +96,11 @@ echo "plugins." echo "############################################################################" echo "" -if [[ -f $DIR/config.json ]]; then - read -p "$DIR/config.json already exists. Should I overwrite it? [y/n]: " ow +if [[ -f $DIR/config.hjson ]]; then + read -p "$DIR/config.hjson already exists. Should I overwrite it? [y/n]: " ow if [[ $ow != y ]]; then - echo "ERR: Cannot write to $DIR/config.json!" + echo "ERR: Cannot write to $DIR/config.hjson!" exit 1 fi fi @@ -114,7 +114,7 @@ sed -e "s|\${server}|${server}|"\ -e "s|\${username}|${username}|"\ -e "s|\${password}|${password}|"\ -e "s|\${superuser}|${superuser}|"\ - $DIR/config.json.template > $DIR/config.json + $DIR/config.hjson.template > $DIR/config.hjson ################################################################# # Configure service diff --git a/matrix_bot_api/matrix_bot_api.py b/matrix_bot_api/matrix_bot_api.py index a895b0a..c3fa0c7 100644 --- a/matrix_bot_api/matrix_bot_api.py +++ b/matrix_bot_api/matrix_bot_api.py @@ -2,6 +2,7 @@ import traceback import re import os import sys +import hjson import importlib import sqlite3 import datetime as dt @@ -14,10 +15,11 @@ from matrix_client.user import User from matrix_bot_api.mregex_handler import MRegexHandler -HELP_LOCATION = os.path.join(os.path.dirname(__file__), 'help') +MESSAGES_DIR = os.path.join(os.path.dirname(__file__), 'messages') DATA_LOCATION = os.path.join(os.path.dirname(__file__), '../data/bot.db') -private_message = "Hey {}! Ik heb je even een privébericht gestuurd 🙂" +HELP_LOCATION = MESSAGES_DIR + '/help' +MESSAGES_LOCATION = MESSAGES_DIR + '/messages.dutch.hjson' def eprint(*args, **kwargs): """Print error messages to stderr""" @@ -84,6 +86,11 @@ class MatrixBotAPI: self.config['triggers']['help'], self.help) self.add_handler(self.help_handler) + # Load messages + with open(MESSAGES_LOCATION) as hjson_data: + self.messages = hjson.load(hjson_data) + + def add_plugins(self): """Acquire list of plugins from configuration, load them, initialize them, and add them to a list of object @@ -264,7 +271,8 @@ class MatrixBotAPI: if room != orig_room: display_name_sender = self.api.get_display_name(event['sender']) - orig_room.send_text(private_message.format(display_name_sender)) + orig_room.send_text(self.messages['private_message'].format( + display_name_sender)) def help(self, room, event): """Prints a general help message and then grabs all help diff --git a/matrix_bot_api/help b/matrix_bot_api/messages/help similarity index 100% rename from matrix_bot_api/help rename to matrix_bot_api/messages/help diff --git a/matrix_bot_api/messages/messages.dutch.hjson b/matrix_bot_api/messages/messages.dutch.hjson new file mode 100644 index 0000000..08e7b4e --- /dev/null +++ b/matrix_bot_api/messages/messages.dutch.hjson @@ -0,0 +1,6 @@ +{ + "private_message": + ''' + Hey {}! Ik heb je even een privébericht gestuurd 🙂 + ''', +} diff --git a/plugins/admidio_events/admidio_events.py b/plugins/admidio_events/admidio_events.py index 64b7092..ef371e6 100644 --- a/plugins/admidio_events/admidio_events.py +++ b/plugins/admidio_events/admidio_events.py @@ -7,7 +7,7 @@ __maintainer__ = "Dennis Potter" __email__ = "dennis@dennispotter.eu" import os -import json +import hjson import time import sqlite3 import threading @@ -16,13 +16,13 @@ import MySQLdb as mysql from matrix_bot_api.mregex_handler import MRegexHandler -MESSAGE_DIR = os.path.join(os.path.dirname(__file__), 'messages') +MESSAGES_DIR = os.path.join(os.path.dirname(__file__), 'messages') DATA_DIR = os.path.join(os.path.dirname(__file__),'../../data/events') -CONFIG_LOCATION = os.path.join(os.path.dirname(__file__), 'config.json') +CONFIG_LOCATION = os.path.join(os.path.dirname(__file__), 'config.hjson') DATA_LOCATION = DATA_DIR + '/data.db' -HELP_LOCATION = MESSAGE_DIR + '/help' -MESSAGES_LOCATION = MESSAGE_DIR + '/messages.dutch.json' +HELP_LOCATION = MESSAGES_DIR + '/help' +MESSAGES_LOCATION = MESSAGES_DIR + '/messages.dutch.hjson' class Plugin: """ This plugin grabs events from Admidio (https://admidio.org) @@ -30,12 +30,12 @@ class Plugin: """ def __init__(self, bot): # Load the configuration - with open(CONFIG_LOCATION) as json_data: - self.config = json.load(json_data) + with open(CONFIG_LOCATION) as hjson_data: + self.config = hjson.load(hjson_data) # Load all messages for this plugin - with open(MESSAGES_LOCATION) as json_data: - self.messages = json.load(json_data) + with open(MESSAGES_LOCATION) as hjson_data: + self.messages = hjson.load(hjson_data) # Define sensitivity self.handler = [] diff --git a/plugins/admidio_events/config.json.example b/plugins/admidio_events/config.hjson.example similarity index 100% rename from plugins/admidio_events/config.json.example rename to plugins/admidio_events/config.hjson.example diff --git a/plugins/admidio_events/messages/messages.dutch.hjson b/plugins/admidio_events/messages/messages.dutch.hjson new file mode 100644 index 0000000..194b00a --- /dev/null +++ b/plugins/admidio_events/messages/messages.dutch.hjson @@ -0,0 +1,35 @@ +{ + "new_event": + ''' + @room er is zojuist een nieuw evenement aangemaakt! + Op {} om {} zal "{}" plaatsvinden. + +

+ + Ben je aangemeld op de leden database in je favoriete browser? + Klik dan hier: + + + ''', + + "list_events_head": + ''' + De aankomende {} evenementen zijn: + ''', + + "list_event_item": + ''' + {} om {}: {} (aanmelden) + ''', + + "list_event_num_err": + ''' + Let op: alleen de getallen [1,100] zijn toegestaan! + Ik pak de standaard waarde 10. + ''' +} diff --git a/plugins/admidio_events/messages/messages.dutch.json b/plugins/admidio_events/messages/messages.dutch.json deleted file mode 100644 index 881cca6..0000000 --- a/plugins/admidio_events/messages/messages.dutch.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "new_event": "@room er is zojuist een nieuw evenement aangemaakt! Op {} om {} zal \"{}\" plaatsvinden.

Ben je aangemeld op de leden database in je favoriete browser? Klik dan hier:", - "list_events_head": "De aankomende {} evenementen zijn:", - "list_event_item": "{} om {}: {} (aanmelden)", - "list_event_num_err": "Let op: alleen de getallen [1,100] zijn toegestaan! Ik pak de standaard waarde 10." -} diff --git a/plugins/woocommerce_coupons/config.json.template b/plugins/woocommerce_coupons/config.hjson.template similarity index 100% rename from plugins/woocommerce_coupons/config.json.template rename to plugins/woocommerce_coupons/config.hjson.template diff --git a/plugins/woocommerce_coupons/messages/messages.dutch.hjson b/plugins/woocommerce_coupons/messages/messages.dutch.hjson new file mode 100644 index 0000000..22f9c3c --- /dev/null +++ b/plugins/woocommerce_coupons/messages/messages.dutch.hjson @@ -0,0 +1,8 @@ +{ + "coupon_message" : + ''' + De huidige code om {}% korting te krijgen is: {}. + Ga meteen naar de webshop om + hem te gebruiken! + ''' +} diff --git a/plugins/woocommerce_coupons/messages/messages.dutch.json b/plugins/woocommerce_coupons/messages/messages.dutch.json deleted file mode 100644 index 5a88627..0000000 --- a/plugins/woocommerce_coupons/messages/messages.dutch.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - - "coupon_message" : "De huidige code om {}% korting te krijgen is: {}. Ga meteen naar de webshop om hem te gebruiken!" - -} diff --git a/plugins/woocommerce_coupons/woocommerce_coupons.py b/plugins/woocommerce_coupons/woocommerce_coupons.py index 37c07ef..25794be 100644 --- a/plugins/woocommerce_coupons/woocommerce_coupons.py +++ b/plugins/woocommerce_coupons/woocommerce_coupons.py @@ -1,17 +1,25 @@ +__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" + from matrix_bot_api.mregex_handler import MRegexHandler from woocommerce import API from base64 import b64encode import os -import json +import hjson import datetime as dt MESSAGE_DIR = os.path.join(os.path.dirname(__file__), 'messages') DATA_DIR = os.path.join(os.path.dirname(__file__),'../../data/woocommerce') -CONFIG_LOCATION = os.path.join(os.path.dirname(__file__), 'config.json') +CONFIG_LOCATION = os.path.join(os.path.dirname(__file__), 'config.hjson') -DATA_LOCATION = DATA_DIR + '/id.json' +DATA_LOCATION = DATA_DIR + '/id.hjson' HELP_LOCATION = MESSAGE_DIR + '/help' -MESSAGES_LOCATION = MESSAGE_DIR + '/messages.dutch.json' +MESSAGES_LOCATION = MESSAGE_DIR + '/messages.dutch.hjson' class Plugin: """ This is an example plugin with only a single callback. When @@ -21,16 +29,16 @@ class Plugin: def __init__(self, bot): # Load the configuration - with open(CONFIG_LOCATION) as json_data: - self.config = json.load(json_data) + with open(CONFIG_LOCATION) as hjson_data: + self.config = hjson.load(hjson_data) # Load ID of coupon - with open(DATA_LOCATION) as json_data: - self.coupon_id = json.load(json_data) + with open(DATA_LOCATION) as hjson_data: + self.coupon_id = hjson.load(hjson_data) # Load all messages for this plugin - with open(MESSAGES_LOCATION) as json_data: - self.messages = json.load(json_data) + with open(MESSAGES_LOCATION) as hjson_data: + self.messages = hjson.load(hjson_data) # Define sensitivity self.handler = [] @@ -91,8 +99,8 @@ def setup(): """This function initializes a coupon with a given percentage""" # Load the configuration - with open(CONFIG_LOCATION) as json_data: - config = json.load(json_data) + with open(CONFIG_LOCATION) as hjson_data: + config = hjson.load(hjson_data) # Create random token and determine max validity vld_days = config['coupon']['max_days'] @@ -120,12 +128,12 @@ def setup(): ) # Send to shop - ret = wcapi.post("coupons", data) + ret = wcapi.post("coupons", data).json() # Create data directory os.mkdir(DATA_DIR) # Write to JSON file to save ID - with open(DATA_LOCATION, 'w') as json_data: - json.dump(ret['id'], json_data) + with open(DATA_LOCATION, 'w') as hjson_data: + hjson.dump(ret['id'], hjson_data) diff --git a/requirements.txt b/requirements.txt index c5f69d1..ee2eeaa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ matrix-client>=0.3.2 +hjson>=3.0.1 diff --git a/run.py b/run.py index 989dc96..11aebec 100755 --- a/run.py +++ b/run.py @@ -11,7 +11,7 @@ __version__ = "0.5.0" __maintainer__ = "Dennis Potter" __email__ = "dennis@dennispotter.eu" -import json +import hjson import os import time import threading @@ -19,12 +19,12 @@ import threading # Bot API import from matrix_bot_api.matrix_bot_api import MatrixBotAPI -CONFIG_LOCATION = os.path.join(os.path.dirname(__file__), 'config.json') +CONFIG_LOCATION = os.path.join(os.path.dirname(__file__), 'config.hjson') def main(): # Load the configuration - with open(CONFIG_LOCATION) as json_data: - config = json.load(json_data) + with open(CONFIG_LOCATION) as hjson_data: + config = hjson.load(hjson_data) # Create an instance of the MatrixBotAPI bot = MatrixBotAPI(config)