From eb2b887c0a2897ac6bb59ad95f5d9ae06a45d4d5 Mon Sep 17 00:00:00 2001 From: Dennis Date: Mon, 14 Jan 2019 23:47:38 +0100 Subject: [PATCH] Transitioned from JSON to Hjson. Closes #3 All configuration files and all messages files should now preferrable be done in Hjson. This format supports, i.a. features, multi line strings and commenting. This greatly improves readability. All installation and documentation files are also updated in this commit. --- .gitignore | 6 +++ README.md | 30 +++++++-------- config.json.template => config.hjson.template | 0 install.sh | 14 +++---- matrix_bot_api/matrix_bot_api.py | 14 +++++-- matrix_bot_api/{ => messages}/help | 0 matrix_bot_api/messages/messages.dutch.hjson | 6 +++ plugins/admidio_events/admidio_events.py | 18 ++++----- ...nfig.json.example => config.hjson.example} | 0 .../messages/messages.dutch.hjson | 35 +++++++++++++++++ .../messages/messages.dutch.json | 6 --- ...ig.json.template => config.hjson.template} | 0 .../messages/messages.dutch.hjson | 8 ++++ .../messages/messages.dutch.json | 5 --- .../woocommerce_coupons.py | 38 +++++++++++-------- requirements.txt | 1 + run.py | 8 ++-- 17 files changed, 125 insertions(+), 64 deletions(-) rename config.json.template => config.hjson.template (100%) rename matrix_bot_api/{ => messages}/help (100%) create mode 100644 matrix_bot_api/messages/messages.dutch.hjson rename plugins/admidio_events/{config.json.example => config.hjson.example} (100%) create mode 100644 plugins/admidio_events/messages/messages.dutch.hjson delete mode 100644 plugins/admidio_events/messages/messages.dutch.json rename plugins/woocommerce_coupons/{config.json.template => config.hjson.template} (100%) create mode 100644 plugins/woocommerce_coupons/messages/messages.dutch.hjson delete mode 100644 plugins/woocommerce_coupons/messages/messages.dutch.json 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)