1 Commits

Author SHA1 Message Date
Thomas Peetz e2ff26f6bf Setup MessageModerator as Docker build
refs #28
2025-07-16 16:04:33 +02:00
10 changed files with 258 additions and 9 deletions
+81
View File
@@ -0,0 +1,81 @@
"""
read file with URLs and store in DB
"""
import logging.config
import requests
import yaml
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
from pathlib import Path
from platformdirs import PlatformDirs
from proton import Message, Event
from proton.handlers import MessagingHandler
from proton.reactor import Container
parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
parser.add_argument('-u', '--url', help='link')
parser.add_argument('--video', help='store Url as VideoFile', action="store_true")
parser.add_argument("--api", help="use Kontor API", action="store_true")
parser.add_argument('--config', '-c', default='kontor-docker')
parser.add_argument('--verbose', '-v', action='count', default=0)
args = parser.parse_args()
def get_logger(level: int, config: str):
dirs = PlatformDirs(config)
logging_config = Path(dirs.user_config_dir, 'logging-config.yaml')
with open(logging_config, 'rt') as f:
configDict = yaml.safe_load(f.read())
logging.config.dictConfig(configDict)
logger = logging.getLogger('development')
if level is not None:
match level:
case 0:
logger.setLevel(logging.INFO)
case 1:
logger.setLevel(logging.DEBUG)
case _:
logger.setLevel(logging.CRITICAL)
return logger
class AddLinkMessage(MessagingHandler):
def __init__(self, server, url, log):
super(AddLinkMessage, self).__init__()
log.info("create AddLinkMessage")
self.server = server
self.address = "add_link_file"
self.url = url
self.log = log
def on_start(self, event: Event):
self.log.info("Connection...")
conn = event.container.connect(self.server, user="artemis", password="artemis")
event.container.create_sender(conn, self.address)
def on_connection_error(self, event: Event) -> None:
self.log.info(f"error: {event}")
def on_sendable(self, event: Event):
self.log.info("send message")
event.sender.send(Message(body=self.url, address=self.address, content_type="text/json"))
event.connection.close()
event.sender.close()
def on_accepted(self, event: Event) -> None:
self.log.info(f"accepted: {event}")
if __name__ == '__main__':
logger = get_logger(args.verbose, args.config)
logger.info('kontor.add_link started')
link: str = args.url
data = {"url": link}
if args.api:
if args.video:
request: str = "http://127.0.0.1:8800/api/video/files"
else:
request: str = "http://127.0.0.1:8800/api/media/files"
response = requests.post(request, json=data)
logger.info(f"Status: {response.status_code}")
data = response.json()
else:
Container(AddLinkMessage("amqp://127.0.0.1:5672", data, logger)).run()
logger.info('kontor.add_link finished')
@@ -0,0 +1 @@
3.13
@@ -0,0 +1,50 @@
## ------------------------------- Builder Stage ------------------------------ ##
FROM python:3.13-bookworm AS builder
RUN apt-get update && apt-get install --no-install-recommends -y build-essential && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# Download the latest installer, install it and then remove it
ADD https://astral.sh/uv/install.sh /install.sh
RUN chmod -R 655 /install.sh && /install.sh && rm /install.sh
# Set up the UV environment path correctly
ENV PATH="/root/.local/bin:${PATH}"
WORKDIR /app
COPY ./pyproject.toml .
RUN uv sync
# ------------------------------- Production Stage ------------------------------ ##
FROM python:3.13-slim-bookworm AS production
# The following secrets are available during build time
#RUN --mount=type=secret,id=DB_PASSWORD \
# --mount=type=secret,id=DB_USER \
# --mount=type=secret,id=DB_NAME \
# --mount=type=secret,id=DB_HOST \
# --mount=type=secret,id=DB_PORT \
# DB_PASSWORD=/run/secrets/DB_PASSWORD \
# DB_USER=$(cat /run/secrets/DB_USER) \
# DB_NAME=$(cat /run/secrets/DB_NAME) \
# DB_HOST=$(cat /run/secrets/DB_HOST) \
# DB_PORT=$(cat /run/secrets/DB_PORT)
#RUN --mount=type=secret,id=secret-key,target=secrets.json
RUN useradd --create-home appuser
USER appuser
WORKDIR /app
COPY /src src
COPY --from=builder /app/.venv .venv
# Set up environment variables for production
ENV PATH="/app/.venv/bin:$PATH"
# Start the application with Uvicorn in production mode, using environment variable references
CMD ["python", "src/main.py", "--log-level", "info"]
@@ -0,0 +1,16 @@
[project]
name = "kontor-domain"
version = "0.2.0"
description = "Example setup of DDD"
readme = "README.md"
authors = [
{name = "Thomas Peetz", email = "thomas.peetz@thpeetz.de"}
]
maintainers = [
{name = "Thomas Peetz", email = "thomas.peetz@thpeetz.de"}
]
requires-python = ">=3.13"
dependencies = [
"python-qpid-proton>=0.40.0",
]
@@ -0,0 +1,6 @@
def main():
print("Hello from kontor-domain!")
if __name__ == "__main__":
main()
+57
View File
@@ -0,0 +1,57 @@
version = 1
revision = 2
requires-python = ">=3.13"
[[package]]
name = "cffi"
version = "1.17.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pycparser" },
]
sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989, upload-time = "2024-09-04T20:44:28.956Z" },
{ url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802, upload-time = "2024-09-04T20:44:30.289Z" },
{ url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792, upload-time = "2024-09-04T20:44:32.01Z" },
{ url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893, upload-time = "2024-09-04T20:44:33.606Z" },
{ url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810, upload-time = "2024-09-04T20:44:35.191Z" },
{ url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200, upload-time = "2024-09-04T20:44:36.743Z" },
{ url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447, upload-time = "2024-09-04T20:44:38.492Z" },
{ url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358, upload-time = "2024-09-04T20:44:40.046Z" },
{ url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469, upload-time = "2024-09-04T20:44:41.616Z" },
{ url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475, upload-time = "2024-09-04T20:44:43.733Z" },
{ url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009, upload-time = "2024-09-04T20:44:45.309Z" },
]
[[package]]
name = "kontor-domain"
version = "0.2.0"
source = { virtual = "." }
dependencies = [
{ name = "python-qpid-proton" },
]
[package.metadata]
requires-dist = [{ name = "python-qpid-proton", specifier = ">=0.40.0" }]
[[package]]
name = "pycparser"
version = "2.22"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736, upload-time = "2024-03-30T13:22:22.564Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552, upload-time = "2024-03-30T13:22:20.476Z" },
]
[[package]]
name = "python-qpid-proton"
version = "0.40.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cffi" },
]
sdist = { url = "https://files.pythonhosted.org/packages/d5/dd/e9e5066009517bdfee92374264a2b6794fa0987bfeddcbf4d2a08dccaf36/python_qpid_proton-0.40.0.tar.gz", hash = "sha256:7680d607cf6e9684f97bf5b2ba16cda7d8512aab9e4ff78f98d44a4644fc819a", size = 354215, upload-time = "2025-05-19T18:45:37.932Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7b/dd/a82c1e377f08d62d83898c1aa9b39aef890e910f683fca6dc5242a123f6b/python_qpid_proton-0.40.0-cp313-cp313-win_amd64.whl", hash = "sha256:a19d8c71c908700ceb38f6cbc1eb4a039428570f96bfc2caeeafdfec804fb94f", size = 277376, upload-time = "2025-05-19T19:39:31.201Z" },
]
+2 -1
View File
@@ -49,10 +49,11 @@ class AddLinkMessage(MessagingHandler):
message = Message(body=self.url, address=self.address, content_type="application/json", durable=True) message = Message(body=self.url, address=self.address, content_type="application/json", durable=True)
delivery = event.sender.send(message) delivery = event.sender.send(message)
self.log.info(f"Delivery {delivery} sent") self.log.info(f"Delivery {delivery} sent")
event.connection.close() #event.connection.close()
def on_accepted(self, event: Event) -> None: def on_accepted(self, event: Event) -> None:
self.log.info(f"accepted Delivery: {event.delivery.remote_state}") self.log.info(f"accepted Delivery: {event.delivery.remote_state}")
event.connection.close()
def on_rejected(self, event: Event) -> None: def on_rejected(self, event: Event) -> None:
+45 -8
View File
@@ -2,6 +2,9 @@ import stomp
import json import json
import time import time
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
from proton import Message, Event, symbol
from proton.handlers import MessagingHandler
from proton.reactor import Container, ReceiverOption, SenderOption
from config import get_logger from config import get_logger
parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter) parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
@@ -23,15 +26,49 @@ class MyListener(stomp.ConnectionListener):
self.log.info(f"found link: {url}") self.log.info(f"found link: {url}")
class AddLinkReceiver(MessagingHandler):
def __init__(self, server, log):
super(AddLinkReceiver, self).__init__()
self.log = log
self.log.info("create AddLinkReceiver")
self.server = server
self.conn = None
self.address = "KontorMediaFile::add_link_file"
def on_start(self, event: Event) -> None:
self.log.info("AddLinkReceiver started...")
self.conn = event.container.connect(self.server, user="artemis", password="artemis")
event.container.create_receiver(self.conn, self.address, options=ReceiverCapabilityOptions())
def on_link_opened(self, event: Event) -> None:
self.log.info(f"AddLinkReceiver opened for address {self.address}")
def on_message(self, event: Event) -> None:
message = event.message
self.log.info(f"AddLinkReceiver message received: {message}")
class ReceiverCapabilityOptions(ReceiverOption):
def apply(self, receiver):
receiver.source.capabilities.put_object(symbol("queue"))
class SenderCapabilityOptions(SenderOption):
def apply(self, sender):
sender.source.capabilities.put_object(symbol("queue"))
if __name__ == '__main__': if __name__ == '__main__':
log = get_logger(args.verbose, args.config) log = get_logger(args.verbose, args.config)
log.info("kontor.read_queue started") log.info("kontor.read_queue started")
host = [('127.0.0.1', 61616)] handler = AddLinkReceiver("amqp://127.0.0.1:5672", log)
conn = stomp.Connection(host_and_ports=host) container = Container(handler)
conn.set_listener('', MyListener(log)) container.run()
conn.connect(username='artemis', passcode='artemis', wait=True) #host = [('127.0.0.1', 61616)]
conn.subscribe(destination='KontorMediaFile::add_link_file', id=1, ack='auto', headers={}) #conn = stomp.Connection(host_and_ports=host)
time.sleep(5) #conn.set_listener('', MyListener(log))
conn.disconnect() #conn.connect(username='artemis', passcode='artemis', wait=True)
#conn.subscribe(destination='KontorMediaFile::add_link_file', id=1, ack='auto', headers={})
#time.sleep(5)
#conn.disconnect()
log.info("kontor.read_queue finished") log.info("kontor.read_queue finished")