diff options
| author | salmonik <raisersoft@proton.me> | 2026-04-29 14:47:32 +0200 |
|---|---|---|
| committer | salmonik <raisersoft@proton.me> | 2026-04-29 14:47:32 +0200 |
| commit | 8a4352ebb5e15ff4be82a9b4e111c1535aab349e (patch) | |
| tree | 2c4d5b4b65bdc8308b35c411cffa7f17b1bfeb4d /cogs/cron.py | |
| parent | fix: fallback to plaintext if no json is provided for assistant.py (diff) | |
| parent | proper context for settings (diff) | |
| download | senator-sperma-8a4352ebb5e15ff4be82a9b4e111c1535aab349e.tar.gz senator-sperma-8a4352ebb5e15ff4be82a9b4e111c1535aab349e.zip | |
Merge branch 'dev'
Signed-off-by: salmonik <raisersoft@proton.me>
Diffstat (limited to '')
| -rw-r--r-- | cogs/cron.py | 98 |
1 files changed, 65 insertions, 33 deletions
diff --git a/cogs/cron.py b/cogs/cron.py index da8127b..aad43d2 100644 --- a/cogs/cron.py +++ b/cogs/cron.py | |||
| @@ -4,9 +4,7 @@ | |||
| 4 | # https://codeberg.org/salmonik/senator-sperma | 4 | # https://codeberg.org/salmonik/senator-sperma |
| 5 | 5 | ||
| 6 | import asyncio | 6 | import asyncio |
| 7 | import json | ||
| 8 | import logging | 7 | import logging |
| 9 | import os | ||
| 10 | from datetime import datetime | 8 | from datetime import datetime |
| 11 | from venv import logger | 9 | from venv import logger |
| 12 | 10 | ||
| @@ -16,37 +14,67 @@ from discord.ext import commands | |||
| 16 | 14 | ||
| 17 | from cogs.utils import file_search as search_utils | 15 | from cogs.utils import file_search as search_utils |
| 18 | from cogs.voice import get_voice_manager | 16 | from cogs.voice import get_voice_manager |
| 17 | from cogs.utils.database import get_connection, init_database | ||
| 19 | 18 | ||
| 20 | logger = logging.getLogger(__name__) | 19 | logger = logging.getLogger(__name__) |
| 21 | 20 | ||
| 21 | init_database() | ||
| 22 | |||
| 22 | 23 | ||
| 23 | class Cron(commands.Cog): | 24 | class Cron(commands.Cog): |
| 24 | def __init__(self, bot): | 25 | def __init__(self, bot): |
| 25 | self.bot = bot | 26 | self.bot = bot |
| 26 | self.scheduled_tasks = [] | 27 | self.scheduled_tasks = [] |
| 27 | self.cron_file = "data/cron_jobs.json" | ||
| 28 | self.load_tasks() | 28 | self.load_tasks() |
| 29 | self.task = bot.loop.create_task(self.schedule_checker()) | 29 | self.task = bot.loop.create_task(self.schedule_checker()) |
| 30 | 30 | ||
| 31 | def load_tasks(self): | 31 | def load_tasks(self): |
| 32 | """Load scheduled tasks from file""" | ||
| 33 | try: | 32 | try: |
| 34 | if os.path.exists(self.cron_file): | 33 | with get_connection() as conn: |
| 35 | with open(self.cron_file, "r") as f: | 34 | c = conn.cursor() |
| 36 | self.scheduled_tasks = json.load(f) | 35 | c.execute("SELECT id, cron_expression, type, channel_id, active, audio_filename, message FROM cron_jobs") |
| 37 | logger.info(f"Loaded {len(self.scheduled_tasks)} cron jobs") | 36 | rows = c.fetchall() |
| 38 | else: | 37 | |
| 39 | self.scheduled_tasks = [] | 38 | self.scheduled_tasks = [ |
| 39 | { | ||
| 40 | "id": row[0], | ||
| 41 | "cron_expression": row[1], | ||
| 42 | "type": row[2], | ||
| 43 | "channel_id": row[3], | ||
| 44 | "active": bool(row[4]), | ||
| 45 | "audio_filename": row[5], | ||
| 46 | "message": row[6], | ||
| 47 | } | ||
| 48 | for row in rows | ||
| 49 | ] | ||
| 50 | logger.info(f"Loaded {len(self.scheduled_tasks)} cron jobs from database") | ||
| 40 | except Exception as e: | 51 | except Exception as e: |
| 41 | logger.error(f"Error loading cron jobs: {e}") | 52 | logger.error(f"Error loading cron jobs: {e}") |
| 42 | self.scheduled_tasks = [] | 53 | self.scheduled_tasks = [] |
| 43 | 54 | ||
| 44 | def save_tasks(self): | 55 | def save_tasks(self): |
| 45 | """Save scheduled tasks to file""" | ||
| 46 | try: | 56 | try: |
| 47 | os.makedirs(os.path.dirname(self.cron_file), exist_ok=True) | 57 | with get_connection() as conn: |
| 48 | with open(self.cron_file, "w") as f: | 58 | c = conn.cursor() |
| 49 | json.dump(self.scheduled_tasks, f, indent=2) | 59 | c.execute("PRAGMA foreign_keys = ON") |
| 60 | |||
| 61 | c.execute("DELETE FROM cron_jobs") | ||
| 62 | |||
| 63 | for task in self.scheduled_tasks: | ||
| 64 | c.execute( | ||
| 65 | """INSERT INTO cron_jobs (id, cron_expression, type, channel_id, active, audio_filename, message) | ||
| 66 | VALUES (?, ?, ?, ?, ?, ?, ?)""", | ||
| 67 | ( | ||
| 68 | task.get("id"), | ||
| 69 | task["cron_expression"], | ||
| 70 | task["type"], | ||
| 71 | task["channel_id"], | ||
| 72 | int(task.get("active", True)), | ||
| 73 | task.get("audio_filename"), | ||
| 74 | task.get("message"), | ||
| 75 | ), | ||
| 76 | ) | ||
| 77 | conn.commit() | ||
| 50 | except Exception as e: | 78 | except Exception as e: |
| 51 | logger.error(f"Error saving cron jobs: {e}") | 79 | logger.error(f"Error saving cron jobs: {e}") |
| 52 | 80 | ||
| @@ -104,7 +132,7 @@ class Cron(commands.Cog): | |||
| 104 | 132 | ||
| 105 | if task_type in ("zagraj_audio", "audio"): | 133 | if task_type in ("zagraj_audio", "audio"): |
| 106 | await self.play_audio_task(task, channel) | 134 | await self.play_audio_task(task, channel) |
| 107 | elif task_type in ("wyślij_wiadomość", "send_message"): | 135 | elif task_type in ("wyślij_wiadomość", "send_message", "wiadomość"): |
| 108 | await self.send_message_task(task, channel) | 136 | await self.send_message_task(task, channel) |
| 109 | 137 | ||
| 110 | logger.info(f"Executed task {task['id']} of type {task_type}") | 138 | logger.info(f"Executed task {task['id']} of type {task_type}") |
| @@ -132,11 +160,13 @@ class Cron(commands.Cog): | |||
| 132 | while voice_client.is_playing(): | 160 | while voice_client.is_playing(): |
| 133 | await asyncio.sleep(1) | 161 | await asyncio.sleep(1) |
| 134 | 162 | ||
| 163 | logger.info("Audio playback finished normally - disconnecting") | ||
| 135 | await voice_client.disconnect() | 164 | await voice_client.disconnect() |
| 136 | logger.info(f"Finished playing audio: {audio_url}") | 165 | logger.info(f"Finished playing audio: {audio_url}") |
| 137 | except Exception as e: | 166 | except Exception as e: |
| 138 | logger.error(f"Error playing audio: {e}") | 167 | logger.error(f"Error playing audio: {e}") |
| 139 | if voice_client.is_connected(): | 168 | if voice_client.is_connected(): |
| 169 | logger.info("Audio playback failed - disconnecting") | ||
| 140 | await voice_client.disconnect() | 170 | await voice_client.disconnect() |
| 141 | if channel.guild.system_channel: | 171 | if channel.guild.system_channel: |
| 142 | await channel.guild.system_channel.send( | 172 | await channel.guild.system_channel.send( |
| @@ -176,8 +206,19 @@ class Cron(commands.Cog): | |||
| 176 | else [discord.OptionChoice(name="Brak wyników", value="")] | 206 | else [discord.OptionChoice(name="Brak wyników", value="")] |
| 177 | ) | 207 | ) |
| 178 | 208 | ||
| 179 | @commands.slash_command( | 209 | def _get_baseurl(self): |
| 180 | name="cron_dodaj_audio", description="Dodaj nowe zadanie cron audio" | 210 | """Get base URL from settings""" |
| 211 | try: | ||
| 212 | from cogs.utils.settings import get_baseurl | ||
| 213 | |||
| 214 | return get_baseurl() | ||
| 215 | except Exception: | ||
| 216 | return "" | ||
| 217 | |||
| 218 | trigger_group = discord.SlashCommandGroup("cron", "komendy cron") | ||
| 219 | |||
| 220 | @trigger_group.command( | ||
| 221 | name="dodaj_audio", description="Dodaj nowe zadanie cron audio" | ||
| 181 | ) | 222 | ) |
| 182 | async def cron_add_audio( | 223 | async def cron_add_audio( |
| 183 | self, | 224 | self, |
| @@ -227,8 +268,8 @@ class Cron(commands.Cog): | |||
| 227 | f"Zadanie cron dodane. ID: {task_id}\nSkładnia: `{cron_expression}`\nAkcja: audio\nKanał: <#{channel.id}>" | 268 | f"Zadanie cron dodane. ID: {task_id}\nSkładnia: `{cron_expression}`\nAkcja: audio\nKanał: <#{channel.id}>" |
| 228 | ) | 269 | ) |
| 229 | 270 | ||
| 230 | @commands.slash_command( | 271 | @trigger_group.command( |
| 231 | name="cron_dodaj_wiadomość", description="Dodaj nowe zadanie cron wiadomość" | 272 | name="dodaj_wiadomość", description="Dodaj nowe zadanie cron wiadomość" |
| 232 | ) | 273 | ) |
| 233 | async def cron_add_message( | 274 | async def cron_add_message( |
| 234 | self, | 275 | self, |
| @@ -272,17 +313,8 @@ class Cron(commands.Cog): | |||
| 272 | f"Zadanie cron dodane. ID: {task_id}\nSkładnia: `{cron_expression}`\nAkcja: wiadomość\nKanał: <#{channel.id}>" | 313 | f"Zadanie cron dodane. ID: {task_id}\nSkładnia: `{cron_expression}`\nAkcja: wiadomość\nKanał: <#{channel.id}>" |
| 273 | ) | 314 | ) |
| 274 | 315 | ||
| 275 | def _get_baseurl(self): | 316 | @trigger_group.command( |
| 276 | """Get base URL from settings""" | 317 | name="pokaż", description="Pokaż wszystkie zadania cron" |
| 277 | try: | ||
| 278 | from cogs.utils.settings import get_baseurl | ||
| 279 | |||
| 280 | return get_baseurl() | ||
| 281 | except Exception: | ||
| 282 | return "" | ||
| 283 | |||
| 284 | @commands.slash_command( | ||
| 285 | name="cron_pokaż", description="Pokaż wszystkie zadania cron" | ||
| 286 | ) | 318 | ) |
| 287 | async def cron_list(self, ctx): | 319 | async def cron_list(self, ctx): |
| 288 | """List all cron jobs""" | 320 | """List all cron jobs""" |
| @@ -313,7 +345,7 @@ class Cron(commands.Cog): | |||
| 313 | 345 | ||
| 314 | await ctx.respond(embed=embed) | 346 | await ctx.respond(embed=embed) |
| 315 | 347 | ||
| 316 | @commands.slash_command(name="cron_usuń", description="Usuń zadanie cron z ID") | 348 | @trigger_group.command(name="usuń", description="Usuń zadanie cron z ID") |
| 317 | async def cron_remove( | 349 | async def cron_remove( |
| 318 | self, | 350 | self, |
| 319 | ctx, | 351 | ctx, |
| @@ -331,7 +363,7 @@ class Cron(commands.Cog): | |||
| 331 | 363 | ||
| 332 | await ctx.respond(f"Nie znaleziono zadania cron z ID {job_id}") | 364 | await ctx.respond(f"Nie znaleziono zadania cron z ID {job_id}") |
| 333 | 365 | ||
| 334 | @commands.slash_command(name="cron_pauza", description="Zapauzuj zadanie cron z ID") | 366 | @trigger_group.command(name="pauza", description="Zapauzuj zadanie cron z ID") |
| 335 | async def cron_pause( | 367 | async def cron_pause( |
| 336 | self, | 368 | self, |
| 337 | ctx, | 369 | ctx, |
| @@ -349,7 +381,7 @@ class Cron(commands.Cog): | |||
| 349 | 381 | ||
| 350 | await ctx.respond(f"Nie znaleziono zadania cron z ID {job_id}") | 382 | await ctx.respond(f"Nie znaleziono zadania cron z ID {job_id}") |
| 351 | 383 | ||
| 352 | @commands.slash_command(name="cron_wznów", description="Wznów zadanie cron z ID") | 384 | @trigger_group.command(name="wznów", description="Wznów zadanie cron z ID") |
| 353 | async def cron_resume( | 385 | async def cron_resume( |
| 354 | self, | 386 | self, |
| 355 | ctx, | 387 | ctx, |
