9 Commits

Author SHA1 Message Date
Cromatin 0b031d20f9 Merge pull request #3 from official-Cromatin/release-v0.5
Merge branch 'release-v0.5' into 'main'
2025-09-16 18:49:29 +02:00
lars-winzer bfd497898e Update copyright year 2025-09-16 18:30:07 +02:00
lars-winzer 077f845b94 Merge commit '42bd226a6007780debe6ee1ca6357185f409f70e' into release-v0.5 2025-09-16 18:28:05 +02:00
lars-winzer 26e3a4bb8e Update LICENSE 2025-09-16 18:13:56 +02:00
lars-winzer f56636c1ff Create workflow to build and release docker image on ghcr 2025-09-16 17:30:08 +02:00
lars-winzer f427d06e61 Create Dockerfile and .dockerignore for upcoming official docker support
- Update .gitignore
2025-09-16 16:07:07 +02:00
lars-winzer 42bd226a60 Update LICENSE 2025-09-16 16:03:13 +02:00
lars-winzer 4dd578c9a8 Refine '/post'-command error handling when file size exceeds upload limit 2025-09-16 14:13:02 +02:00
lars-winzer 01d90e6625 Move imports to the top of the document
- Remove unnecessary prints
- Remove unnecessary f-strings
2025-09-16 14:10:04 +02:00
7 changed files with 130 additions and 29 deletions
+27
View File
@@ -0,0 +1,27 @@
**/__pycache__
**/.venv
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/bin
**/charts
**/docker-compose*
**/compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
+35
View File
@@ -0,0 +1,35 @@
name: Release Multi-Arch Docker Image
on:
release:
types: [published]
jobs:
build-and-push-docker:
runs-on: self-hosted
steps:
- name: Checkout code
uses: actions/checkout@v4
- 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 GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push multi-arch image
uses: docker/build-push-action@v5
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: |
ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }}
ghcr.io/${{ github.repository }}:latest
-1
View File
@@ -4,7 +4,6 @@ config/*.ini
pastebin.txt
.DS_Store
test*.py
.dockerignore
docker-*
.vscode
+22
View File
@@ -0,0 +1,22 @@
# Base image (multi-arch via buildx)
FROM python:3.10-slim
# Prevents pyc files + enables unbuffered logging
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1
# Install dependencies
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy only necessary files (via .dockerignore)
COPY . .
# Create non-root user
RUN adduser --disabled-password --no-create-home --gecos "" appuser \
&& chown -R appuser /app
USER appuser
# Default command
ENTRYPOINT ["python", "src/main.py"]
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2024 Lars Winzer
Copyright (c) 2024-2025 Lars Winzer
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+25 -3
View File
@@ -5,7 +5,7 @@ from cogs.base_cog import Base_Cog
import logging
from urllib.parse import urlparse
from praw.models import Submission, Subreddit
from asyncpraw.models import Submission
from utils.portal import Portal
import aiohttp
from PIL import Image
@@ -93,7 +93,7 @@ class Post_Command(Base_Cog):
author = subm.author.name if subm.author else "Author not found"
content = f":copyright: [{author}]({url})"
if use_title:
content += f"\n## {subm.title}"
content += f"\n# {subm.title}"
if custom_note:
content += f"\n> {custom_note}"
@@ -134,6 +134,25 @@ class Post_Command(Base_Cog):
)
embed.set_footer(text = "Supported image formats: jpg, jpeg, png, webp, heic, heif")
except discord.errors.HTTPException as error:
self._logger.error(f"Could not complete command by {ctx.user.name} ({ctx.user.id})")
self._logger.exception(error, stack_info = True)
match error.code:
case 40005:
self._logger.error("Failed to upload images, payload too large")
embed = discord.Embed(
title = "Error while processing",
description = "The attachments exceed the upload limit of Discord,\nchoose a different quality level via the argument `quality`",
color = 0xED4337
)
if ctx.response.is_done():
await ctx.followup.send(embed = embed, ephemeral = True)
else:
await ctx.response.send_message(embed = embed)
except Exception as error:
self._logger.error(f"Could not complete command by {ctx.user.name} ({ctx.user.id})")
self._logger.exception(error, stack_info = True)
@@ -150,7 +169,10 @@ class Post_Command(Base_Cog):
description = f"While we processed your request, the following exception occured: `{error}`",
color = 0xED4337
)
await ctx.followup.send(embed = embed, ephemeral = True)
if ctx.response.is_done():
await ctx.followup.send(embed = embed, ephemeral = True)
else:
await ctx.response.send_message(embed = embed)
async def setup(bot:commands.Bot):
+20 -24
View File
@@ -1,25 +1,6 @@
print(" ____ ____ ___________ __________")
print(" / __ \/ __ \/ ___/_ __/ / _/_ __/")
print(" / /_/ / / / /\__ \ / /_____ / / / / ")
print(" / ____/ /_/ /___/ // /_____// / / / ")
print(" /_/ \____//____//_/ /___/ /_/ ")
print(" Copyright (c) 2024 Lars Winzer")
print()
print(" Source: https://github.com/official-Cromatin/Post-It")
print(" Report an Issue: https://github.com/official-Cromatin/Post-It/issues/new?assignees=&labels=bug&projects=&template=issue_report.yml")
print("\n")
from datetime import datetime
startup = datetime.now().timestamp()
# Initialize the logger
from utils.logger.custom_logging import Custom_Logger
Custom_Logger.initialize()
import logging
app_logger = logging.getLogger("app")
startup_logger = logging.getLogger("app.startup")
from utils.adv_configparser import Advanced_ConfigParser
from utils.datetime_tools import get_elapsed_time_smal, get_elapsed_time_big, get_elapsed_time_milliseconds
import discord
@@ -33,6 +14,23 @@ import asyncio
from typing import Union
from platforms.reddit import Reddit_Adapter
print(" ____ ____ ___________ __________")
print(" / __ \/ __ \/ ___/_ __/ / _/_ __/")
print(" / /_/ / / / /\__ \ / /_____ / / / / ")
print(" / ____/ /_/ /___/ // /_____// / / / ")
print(" /_/ \____//____//_/ /___/ /_/ ")
print(" Copyright (c) 2024-2025 Lars Winzer")
print()
print(" Source: https://github.com/official-Cromatin/Post-It")
print(" Report an Issue: https://github.com/official-Cromatin/Post-It/issues/new?assignees=&labels=bug&projects=&template=issue_report.yml")
print("\n")
startup = datetime.now().timestamp()
# Initialize the logger
Custom_Logger.initialize()
app_logger = logging.getLogger("app")
startup_logger = logging.getLogger("app.startup")
source_path = Path(__file__).resolve()
base_path = source_path.parents[1]
app_logger.info(f"Using the following path as entrypoint: '{base_path}'")
@@ -58,13 +56,11 @@ class MyBot(commands.Bot):
async def on_app_command_completion(self, interaction: discord.Interaction, command: Union[discord.app_commands.Command, discord.app_commands.ContextMenu]):
"""Called when a `app_commands.Command` or `app_commands.ContextMenu` has successfully completed without error"""
self.__portal.no_succeeded_commands += 1
print("Command succeeded")
async def on_interaction(self, interaction: discord.Interaction):
"""Called when an interaction happened"""
match interaction.type.name:
case discord.InteractionType.application_command.name:
print("Interaction with bot", interaction.command.name)
self.__portal.no_executed_commands += 1
case discord.InteractionType.ping.name:
print("App got pinged by discord")
@@ -78,20 +74,20 @@ class MyBot(commands.Bot):
async def on_connect(self):
"""A coroutine to be called to setup the bot, after the bot is logged in but before it has connected to the Websocket"""
if not self.__first_on_ready:
startup_logger.info(f"Beginning startup routine ...")
startup_logger.info("Beginning startup routine ...")
routine_begin = datetime.now().timestamp()
await self.change_presence(status = discord.Status.dnd, activity = discord.CustomActivity("Executing pre startup routine"))
# Create the adapters for the platforms
task_start = datetime.now().timestamp()
startup_logger.debug(f"Loading platforms config ...")
startup_logger.debug("Loading platforms config ...")
platforms_config = Advanced_ConfigParser(Path.joinpath(base_path, "config", "platforms.ini"))
portal.platforms_config = platforms_config
startup_logger.info(f"Loaded platforms config after {get_elapsed_time_milliseconds(datetime.now().timestamp() - task_start)}")
# Create platforms adapter
task_start = datetime.now().timestamp()
startup_logger.debug(f"Creating reddit adapter ...")
startup_logger.debug("Creating reddit adapter ...")
portal.reddit_adapter = Reddit_Adapter(platforms_config["REDDIT"]["CLIENT_ID"], platforms_config["REDDIT"]["CLIENT_SECRET"])
startup_logger.info(f"Created reddit adapter after {get_elapsed_time_milliseconds(datetime.now().timestamp() - task_start)}")