Compare commits
9 Commits
rewrite-v1.0
...
v0.5
| Author | SHA1 | Date | |
|---|---|---|---|
| 0b031d20f9 | |||
| bfd497898e | |||
| 077f845b94 | |||
| 26e3a4bb8e | |||
| f56636c1ff | |||
| f427d06e61 | |||
| 42bd226a60 | |||
| 4dd578c9a8 | |||
| 01d90e6625 |
@@ -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
|
||||||
@@ -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
|
||||||
@@ -4,7 +4,6 @@ config/*.ini
|
|||||||
pastebin.txt
|
pastebin.txt
|
||||||
.DS_Store
|
.DS_Store
|
||||||
test*.py
|
test*.py
|
||||||
.dockerignore
|
|
||||||
docker-*
|
docker-*
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
|
|||||||
+22
@@ -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,6 +1,6 @@
|
|||||||
MIT License
|
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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+25
-3
@@ -5,7 +5,7 @@ from cogs.base_cog import Base_Cog
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
from praw.models import Submission, Subreddit
|
from asyncpraw.models import Submission
|
||||||
from utils.portal import Portal
|
from utils.portal import Portal
|
||||||
import aiohttp
|
import aiohttp
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
@@ -93,7 +93,7 @@ class Post_Command(Base_Cog):
|
|||||||
author = subm.author.name if subm.author else "Author not found"
|
author = subm.author.name if subm.author else "Author not found"
|
||||||
content = f":copyright: [{author}]({url})"
|
content = f":copyright: [{author}]({url})"
|
||||||
if use_title:
|
if use_title:
|
||||||
content += f"\n## {subm.title}"
|
content += f"\n# {subm.title}"
|
||||||
|
|
||||||
if custom_note:
|
if custom_note:
|
||||||
content += f"\n> {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")
|
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:
|
except Exception as error:
|
||||||
self._logger.error(f"Could not complete command by {ctx.user.name} ({ctx.user.id})")
|
self._logger.error(f"Could not complete command by {ctx.user.name} ({ctx.user.id})")
|
||||||
self._logger.exception(error, stack_info = True)
|
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}`",
|
description = f"While we processed your request, the following exception occured: `{error}`",
|
||||||
color = 0xED4337
|
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):
|
async def setup(bot:commands.Bot):
|
||||||
|
|||||||
+20
-24
@@ -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
|
from datetime import datetime
|
||||||
startup = datetime.now().timestamp()
|
|
||||||
|
|
||||||
# Initialize the logger
|
|
||||||
from utils.logger.custom_logging import Custom_Logger
|
from utils.logger.custom_logging import Custom_Logger
|
||||||
Custom_Logger.initialize()
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
app_logger = logging.getLogger("app")
|
|
||||||
startup_logger = logging.getLogger("app.startup")
|
|
||||||
|
|
||||||
from utils.adv_configparser import Advanced_ConfigParser
|
from utils.adv_configparser import Advanced_ConfigParser
|
||||||
from utils.datetime_tools import get_elapsed_time_smal, get_elapsed_time_big, get_elapsed_time_milliseconds
|
from utils.datetime_tools import get_elapsed_time_smal, get_elapsed_time_big, get_elapsed_time_milliseconds
|
||||||
import discord
|
import discord
|
||||||
@@ -33,6 +14,23 @@ import asyncio
|
|||||||
from typing import Union
|
from typing import Union
|
||||||
from platforms.reddit import Reddit_Adapter
|
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()
|
source_path = Path(__file__).resolve()
|
||||||
base_path = source_path.parents[1]
|
base_path = source_path.parents[1]
|
||||||
app_logger.info(f"Using the following path as entrypoint: '{base_path}'")
|
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]):
|
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"""
|
"""Called when a `app_commands.Command` or `app_commands.ContextMenu` has successfully completed without error"""
|
||||||
self.__portal.no_succeeded_commands += 1
|
self.__portal.no_succeeded_commands += 1
|
||||||
print("Command succeeded")
|
|
||||||
|
|
||||||
async def on_interaction(self, interaction: discord.Interaction):
|
async def on_interaction(self, interaction: discord.Interaction):
|
||||||
"""Called when an interaction happened"""
|
"""Called when an interaction happened"""
|
||||||
match interaction.type.name:
|
match interaction.type.name:
|
||||||
case discord.InteractionType.application_command.name:
|
case discord.InteractionType.application_command.name:
|
||||||
print("Interaction with bot", interaction.command.name)
|
|
||||||
self.__portal.no_executed_commands += 1
|
self.__portal.no_executed_commands += 1
|
||||||
case discord.InteractionType.ping.name:
|
case discord.InteractionType.ping.name:
|
||||||
print("App got pinged by discord")
|
print("App got pinged by discord")
|
||||||
@@ -78,20 +74,20 @@ class MyBot(commands.Bot):
|
|||||||
async def on_connect(self):
|
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"""
|
"""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:
|
if not self.__first_on_ready:
|
||||||
startup_logger.info(f"Beginning startup routine ...")
|
startup_logger.info("Beginning startup routine ...")
|
||||||
routine_begin = datetime.now().timestamp()
|
routine_begin = datetime.now().timestamp()
|
||||||
await self.change_presence(status = discord.Status.dnd, activity = discord.CustomActivity("Executing pre startup routine"))
|
await self.change_presence(status = discord.Status.dnd, activity = discord.CustomActivity("Executing pre startup routine"))
|
||||||
|
|
||||||
# Create the adapters for the platforms
|
# Create the adapters for the platforms
|
||||||
task_start = datetime.now().timestamp()
|
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"))
|
platforms_config = Advanced_ConfigParser(Path.joinpath(base_path, "config", "platforms.ini"))
|
||||||
portal.platforms_config = platforms_config
|
portal.platforms_config = platforms_config
|
||||||
startup_logger.info(f"Loaded platforms config after {get_elapsed_time_milliseconds(datetime.now().timestamp() - task_start)}")
|
startup_logger.info(f"Loaded platforms config after {get_elapsed_time_milliseconds(datetime.now().timestamp() - task_start)}")
|
||||||
|
|
||||||
# Create platforms adapter
|
# Create platforms adapter
|
||||||
task_start = datetime.now().timestamp()
|
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"])
|
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)}")
|
startup_logger.info(f"Created reddit adapter after {get_elapsed_time_milliseconds(datetime.now().timestamp() - task_start)}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user