diff --git a/docs/source/_static/images/slack-1.jpg b/docs/source/_static/images/slack-1.jpg
new file mode 100644
index 0000000..192b2a3
Binary files /dev/null and b/docs/source/_static/images/slack-1.jpg differ
diff --git a/docs/source/_static/images/slack-2.jpg b/docs/source/_static/images/slack-2.jpg
new file mode 100644
index 0000000..69c7db6
Binary files /dev/null and b/docs/source/_static/images/slack-2.jpg differ
diff --git a/docs/source/_static/images/slack-3.jpg b/docs/source/_static/images/slack-3.jpg
new file mode 100644
index 0000000..a6778a8
Binary files /dev/null and b/docs/source/_static/images/slack-3.jpg differ
diff --git a/docs/source/_static/images/twist-1.png b/docs/source/_static/images/twist-1.png
new file mode 100644
index 0000000..a2806e4
Binary files /dev/null and b/docs/source/_static/images/twist-1.png differ
diff --git a/docs/source/_static/images/twist-2.png b/docs/source/_static/images/twist-2.png
new file mode 100644
index 0000000..deb31ef
Binary files /dev/null and b/docs/source/_static/images/twist-2.png differ
diff --git a/help/en/docs/usage/images/mattermost-1.png b/help/en/docs/usage/images/mattermost-1.png
new file mode 100644
index 0000000..8007ec1
Binary files /dev/null and b/help/en/docs/usage/images/mattermost-1.png differ
diff --git a/help/en/docs/usage/images/mattermost-2.png b/help/en/docs/usage/images/mattermost-2.png
new file mode 100644
index 0000000..95783dd
Binary files /dev/null and b/help/en/docs/usage/images/mattermost-2.png differ
diff --git a/help/en/docs/usage/images/mattermost-3.png b/help/en/docs/usage/images/mattermost-3.png
new file mode 100644
index 0000000..b43a539
Binary files /dev/null and b/help/en/docs/usage/images/mattermost-3.png differ
diff --git a/help/en/docs/usage/images/slack-1.jpg b/help/en/docs/usage/images/slack-1.jpg
new file mode 100644
index 0000000..192b2a3
Binary files /dev/null and b/help/en/docs/usage/images/slack-1.jpg differ
diff --git a/help/en/docs/usage/images/slack-2.jpg b/help/en/docs/usage/images/slack-2.jpg
new file mode 100644
index 0000000..69c7db6
Binary files /dev/null and b/help/en/docs/usage/images/slack-2.jpg differ
diff --git a/help/en/docs/usage/images/slack-3.jpg b/help/en/docs/usage/images/slack-3.jpg
new file mode 100644
index 0000000..a6778a8
Binary files /dev/null and b/help/en/docs/usage/images/slack-3.jpg differ
diff --git a/help/en/docs/usage/images/twist-1.png b/help/en/docs/usage/images/twist-1.png
new file mode 100644
index 0000000..a2806e4
Binary files /dev/null and b/help/en/docs/usage/images/twist-1.png differ
diff --git a/help/en/docs/usage/images/twist-2.png b/help/en/docs/usage/images/twist-2.png
new file mode 100644
index 0000000..deb31ef
Binary files /dev/null and b/help/en/docs/usage/images/twist-2.png differ
diff --git a/help/en/docs/usage/messages.md b/help/en/docs/usage/messages.md
index 43c1e67..73bd3cc 100644
--- a/help/en/docs/usage/messages.md
+++ b/help/en/docs/usage/messages.md
@@ -52,6 +52,34 @@ echo: "This is a message."
echo: "This is a message."
```
+### mattermost
+
+Send a message via Mattermost.
+
+- `url` (str): Required. The URL to which the message should be sent.
+
+```ini
+[send some feedback]
+mattermost: "This is a message."
+url: https://mattermostdomain.com/path/to/your/channel/webhook
+```
+
+Using the mattermost command requires setup from your Mattermost admin. The procedure will be something like the following:
+
+**1.** Click on Integrations from the admin menu.
+
+![integrations menu](images/mattermost-1.png)
+
+**2.** Click Incoming Webhooks and then Add New Webhook.
+
+![add new webhook](images/mattermost-2.png)
+
+**3.** Fill in the information and click Save.
+
+![webhook form](images/mattermost-3.png)
+
+**4.** Copy and past the webhook URL to your configuration.
+
### slack
Send a message via Slack.
@@ -73,6 +101,24 @@ url: https://subdomain.slack.com/path/to/your/integration
!!! note
You could easily define a variable for the Slack URL and set ``url: {{ slack_url }}`` to save some typing. See [variables](../config/variables.md).
+Using the slack command requires setup from your Slack admin. The procedure will be something like the following:
+
+**1.** Log in to Slack and go to [Your Apps](https://api.slack.com/apps)
+
+**2.** Create a new Slack app.
+
+**3.** On the next page, select Incoming Webhooks and then toggle activation.
+
+![toggle activation](images/slack-1.jpg)
+
+**4.** Next click Add new Webhook to Workspace and select the channel to which the message will be posted.
+
+![incoming webhooks](images/slack-2.jpg)
+
+![select channel](images/slack-3.jpg)
+
+**5.** Copy the URL for the new webhook to use as the ``url`` parameter for the Slack command.
+
### screenshot
Like `explain` above, a screenshot adds detail to comments or documentation, but does not produce a command statement.
@@ -114,3 +160,17 @@ url: https://subdomain.twist.com/path/to/your/integration
!!! note
As with Slack, you could easily define a variable for the Twist URL and set ``url: {{ twist_url }}``. See [variables](../config/variables.md).
+
+Using the twist command requires setup on your Twist account. The procedure will be something like the following:
+
+**1.** Log in to Twist and from the profile menu go to Add Integrations. Then click on Build and "Add a new integration".
+
+**2.** Provide the requested info.
+
+![provide info about your integration](images/twist-1.png)
+
+**3.** After submitting this info, go to Installation. Select a channel and who to notify. Then click "Install integration".
+
+![install integration](images/twist-2.png)
+
+**4.** Copy the "Post content manually" URL for use in your configuration file.
diff --git a/scripttease/data/inventory/matomo/notes.md b/scripttease/data/inventory/matomo/notes.md
new file mode 100644
index 0000000..37fb60e
--- /dev/null
+++ b/scripttease/data/inventory/matomo/notes.md
@@ -0,0 +1,99 @@
+Install dependencies
+
+apt install apache2 mariadb-server php libapache2-mod-php php-cli php-fpm php-json php-common php-mysql php-zip php-gd php-mbstring php-curl php-xml php-pear phpbcmath curl unzip -v
+
+sudo systemctl start apache2
+sudo systemctl start mariadb
+
+
+Enable and Create db
+
+sudo systemctl enable apache2 mariadb
+
+CREATE MYSQL DATABASE
+MYSQL
+CREATE DATABASE matomodb;
+CREATE USER 'matomouser'@'localhost' IDENTIFIED BY 'password'
+GRANT ALL PRIVILAGES ON matomodb.* TO 'matomouser'@'localhost'
+
+
+Pull and unzip Matomo files and set permissions
+
+wget http://builds.matomo.org/matomo-latest.zip
+
+unzip matomo-latest.zip
+
+mv matomo /var/www/html/matomo
+
+chown -R www-data:www-data /var/www/html/matomo
+
+chmod -R 755 /var/www/html/matomo
+
+
+
+Create Apache config file
+
+sudo nano /etc/apache2/sites-available/matomo.conf
+
+
+
+ServerName matomo.mark37.com
+DocumentRoot /var/www/html/matomo/
+
+
+Options FollowSymLinks
+Allowoverride All
+Require all granted
+
+
+
+Options None
+Require all denied
+
+
+
+Options None
+Required all granted
+
+
+
+Options None
+Required all granted
+
+
+
+Options None
+Required all granted
+
+
+ErrorLog ${APACHE_LOG_DIR}/matomo_error.log
+CustomLog ${APACHE_LOG_DIR}/matomo_access.log combined
+
+
+
+
+
+
+Enable site
+
+sudo a2ensite matomo.mark37.com
+
+sudo a2enmod rewrite headers enc dif mime setenvif ssl
+
+sudo systemctl enable --now php7.4-fpm
+sudo systemctl reload apache2
+
+
+Install SSL Certificate
+
+sudo apt install certbot python3-certbot-apache -y
+
+sudo ufw disable
+sudo certbot --apache -d matomo.mark37.com
+sudo ufw enable
+
+
+
+cron settings for Ssl renew
+
+0 6 * * 0 certbot renew -n -q --pre-hook “systemctl stop apache2” --post-hook “systemctl start apache2”
diff --git a/scripttease/lib/commands/messages.py b/scripttease/lib/commands/messages.py
index 5aff258..2654907 100644
--- a/scripttease/lib/commands/messages.py
+++ b/scripttease/lib/commands/messages.py
@@ -50,6 +50,27 @@ def explain(message, heading=None, **kwargs):
return Content("explain", message=message, heading=heading, **kwargs)
+def mattermost(message, url=None, **kwargs):
+ """Send a message to a Mattermost channel.
+
+ :param message: The message to be sent.
+ :type message: str
+
+ :param url: The URL of the Mattermost channel.
+ :type url: str
+
+ """
+ if url is None:
+ raise InvalidInput("mattermost command requires a url parameter.")
+
+ statement = list()
+ statement.append("curl -X POST -H 'Content-type: application/json' --data")
+ statement.append('\'{"text": "%s"}\'' % message)
+ statement.append(url)
+
+ return Command(" ".join(statement), **kwargs)
+
+
def screenshot(image, caption=None, css=None, height=None, width=None, **kwargs):
"""Create a screenshot for documentation.
@@ -90,7 +111,7 @@ def slack(message, url=None, **kwargs):
statement.append('\'{"text": "%s"}\'' % message)
statement.append(url)
- return Command(statement, **kwargs)
+ return Command(" ".join(statement), **kwargs)
def twist(message, title="Notice", url=None, **kwargs):
@@ -121,6 +142,7 @@ MESSAGE_MAPPINGS = {
'dialog': dialog,
'echo': echo,
'explain': explain,
+ 'mattermost': mattermost,
'screenshot': screenshot,
'slack': slack,
'twist': twist,
diff --git a/scripttease/lib/commands/pgsql.py b/scripttease/lib/commands/pgsql.py
index 6d843bc..d63f9fe 100644
--- a/scripttease/lib/commands/pgsql.py
+++ b/scripttease/lib/commands/pgsql.py
@@ -100,6 +100,9 @@ def pgsql_create(database, owner=None, template=None, **kwargs):
if template is not None:
kwargs['template'] = template
+ # SELECT 'CREATE DATABASE '
+ # WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '')\gexec
+
# psql -U postgres -tc "SELECT 1 FROM pg_database WHERE datname = ''" | grep -q 1 | psql -U postgres -c "CREATE DATABASE "
# first = pgsql("psql", **kwargs)
#
diff --git a/tests/test_lib_commands_messages.py b/tests/test_lib_commands_messages.py
index 3472cf0..088060b 100644
--- a/tests/test_lib_commands_messages.py
+++ b/tests/test_lib_commands_messages.py
@@ -22,6 +22,18 @@ def test_explain():
assert explain("this is a test") is not None
+def test_mattermost():
+
+ with pytest.raises(InvalidInput):
+ mattermost("This is a test.")
+
+ c = mattermost("This is a test.", url="https://example.mattermost.com/asdf/1234")
+ s = c.get_statement(include_comment=False)
+
+ assert "curl -X POST -H 'Content-type: application/json' --data" in s
+ assert "This is a test." in s
+ assert "https://example.mattermost.com/asdf/1234" in s
+
def test_screenshot():
assert screenshot("static/images/testing.png") is not None