1 Commits

Author SHA1 Message Date
f804911c42 [CI SKIP] Update mollre/journal-bot Docker tag to v1.0.67 2024-03-12 19:00:33 +00:00
29 changed files with 289 additions and 472 deletions

29
.drone.yml Normal file
View File

@@ -0,0 +1,29 @@
kind: pipeline
type: kubernetes
name: docker-build
node_selector:
kubernetes.io/arch: amd64
steps:
- name: docker
image: plugins/docker
settings:
username:
from_secret: docker_uname
password:
from_secret: docker_pw
repo: mollre/journal-bot
tags:
- 1.0.${DRONE_BUILD_NUMBER}
- latest
build_args: "BOT_VERSION=1.0.${DRONE_BUILD_NUMBER}"
trigger:
branch:
- main
event:
- push

1
.envrc
View File

@@ -1 +0,0 @@
use nix

View File

@@ -1,50 +0,0 @@
on:
pull_request:
branches:
- main
push:
branches:
- main
name: Build container
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: https://gitea.com/actions/checkout@v4
- name: Fetch tags from main branch
id: version
run: |
git fetch origin main --tags
LATEST_TAG=$(git describe --tags $(git rev-list --tags --max-count=1))
# remove the 'v' prefix from the tag name
echo "BUILD_NAME=${LATEST_TAG//v}" >> $GITHUB_OUTPUT
- name: Output the version that is being used
run: |
echo "Building for version ${{ steps.version.outputs.BUILD_NAME }}"
- name: Login to Docker Registry
uses: docker/login-action@v3
with:
registry: git.kluster.moll.re
username: ${{ gitea.repository_owner }}
password: ${{ secrets.PACKAGE_REGISTRY_ACCESS }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
# use the current commit SHA as the tag
tags: git.kluster.moll.re/remoll/journal-bot:${{ steps.version.outputs.BUILD_NAME }}-${{ gitea.run_number }}
push: true

10
.gitignore vendored
View File

@@ -1,13 +1,9 @@
# Nix shell files
.direnv/
# Secrets
*.secret.yaml
dev.env
secret.yaml
# Static data
.bot/
.bot_storage/
# ---> Python
# Byte-compiled / optimized / DLL files

View File

@@ -1 +0,0 @@
3.13

4
.vscode/launch.json vendored
View File

@@ -6,7 +6,7 @@
"configurations": [
{
"name": "Python: Current project",
"type": "debugpy",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/bot/main.py",
"console": "integratedTerminal",
@@ -14,4 +14,4 @@
"envFile": "${workspaceFolder}/dev.env",
}
]
}
}

View File

@@ -1,14 +1,17 @@
FROM docker.io/python:3.13-alpine
# use the latest version of uv, independently of the python version
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
FROM python:3-slim
ENV DOCKERIZED=true
ARG BOT_VERSION
# set at build time
ENV BOT_VERSION=$BOT_VERSION
WORKDIR /app
RUN pip install pipenv
# copy the requirements and install them
COPY pyproject.toml uv.lock .
RUN uv sync --frozen
# copy the rest of the code
COPY Pipfile Pipfile.lock ./
RUN pipenv install --system --deploy
COPY bot .
CMD ["uv", "run", "main.py"]
CMD ["python", "main.py"]

7
Makefile Normal file
View File

@@ -0,0 +1,7 @@
CURRENT_DIR := $(shell pwd)
DOTENV := ${CURRENT_DIR}/dev.env
PIPENV_CMD_PREFIX := PIPENV_DOTENV_LOCATION=${DOTENV} pipenv run
run:
${PIPENV_CMD_PREFIX} python bot/main.py

14
Pipfile Normal file
View File

@@ -0,0 +1,14 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
peewee = "*"
python-telegram-bot = {extras = ["job-queue"], version = "*"}
anyio = "*"
[dev-packages]
[pipenv]
allow_prereleases = true

131
Pipfile.lock generated Normal file
View File

@@ -0,0 +1,131 @@
{
"_meta": {
"hash": {
"sha256": "5458e81c4f85af776acc44f46af838644ef8c00ccf4223fbe06f9d76a4717fc6"
},
"pipfile-spec": 6,
"requires": {},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"anyio": {
"hashes": [
"sha256:48d53f0b141f5757c38d648309e6fe254857fae092d67f938fa248d7c0f36804",
"sha256:596b09c520820e7eed961ddc889540972f92d5e8fcb081117fc054c409df34ae"
],
"index": "pypi",
"version": "==4.0.0rc1"
},
"apscheduler": {
"hashes": [
"sha256:0293937d8f6051a0f493359440c1a1b93e882c57daf0197afeff0e727777b96e",
"sha256:e813ad5ada7aff36fb08cdda746b520531eaac7757832abc204868ba78e0c8f6"
],
"version": "==3.10.1"
},
"certifi": {
"hashes": [
"sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082",
"sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"
],
"markers": "python_version >= '3.6'",
"version": "==2023.7.22"
},
"h11": {
"hashes": [
"sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d",
"sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"
],
"markers": "python_version >= '3.7'",
"version": "==0.14.0"
},
"httpcore": {
"hashes": [
"sha256:a6f30213335e34c1ade7be6ec7c47f19f50c56db36abef1a9dfa3815b1cb3888",
"sha256:c2789b767ddddfa2a5782e3199b2b7f6894540b17b16ec26b2c4d8e103510b87"
],
"markers": "python_version >= '3.7'",
"version": "==0.17.3"
},
"httpx": {
"hashes": [
"sha256:06781eb9ac53cde990577af654bd990a4949de37a28bdb4a230d434f3a30b9bd",
"sha256:5853a43053df830c20f8110c5e69fe44d035d850b2dfe795e196f00fdb774bdd"
],
"markers": "python_version >= '3.7'",
"version": "==0.24.1"
},
"idna": {
"hashes": [
"sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4",
"sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"
],
"markers": "python_version >= '3.5'",
"version": "==3.4"
},
"peewee": {
"hashes": [
"sha256:10769981198c7311f84a0ca8db892fa213303a8eb1305deb795a71e7bd606a91"
],
"index": "pypi",
"version": "==3.16.2"
},
"python-telegram-bot": {
"extras": [
"job-queue"
],
"hashes": [
"sha256:a6ac3f9c9674aaf7d1c7e652d8b75cde969fb872f75e9521b8516eceaba82b1b",
"sha256:e426404b0006989a5bcc05e11a7ef3ffe0c086b684a4e963db5bda1d361a049a"
],
"index": "pypi",
"version": "==20.4"
},
"pytz": {
"hashes": [
"sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588",
"sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"
],
"version": "==2023.3"
},
"setuptools": {
"hashes": [
"sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f",
"sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235"
],
"markers": "python_version >= '3.7'",
"version": "==68.0.0"
},
"six": {
"hashes": [
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.16.0"
},
"sniffio": {
"hashes": [
"sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101",
"sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"
],
"markers": "python_version >= '3.7'",
"version": "==1.3.0"
},
"tzlocal": {
"hashes": [
"sha256:46eb99ad4bdb71f3f72b7d24f4267753e240944ecfc16f25d2719ba89827a803",
"sha256:f3596e180296aaf2dbd97d124fe76ae3a0e3d32b258447de7b939b3fd4be992f"
],
"markers": "python_version >= '3.7'",
"version": "==5.0.1"
}
},
"develop": {}
}

View File

@@ -38,7 +38,7 @@ class JournalHandler(BaseHandler):
async def entry_point(self, update, context):
await super().entry_point(update, context)
if models.IS_PRODUCTION and os.getenv("CHAT_ID") != str(update.message.chat_id):
if os.getenv("DOCKERIZED", "false") == "true" and os.getenv("CHAT_ID") != str(update.message.chat_id):
await update.message.reply_text("You are not authorized to use this bot")
return ConversationHandler.END
@@ -79,7 +79,7 @@ class JournalHandler(BaseHandler):
else:
await query.edit_message_text(text="An entry already exists for this date")
return ConversationHandler.END
return CONTENT_ENTRY
@@ -113,13 +113,13 @@ class JournalHandler(BaseHandler):
async def date_entry(self, update, context):
date = update.message.text
try:
date = datetime.datetime.strptime(date, "%d%m%Y").date()
except ValueError:
await update.message.reply_text("Please enter the date in the format _DDMMYYYY_", parse_mode=ParseMode.MARKDOWN_V2)
return ENTRY_OPTIONS
if context.chat_data.get("delete", False): # if not set, delete was not chosen
with models.db:
self.current_model = models.JournalEntry.get_or_none(
@@ -158,7 +158,7 @@ class JournalHandler(BaseHandler):
file = await update.message.effective_attachment[-1].get_file()
else:
file = await update.message.effective_attachment.get_file()
file_bytes = await file.download_as_bytearray()
file_path = file.file_path
self.current_model.save_media(file_bytes, file_path)
@@ -211,7 +211,7 @@ def get_names(dates: list):
suffix = ""
if models.JournalEntry.get_or_none(date = d):
suffix = ""
if d == datetime.datetime.now().date():
names.append("Today" + suffix)
elif d == datetime.datetime.now().date() - datetime.timedelta(days = 1):

View File

@@ -1,5 +1,5 @@
from pathlib import Path
from peewee import *
db = DatabaseProxy()
class BaseModel(Model):
@@ -13,7 +13,7 @@ class ListModel(BaseModel):
@property
def content(self) -> dict:
return {e.id: e.entry for e in self.entries}
@content.setter
def content(self, new_content: dict):
old_content = self.content
@@ -29,7 +29,7 @@ class ListModel(BaseModel):
@property
def done_dict(self):
return {e.id: e.done for e in self.entries}
@done_dict.setter
def done_dict(self, new_done: dict):
old_done_dict = self.done_dict
@@ -46,8 +46,7 @@ class ListEntryModel(BaseModel):
done = BooleanField(default=None, null=True)
def set_db(db_path: Path):
db_path.parent.mkdir(parents=True, exist_ok=True)
def set_db(db_path):
db.initialize(SqliteDatabase(db_path))
with db:
db.create_tables([ListModel, ListEntryModel], safe=True)

View File

@@ -3,7 +3,7 @@ from telegram.ext import ConversationHandler, CommandHandler, MessageHandler, fi
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update, InputMediaPhoto
import models
from telegram.constants import ParseMode
# ACTION_CHOICE, DATE_ENTRY, ADD_CONTENT = range(3)
MEMORY_CHOICE = range(1)
@@ -28,7 +28,7 @@ class MemoryHandler(BaseHandler):
async def entry_point(self, update: Update, context: CallbackContext):
await super().entry_point(update, context)
if models.IS_PRODUCTION and os.getenv("CHAT_ID") != str(update.message.chat_id):
if os.getenv("DOCKERIZED", "false") == "true" and os.getenv("CHAT_ID") != str(update.message.chat_id):
await update.message.reply_text("You are not authorized to use this bot")
return ConversationHandler.END
@@ -56,9 +56,9 @@ class MemoryHandler(BaseHandler):
await update.message.reply_text(
f"Which moment would you like to remember?", reply_markup=keyboard
)
context.chat_data["kept_matches"] = list(matching_models)
return MEMORY_CHOICE
async def choose_memory(self, update: Update, context: CallbackContext):

View File

@@ -7,14 +7,10 @@ from telegram.constants import ParseMode
import os
FIRST = 1
import models
from .basehandler import BaseHandler
class StatusHandler(BaseHandler):
"""Shows a short status of the program."""
def __init__(self, entry_string):
self.start_time = datetime.datetime.now()
self.entry_string = entry_string
@@ -39,6 +35,7 @@ class StatusHandler(BaseHandler):
reply_markup = InlineKeyboardMarkup(keyboard)
delta = str(datetime.datetime.now() - self.start_time)
message = "BeebBop, this is Norbit\n"
try:
ip = httpx.get('https://api.ipify.org').text
@@ -50,21 +47,18 @@ class StatusHandler(BaseHandler):
ip = "not fetchable"
local_ips = "not fetchable"
message = f"""
BeebBop\!
Status: Running 🟢
Version: `{os.getenv('BOT_VERSION', 'dev')}` and`prod={models.IS_PRODUCTION}`
Uptime: `{delta[:delta.rfind('.')]}`
IP \(public\): `{ip}`
IP \(private\): `{local_ips}`
Chat ID: `{update.effective_chat.id}`
""".strip() # remove trailing whitespace
message += "Status: Running 🟢\n"
message += f"Version: `{os.getenv('BOT_VERSION', 'dev')}`\n"
message += f"Uptime: `{delta[:delta.rfind('.')]}`\n"
message += f"IP \(public\): `{ip}`\n"
message += f"IP \(private\): `{local_ips}`\n"
message += f"Chat ID: `{update.effective_chat.id}`\n"
if update.message:
await update.message.reply_text(message, reply_markup=reply_markup, parse_mode=ParseMode.MARKDOWN_V2)
else:
await update._effective_chat.send_message(message, reply_markup=reply_markup, parse_mode=ParseMode.MARKDOWN_V2)
return FIRST

View File

@@ -13,8 +13,8 @@ class SetChatPhotoJob():
def __init__(self, bot: ExtBot, job_queue):
self.bot = bot
self.logger = logging.getLogger(self.__class__.__name__)
if not models.IS_PRODUCTION:
if os.getenv("DOCKERIZED", "false") != "true":
# when running locally, annoy the programmer every 60 seconds <3
job_queue.run_repeating(self.callback_photo, interval=60)
else:
@@ -24,13 +24,13 @@ class SetChatPhotoJob():
async def callback_photo(self, context):
# last_seen of memory must be older than 10 days in past or None
with models.db:
possible_photos = models.JournalEntry.select().where(
models.JournalEntry.media_path != None
).order_by(fn.Random())
try:
chosen_entry = possible_photos.get()
except:

View File

@@ -1,92 +0,0 @@
import os
from telegram.ext import ExtBot
from telegram.constants import ParseMode
import logging
from datetime import time, timedelta, timezone, datetime, date
from peewee import fn
import models
from telegram.ext import JobQueue
RANKING_TEMPLATE = """
<b>Journal Leaderboard</b>
This week: 📈{week_leader_name} - {week_leader_count} 📉{week_last_name} - {week_last_count}
This month: 📈{month_leader_name} - {month_leader_count} 📉{month_last_name} - {month_last_count}
This year: 📈{year_leader_name} - {year_leader_count} 📉{year_last_name} - {year_last_count}
🏆 Leader: {leader_name}
"""
def get_author_ranking(since_days):
"""Returns the query for the top authors by counting their journal entries. An additional field for the count is added."""
cutoff_date = date.today() - timedelta(days=since_days)
with models.db:
return models.JournalEntry.select(
models.JournalEntry.author,
fn.Count(models.JournalEntry.id).alias('message_count')
).where(
models.JournalEntry.date >= cutoff_date
).group_by(
models.JournalEntry.author
).order_by(
fn.Count(models.JournalEntry.id).desc()
)
class SendLeaderboard():
def __init__(self, bot: ExtBot, job_queue: JobQueue):
self.bot = bot
self.logger = logging.getLogger(self.__class__.__name__)
if not models.IS_PRODUCTION:
# when running locally, just run once after 10 seconds
job_queue.run_once(self.callback_leaderboard, when=10)
else:
# set the message sending time; include UTC shift +2
sending_time = time(hour=12, minute=0, second=0, tzinfo=timezone(timedelta(hours=2)))
job_queue.run_daily(self.callback_leaderboard, time=sending_time, days=(0,))
async def callback_leaderboard(self, context):
"""Send a weakly leaderboard to the chat."""
# get the top contributions of the past week, month and year:
ranking_week = get_author_ranking(7)
ranking_month = get_author_ranking(30)
ranking_year = get_author_ranking(365)
week_leader, week_last = ranking_week.first(n=2)
month_leader, month_last = ranking_month.first(n=2)
year_leader, year_last = ranking_year.first(n=2)
leader = year_leader
message_text = RANKING_TEMPLATE.format(
week_leader_name=week_leader.author,
week_leader_count=week_leader.message_count,
week_last_name=week_last.author,
week_last_count=week_last.message_count,
month_leader_name=month_leader.author,
month_leader_count=month_leader.message_count,
month_last_name=month_last.author,
month_last_count=month_last.message_count,
year_leader_name=year_leader.author,
year_leader_count=year_leader.message_count,
year_last_name=year_last.author,
year_last_count=year_last.message_count,
leader_name=leader.author
)
print(message_text)
chat_id = os.getenv("CHAT_ID")
await self.bot.send_message(
chat_id = chat_id,
text = message_text,
parse_mode=ParseMode.HTML
)

View File

@@ -4,14 +4,13 @@ import os
from peewee import fn
import logging
import models
from telegram.ext import ExtBot
class RandomMemoryJob():
def __init__(self, bot: ExtBot, job_queue):
def __init__(self, bot, job_queue):
self.bot = bot
self.logger = logging.getLogger(self.__class__.__name__)
if not models.IS_PRODUCTION:
if os.getenv("DOCKERIZED", "false") != "true":
# when running locally, annoy the programmer every 60 seconds <3
job_queue.run_repeating(self.callback_memory, interval=3600)
self.min_age = 0 # do not filter messages: show them all
@@ -23,14 +22,14 @@ class RandomMemoryJob():
async def callback_memory(self, context):
# last_seen of memory must be older than 10 days in past or None
with models.db:
possible_entries = models.JournalEntry.select().where(
(models.JournalEntry.last_shown <= datetime.today().date() - timedelta(days=self.min_age)) | \
(models.JournalEntry.last_shown == None)
).order_by(fn.Random())
try:
chosen_entry = possible_entries.get()
except:

View File

@@ -5,7 +5,7 @@ import logging
import models
from commands import journal, status, turtle, memory, advent
from commands.list import list
from cronjob import chat_photo, random_memory, leaderboard
from cronjob import chat_photo, random_memory
logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
@@ -32,7 +32,6 @@ def main() -> None:
random_memory.RandomMemoryJob(application.bot, application.job_queue)
chat_photo.SetChatPhotoJob(application.bot, application.job_queue)
leaderboard.SendLeaderboard(application.bot, application.job_queue)
# Run the bot until the user presses Ctrl-C
application.run_polling()

View File

@@ -2,7 +2,7 @@ from peewee import *
from pathlib import Path
import re
import os
import socket
import datetime
ID_MAPPINGS = {
"Lia": 5603036217,
@@ -11,9 +11,9 @@ ID_MAPPINGS = {
ID_MAPPINGS_REV = dict((v, k) for k, v in ID_MAPPINGS.items())
RATING_MAPPING = {
1: "🙁",
2: "😐",
3: "🙂",
1: "😵",
2: "☹️",
3: "😐",
4: "😃",
5: "🥰"
}
@@ -21,11 +21,6 @@ RATING_MAPPING = {
MEDIA_DIR = Path(os.getenv("MEDIA_DIR"))
MEDIA_DIR.mkdir(parents=True, exist_ok=True)
# check if we are running on a cluster
IS_PRODUCTION = os.getenv('KUBERNETES_SERVICE_HOST') is not None
db = DatabaseProxy()
class BaseModel(Model):
@@ -42,11 +37,11 @@ class JournalEntry(BaseModel):
media_path = TextField(null=True)
last_shown = DateField(null=True)
rating = IntegerField(null=True) # mapped by RATING_MAPPING
@property
def media(self):
return Path(self.media_path).open('rb')
def save_media(self, media: bytearray, file_name: str):
ext = Path(file_name).suffix
file_name = f"{self.date.isoformat()}-media{ext}"
@@ -79,20 +74,20 @@ class JournalEntry(BaseModel):
"""Returns the text with all the frisky details hidden away"""
new_text = self.text.replace("<", "&lt;").replace(">", "&gt;").replace("&", "&amp;")
pattern = re.compile(
r"("
r"(((?<=(\.|\!|\?)\s)[A-Z])|(^[A-Z]))" # beginning of a sentence
r"([^\.\!\?])+" # any character being part of a sentence
r"((\:\))|😇|😈|[Ss]ex)" # the smiley
r"([^\.\!\?])*" # continuation of sentence
r"(\.|\!|\?|\,|$)" # end of the sentence
r")"
"("
"(((?<=(\.|\!|\?)\s)[A-Z])|(^[A-Z]))" # beginning of a sentence
"([^\.\!\?])+" # any character being part of a sentence
"((\:\))|😇|😈|[Ss]ex)" # the smiley
"([^\.\!\?])*" # continuation of sentence
"(\.|\!|\?|\,|$)" # end of the sentence
")"
)
matches = pattern.findall(new_text)
for match in matches:
group_to_replace = match[0]
new_text = new_text.replace(group_to_replace, f"<tg-spoiler>{group_to_replace}</tg-spoiler>")
return new_text
def set_db(db_path):
db.initialize(SqliteDatabase(db_path))

View File

@@ -1,29 +0,0 @@
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
name = "journal-bot-shell";
buildInputs = with pkgs; [
# python
python313
# setuptools as downloaded by uv seems to be broken on nixos
python313Packages.setuptools
uv
];
# fix library dependencies:
env.LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [
# required by numpy and the likes
pkgs.stdenv.cc.cc.lib
pkgs.libz
];
# tell UV where to put the virtualenv:
# env.UV_PROJECT_ENVIRONMENT = ".cache/uv-venvs/thesis";
# install the python packages through uv:
shellHook = "
uv sync
source .venv/bin/activate
";
}

View File

@@ -17,7 +17,7 @@ spec:
spec:
containers:
- name: journal
image: journal
image: mollre/journal-bot:1.0.19
envFrom:
- secretRef:
name: journal-secret-env
@@ -33,3 +33,31 @@ spec:
- name: journal-nfs
persistentVolumeClaim:
claimName: journal-data-nfs
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: "journal-data-nfs"
spec:
storageClassName: ""
capacity:
storage: "5Gi"
accessModes:
- ReadWriteOnce
nfs:
path: /export/kluster/journal-bot
server: 192.168.1.157
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: "journal-data-nfs"
spec:
storageClassName: ""
accessModes:
- ReadWriteOnce
resources:
requests:
storage: "5Gi"
volumeName: journal-data-nfs

View File

@@ -1,15 +1,9 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./namespace.yaml
- ./deployment.yaml
- ./sealedsecret.yaml
- ./pvc.yaml
namespace: journal
images:
- name: journal
newName: git.kluster.moll.re/remoll/journal-bot
newTag: 1.1.0-17
- name: mollre/journal-bot
newTag: 1.0.67

View File

@@ -1,4 +1,6 @@
apiVersion: v1
kind: Namespace
metadata:
name: placeholder
name: journal
labels:
name: journal

View File

@@ -1,27 +0,0 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: "journal-data-nfs"
spec:
storageClassName: ""
capacity:
storage: "5Gi"
accessModes:
- ReadWriteOnce
nfs:
path: /export/kluster/journal-bot
server: 192.168.1.157
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: "journal-data-nfs"
spec:
storageClassName: ""
accessModes:
- ReadWriteOnce
resources:
requests:
storage: "5Gi"
volumeName: journal-data-nfs

View File

@@ -1,3 +0,0 @@
MEDIA_DIR="./.bot/media"
PERSISTENCE_DIR="./.bot/persistence"
DB_PATH="./.bot/db.sqlite"

View File

@@ -1,11 +0,0 @@
[project]
name = "journal-bot"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"anyio>=4.9.0",
"peewee>=3.18.2",
"python-telegram-bot[job-queue]>=22.3",
]

11
renovate.json Normal file
View File

@@ -0,0 +1,11 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"packageRules": [
{
"matchUpdateTypes": ["minor", "patch"],
"matchCurrentVersion": "!/^0/",
"automerge": true
}
],
"commitMessagePrefix" : "[CI SKIP]"
}

View File

@@ -1,17 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"dependencyDashboard": true,
"packageRules": [
// Fully automatically update the container version referenced in the deployment
{
"matchPackageNames": ["@kubernetes-sigs/kustomize"],
"automerge": true,
"automergeType": "branch",
"ignoreTests": true,
"commitMessagePrefix": "[skip ci]",
"registryUrls": [
"https://git.kluster.moll.re"
],
}
],
}

153
uv.lock generated
View File

@@ -1,153 +0,0 @@
version = 1
revision = 2
requires-python = ">=3.13"
[[package]]
name = "anyio"
version = "4.9.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "idna" },
{ name = "sniffio" },
]
sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949, upload-time = "2025-03-17T00:02:54.77Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916, upload-time = "2025-03-17T00:02:52.713Z" },
]
[[package]]
name = "apscheduler"
version = "3.11.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "tzlocal" },
]
sdist = { url = "https://files.pythonhosted.org/packages/4e/00/6d6814ddc19be2df62c8c898c4df6b5b1914f3bd024b780028caa392d186/apscheduler-3.11.0.tar.gz", hash = "sha256:4c622d250b0955a65d5d0eb91c33e6d43fd879834bf541e0a18661ae60460133", size = 107347, upload-time = "2024-11-24T19:39:26.463Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d0/ae/9a053dd9229c0fde6b1f1f33f609ccff1ee79ddda364c756a924c6d8563b/APScheduler-3.11.0-py3-none-any.whl", hash = "sha256:fc134ca32e50f5eadcc4938e3a4545ab19131435e851abb40b34d63d5141c6da", size = 64004, upload-time = "2024-11-24T19:39:24.442Z" },
]
[[package]]
name = "certifi"
version = "2025.7.14"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/b3/76/52c535bcebe74590f296d6c77c86dabf761c41980e1347a2422e4aa2ae41/certifi-2025.7.14.tar.gz", hash = "sha256:8ea99dbdfaaf2ba2f9bac77b9249ef62ec5218e7c2b2e903378ed5fccf765995", size = 163981, upload-time = "2025-07-14T03:29:28.449Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/4f/52/34c6cf5bb9285074dc3531c437b3919e825d976fde097a7a73f79e726d03/certifi-2025.7.14-py3-none-any.whl", hash = "sha256:6b31f564a415d79ee77df69d757bb49a5bb53bd9f756cbbe24394ffd6fc1f4b2", size = 162722, upload-time = "2025-07-14T03:29:26.863Z" },
]
[[package]]
name = "h11"
version = "0.16.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
]
[[package]]
name = "httpcore"
version = "1.0.9"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "certifi" },
{ name = "h11" },
]
sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" },
]
[[package]]
name = "httpx"
version = "0.28.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
{ name = "certifi" },
{ name = "httpcore" },
{ name = "idna" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
]
[[package]]
name = "idna"
version = "3.10"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" },
]
[[package]]
name = "journal-bot"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "anyio" },
{ name = "peewee" },
{ name = "python-telegram-bot", extra = ["job-queue"] },
]
[package.metadata]
requires-dist = [
{ name = "anyio", specifier = ">=4.9.0" },
{ name = "peewee", specifier = ">=3.18.2" },
{ name = "python-telegram-bot", extras = ["job-queue"], specifier = ">=22.3" },
]
[[package]]
name = "peewee"
version = "3.18.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/04/89/76f6f1b744c8608e0d416b588b9d63c2a500ff800065ae610f7c80f532d6/peewee-3.18.2.tar.gz", hash = "sha256:77a54263eb61aff2ea72f63d2eeb91b140c25c1884148e28e4c0f7c4f64996a0", size = 949220, upload-time = "2025-07-08T12:52:03.941Z" }
[[package]]
name = "python-telegram-bot"
version = "22.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "httpx" },
]
sdist = { url = "https://files.pythonhosted.org/packages/db/fc/0196e0d7ad247011a560788db204e0a28d76ab75b3d7c7131878f8fb5a06/python_telegram_bot-22.3.tar.gz", hash = "sha256:513d5ab9db96dcf25272dad0a726555e80edf60d09246a7d0d425b77115f5440", size = 1464513, upload-time = "2025-07-20T20:03:09.805Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e5/54/0955bd46a1e046169500e129c7883664b6675d580074d68823485e4d5de1/python_telegram_bot-22.3-py3-none-any.whl", hash = "sha256:88fab2d1652dbfd5379552e8b904d86173c524fdb9270d3a8685f599ffe0299f", size = 717115, upload-time = "2025-07-20T20:03:07.261Z" },
]
[package.optional-dependencies]
job-queue = [
{ name = "apscheduler" },
]
[[package]]
name = "sniffio"
version = "1.3.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
]
[[package]]
name = "tzdata"
version = "2025.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380, upload-time = "2025-03-23T13:54:43.652Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839, upload-time = "2025-03-23T13:54:41.845Z" },
]
[[package]]
name = "tzlocal"
version = "5.3.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "tzdata", marker = "sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/8b/2e/c14812d3d4d9cd1773c6be938f89e5735a1f11a9f184ac3639b93cef35d5/tzlocal-5.3.1.tar.gz", hash = "sha256:cceffc7edecefea1f595541dbd6e990cb1ea3d19bf01b2809f362a03dd7921fd", size = 30761, upload-time = "2025-03-05T21:17:41.549Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c2/14/e2a54fabd4f08cd7af1c07030603c3356b74da07f7cc056e600436edfa17/tzlocal-5.3.1-py3-none-any.whl", hash = "sha256:eb1a66c3ef5847adf7a834f1be0800581b683b5608e74f86ecbcef8ab91bb85d", size = 18026, upload-time = "2025-03-05T21:17:39.857Z" },
]