🎉 First commit!
Some checks failed
ci / docker (push) Failing after 37s
Python formatting PEP8 / Python-PEP8 (push) Failing after 17s

This commit is contained in:
Finn Christiansen 2024-06-26 19:52:11 +02:00
commit 99c2c62831
13 changed files with 280 additions and 0 deletions

4
.dockerignore Normal file
View file

@ -0,0 +1,4 @@
.env
bin
lib
include

10
.env.example Normal file
View file

@ -0,0 +1,10 @@
BOT_HOMESERVER="https://example.org"
BOT_USERNAME="PrayingTimesBotUsername"
BOT_PASSWORD="supersecret"
REGISTRATION_API_URL="http://localhost:5001/api/token"
REGISTRATION_API_SHARED_SECRET="supersecret"
REGISTRATION_URL="https://matrix.example.org/register?token="
SMTP_HOSTNAME="smtp.example.org"
SMTP_USERNAME="username"
SMTP_PASSWORD="password"
MAIL_FROM_ADDRESS="me@example.org"

View file

@ -0,0 +1,38 @@
name: ci
on:
push:
branches:
- "main"
jobs:
docker:
runs-on: ubuntu-latest
services:
registry:
image: registry:2
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Docker for QEMU
uses: https://github.com/papodaca/install-docker-action@main
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: code.f2n.me
username: ${{ secrets.MY_FORGEJO_USERNAME }}
password: ${{ secrets.MY_FORGEJO_TOKEN }}
- name: Build and push to local registry
uses: docker/build-push-action@v5
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: code.f2n.me/finn/matrix-bot-invitation-mailer:latest
- name: Inspect
run: |
docker buildx imagetools inspect code.f2n.me/finn/matrix-bot-invitation-mailer:latest

View file

@ -0,0 +1,21 @@
name: Python formatting PEP8
run-name: ${{ forgejo.actor }} is running PEP8 check
on: [push]
jobs:
Python-PEP8:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install dependencies
run: |
apt-get update
apt-get install -y python3-pip
pip install flake8
- name: Run checking
run: |
flake8 --ignore=E501 --extend-exclude bin,lib .

8
.gitignore vendored Normal file
View file

@ -0,0 +1,8 @@
bin/
lib/
include/
__pycache__
pyvenv.cfg
.env
session.txt
tags

13
Dockerfile Normal file
View file

@ -0,0 +1,13 @@
# syntax=docker/dockerfile:1
FROM python:3.12-alpine
WORKDIR /bot
RUN apk update && apk add python3-dev gcc libc-dev libffi-dev
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
COPY . .
ENTRYPOINT ["/bot/entrypoint.sh"]

15
README.md Normal file
View file

@ -0,0 +1,15 @@
# Matrix Bot for sending homeserver invitation link via e-mail
A early stage and simlpe Matrix bot which I use in addition to [matrix-registration](https://github.com/ZerataX/matrix-registration).
The bot calls the Api and sends the invitation link via e-mail to a given receipient.
## Usage
Use container image or run this after cloning:
```
. bin/active
python -m matrix_bot_invitation_mailer
```

17
compose.yml Normal file
View file

@ -0,0 +1,17 @@
---
services:
matrix-bot-invitation-mailer:
build:
context: .
image: code.f2n.me/finn/matrix-bot-invitation-mailer:latest
environment:
- BOT_HOMESERVER
- BOT_USERNAME
- BOT_PASSWORD
- REGISTRATION_API_URL
- REGISTRATION_API_SHARED_SECRET
- REGISTRATION_URL
- SMTP_HOSTNAME
- SMTP_USERNAME
- SMTP_PASSWORD
- MAIL_FROM_ADDRESS

4
data/.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

2
entrypoint.sh Executable file
View file

@ -0,0 +1,2 @@
#!/bin/sh
python -m matrix_bot_invitation_mailer

View file

View file

@ -0,0 +1,113 @@
import simplematrixbotlib as botlib
import requests
import os
import logging
import smtplib
import datetime
from email.mime.text import MIMEText
from dotenv import load_dotenv
load_dotenv()
creds = botlib.Creds(
os.getenv("BOT_HOMESERVER"),
os.getenv("BOT_USERNAME"),
os.getenv("BOT_PASSWORD"),
session_stored_file="data/session.txt"
)
bot = botlib.Bot(creds)
PREFIX = '!'
logging.basicConfig(level=logging.INFO)
@bot.listener.on_message_event
async def echo(room, message) -> None:
match = botlib.MessageMatch(room, message, bot, PREFIX)
if match.is_not_from_this_bot() and match.prefix() and match.command("echo"):
await bot.api.send_text_message(
room.room_id, " ".join(arg for arg in match.args())
)
@bot.listener.on_message_event
async def usage(room, message) -> None:
match = botlib.MessageMatch(room, message, bot, PREFIX)
response = """usage:
- **!invite** <johndoe@example.org> - sends e-mail with invitation link to given mail address
- **everything else** - prints this help
"""
if match.is_not_from_this_bot() and not match.prefix() and room.room_id:
await bot.api.send_markdown_message(room.room_id, response)
@bot.listener.on_message_event
async def invite(room, message) -> None:
match = botlib.MessageMatch(room, message, bot, PREFIX)
if match.is_not_from_this_bot() and match.prefix() and match.command("invite"):
logging.info("preparing invite")
# TODO: add validation
mail_address = " ".join(arg for arg in match.args())
send_invitation_mail(mail_address)
response = "mail sent"
await bot.api.send_text_message(room.room_id, response)
def send_invitation_mail(receiver_email):
logging.info("sending email...")
# make reqest to obtain registration token
headers = {
'Content-Type': "application/json",
'Authorization': "SharedSecret {}".format(os.getenv("REGISTRATION_API_SHARED_SECRET"))
}
payload = {
"max-usage": "1",
"expiration_date": (datetime.date.today() + datetime.timedelta(days=7)).strftime("%Y-%m-%d")
}
response = requests.post(os.getenv("REGISTRATION_API_URL"), headers=headers, json=payload)
logging.info(response.text)
logging.info(response.json())
sender_email = os.getenv("MAIL_FROM_ADDRESS")
body = """Hello,
you have been invited to the f2n.me matrix homeserver!
Click the following link and create your account:
{}
The link will be valid for 7 days.""".format(os.getenv("REGISTRATION_URL") + response.json()["name"])
msg = MIMEText(body, 'plain')
msg['From'] = sender_email
msg['To'] = receiver_email
msg['Subject'] = "Your matrix homeserver invitation link"
try:
# Connect to the SMTP server
server = smtplib.SMTP(os.getenv("SMTP_HOSTNAME"), os.getenv("SMTP_PORT"))
server.starttls() # Secure the connection
server.login(os.getenv("SMTP_USERNAME"), os.getenv("SMTP_PASSWORD")) # Login to the server
# Send the email
server.sendmail(sender_email, receiver_email, msg.as_string())
print("Email sent successfully")
except Exception as e:
print(f"Error: {e}")
finally:
# Close the connection
server.quit()
bot.run()

35
requirements.txt Normal file
View file

@ -0,0 +1,35 @@
aiofiles==23.2.1
aiohttp==3.9.5
aiohttp-socks==0.8.4
aiosignal==1.3.1
async-timeout==4.0.3
attrs==23.2.0
certifi==2024.6.2
cffi==1.16.0
charset-normalizer==3.3.2
cryptography==42.0.8
frozenlist==1.4.1
h11==0.14.0
h2==4.1.0
hpack==4.0.0
hyperframe==6.0.1
idna==3.7
jsonschema==4.22.0
jsonschema-specifications==2023.12.1
Markdown==3.6
matrix-nio==0.24.0
multidict==6.0.5
pillow==10.3.0
pycparser==2.22
pycryptodome==3.20.0
python-cryptography-fernet-wrapper==1.0.4
python-dotenv==1.0.1
python-socks==2.5.0
referencing==0.35.1
requests==2.32.3
rpds-py==0.18.1
simplematrixbotlib==2.11.0
toml==0.10.2
unpaddedbase64==2.1.0
urllib3==2.2.2
yarl==1.9.4