diff options
| author | salmonik <raisersoft@proton.me> | 2026-03-23 17:43:09 +0100 |
|---|---|---|
| committer | salmonik <raisersoft@proton.me> | 2026-03-23 17:43:09 +0100 |
| commit | 106789319b1de06e9e8206c3a8d1dedab84496a1 (patch) | |
| tree | 9fd916450f911c2332e4ff3e80d78cdf4f2a6998 | |
| parent | normalised times on vclogs, and improved jarvis via reply chaining (diff) | |
| download | senator-sperma-106789319b1de06e9e8206c3a8d1dedab84496a1.tar.gz senator-sperma-106789319b1de06e9e8206c3a8d1dedab84496a1.zip | |
unify settings api into one file
| -rw-r--r-- | cogs/tts.py | 16 | ||||
| -rw-r--r-- | cogs/utils/settings.py | 62 | ||||
| -rw-r--r-- | cogs/vclogs.py | 26 | ||||
| -rw-r--r-- | main.py | 39 |
4 files changed, 75 insertions, 68 deletions
diff --git a/cogs/tts.py b/cogs/tts.py index 46ab637..5e6945c 100644 --- a/cogs/tts.py +++ b/cogs/tts.py | |||
| @@ -6,12 +6,12 @@ | |||
| 6 | import os | 6 | import os |
| 7 | import json | 7 | import json |
| 8 | import discord | 8 | import discord |
| 9 | import aiofiles | ||
| 10 | import logging | 9 | import logging |
| 11 | import tempfile | 10 | import tempfile |
| 12 | from discord.ext import commands | 11 | from discord.ext import commands |
| 13 | from gtts import gTTS | 12 | from gtts import gTTS |
| 14 | import asyncio | 13 | import asyncio |
| 14 | from cogs.utils.settings import get_volume | ||
| 15 | 15 | ||
| 16 | logger = logging.getLogger(__name__) | 16 | logger = logging.getLogger(__name__) |
| 17 | 17 | ||
| @@ -19,18 +19,6 @@ class TTS(commands.Cog): | |||
| 19 | def __init__(self, bot): | 19 | def __init__(self, bot): |
| 20 | self.bot = bot | 20 | self.bot = bot |
| 21 | 21 | ||
| 22 | async def _load_settings(self): | ||
| 23 | """Load volume settings from settings.json""" | ||
| 24 | volume = 1.0 | ||
| 25 | try: | ||
| 26 | async with aiofiles.open('settings.json') as f: | ||
| 27 | content = await f.read() | ||
| 28 | data = json.loads(content) | ||
| 29 | volume = data.get('volume', 1.0) | ||
| 30 | except (json.JSONDecodeError, KeyError, FileNotFoundError) as e: | ||
| 31 | logger.error(f"Error loading settings: {e}") | ||
| 32 | return volume | ||
| 33 | |||
| 34 | async def _handle_file_output(self, ctx, temp_path, text): | 22 | async def _handle_file_output(self, ctx, temp_path, text): |
| 35 | """Handle TTS file output""" | 23 | """Handle TTS file output""" |
| 36 | try: | 24 | try: |
| @@ -109,7 +97,7 @@ class TTS(commands.Cog): | |||
| 109 | tts.save(temp_path) | 97 | tts.save(temp_path) |
| 110 | 98 | ||
| 111 | # Load settings | 99 | # Load settings |
| 112 | volume = await self._load_settings() | 100 | volume = get_volume() |
| 113 | 101 | ||
| 114 | # Handle output based on user choice | 102 | # Handle output based on user choice |
| 115 | if output == "file": | 103 | if output == "file": |
diff --git a/cogs/utils/settings.py b/cogs/utils/settings.py new file mode 100644 index 0000000..0a1716f --- /dev/null +++ b/cogs/utils/settings.py | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | # This file is part of Senator Sperma | ||
| 2 | # Licensed under the GPL-3.0 License | ||
| 3 | # Copyright (C) 2026 Salmonik @ salmonik@tuta.io | ||
| 4 | # https://codeberg.org/salmonik/senator-sperma | ||
| 5 | |||
| 6 | import json | ||
| 7 | import logging | ||
| 8 | import aiofiles | ||
| 9 | import os | ||
| 10 | |||
| 11 | logger = logging.getLogger(__name__) | ||
| 12 | |||
| 13 | _settings = None | ||
| 14 | settings_file = "data/settings.json" | ||
| 15 | |||
| 16 | async def load_settings(): | ||
| 17 | global _settings | ||
| 18 | global settings_file | ||
| 19 | |||
| 20 | default_settings = { | ||
| 21 | 'volume': 1.0, | ||
| 22 | 'baseurl': 'http://localhost:8080' | ||
| 23 | } | ||
| 24 | |||
| 25 | try: | ||
| 26 | if os.path.exists(settings_file): | ||
| 27 | async with aiofiles.open(settings_file, 'r') as f: | ||
| 28 | content = await f.read() | ||
| 29 | if content.strip(): | ||
| 30 | _settings = json.loads(content) | ||
| 31 | logger.info("Settings loaded into memory") | ||
| 32 | else: | ||
| 33 | _settings = default_settings | ||
| 34 | await save_settings() | ||
| 35 | logger.warning("Empty settings.json, reset to defaults") | ||
| 36 | else: | ||
| 37 | _settings = default_settings | ||
| 38 | await save_settings() | ||
| 39 | logger.info("Created default settings.json") | ||
| 40 | except (json.JSONDecodeError, Exception) as e: | ||
| 41 | logger.error(f"Error loading settings: {e}") | ||
| 42 | _settings = default_settings | ||
| 43 | |||
| 44 | return _settings | ||
| 45 | |||
| 46 | |||
| 47 | async def save_settings(): | ||
| 48 | if _settings: | ||
| 49 | async with aiofiles.open(settings_file, 'w') as f: | ||
| 50 | await f.write(json.dumps(_settings, indent=2)) | ||
| 51 | |||
| 52 | |||
| 53 | def get_settings(): | ||
| 54 | return _settings | ||
| 55 | |||
| 56 | |||
| 57 | def get_volume(): | ||
| 58 | return _settings.get('volume', 1.0) if _settings else 1.0 | ||
| 59 | |||
| 60 | |||
| 61 | def get_baseurl(): | ||
| 62 | return _settings.get('baseurl', 'http://localhost:8080').rstrip('/') if _settings else 'http://localhost:8080' \ No newline at end of file | ||
diff --git a/cogs/vclogs.py b/cogs/vclogs.py index f2efca7..0d80ae7 100644 --- a/cogs/vclogs.py +++ b/cogs/vclogs.py | |||
| @@ -11,8 +11,8 @@ import asyncio | |||
| 11 | import discord | 11 | import discord |
| 12 | from discord.ext import commands | 12 | from discord.ext import commands |
| 13 | from gtts import gTTS | 13 | from gtts import gTTS |
| 14 | import aiofiles | ||
| 15 | from cogs.voice import get_voice_manager | 14 | from cogs.voice import get_voice_manager |
| 15 | from cogs.utils.settings import get_volume, save_settings | ||
| 16 | 16 | ||
| 17 | logger = logging.getLogger(__name__) | 17 | logger = logging.getLogger(__name__) |
| 18 | 18 | ||
| @@ -51,8 +51,6 @@ class VcLogs(commands.Cog): | |||
| 51 | self._voice_manager = get_voice_manager(self.bot) | 51 | self._voice_manager = get_voice_manager(self.bot) |
| 52 | return self._voice_manager | 52 | return self._voice_manager |
| 53 | 53 | ||
| 54 | settings_file = 'settings.json' | ||
| 55 | |||
| 56 | @staticmethod | 54 | @staticmethod |
| 57 | async def handle_state_change(member, channel, state_type, is_enabled, log_channel): | 55 | async def handle_state_change(member, channel, state_type, is_enabled, log_channel): |
| 58 | """Helper method to handle voice state changes""" | 56 | """Helper method to handle voice state changes""" |
| @@ -81,13 +79,7 @@ class VcLogs(commands.Cog): | |||
| 81 | tts.save(tts_file) | 79 | tts.save(tts_file) |
| 82 | 80 | ||
| 83 | voice_client = await voice_mgr.get_voice_client(channel.guild) | 81 | voice_client = await voice_mgr.get_voice_client(channel.guild) |
| 84 | volume = 1.0 | 82 | volume = get_volume() |
| 85 | |||
| 86 | if os.path.exists(VcLogs.settings_file): | ||
| 87 | async with aiofiles.open(VcLogs.settings_file) as f: | ||
| 88 | content = await f.read() | ||
| 89 | data = json.loads(content) | ||
| 90 | volume = data.get('volume', 1.0) | ||
| 91 | 83 | ||
| 92 | if voice_client is None: | 84 | if voice_client is None: |
| 93 | voice_client = await voice_mgr.join_channel(channel) | 85 | voice_client = await voice_mgr.join_channel(channel) |
| @@ -107,14 +99,12 @@ class VcLogs(commands.Cog): | |||
| 107 | name="log_volume" | 99 | name="log_volume" |
| 108 | ) | 100 | ) |
| 109 | async def volume(self, ctx: discord.ApplicationContext, volume: int): | 101 | async def volume(self, ctx: discord.ApplicationContext, volume: int): |
| 110 | try: | 102 | from cogs.utils.settings import get_settings |
| 111 | async with aiofiles.open(VcLogs.settings_file, 'w') as f: | 103 | settings = get_settings() |
| 112 | json.dump({"volume": volume}, f, indent=4) | 104 | settings['volume'] = volume |
| 113 | await ctx.followup.send(f"Volume has been set to: {volume}") | 105 | await save_settings() |
| 114 | logger.info(f"Volume changed to: {volume}") | 106 | await ctx.followup.send(f"Volume has been set to: {volume}") |
| 115 | except Exception as e: | 107 | logger.info(f"Volume changed to: {volume}") |
| 116 | await ctx.respond(e, ephemeral=True) | ||
| 117 | logger.error(f"Error in volume command: {e}", exc_info=True) | ||
| 118 | 108 | ||
| 119 | @commands.Cog.listener() | 109 | @commands.Cog.listener() |
| 120 | async def on_voice_state_update(self, member, before, after): | 110 | async def on_voice_state_update(self, member, before, after): |
| @@ -6,14 +6,13 @@ | |||
| 6 | import logging | 6 | import logging |
| 7 | import os | 7 | import os |
| 8 | import sys | 8 | import sys |
| 9 | import json | ||
| 10 | import asyncio | 9 | import asyncio |
| 11 | import aiofiles | ||
| 12 | import discord | 10 | import discord |
| 13 | from discord.ext import commands | 11 | from discord.ext import commands |
| 14 | from dotenv import load_dotenv | 12 | from dotenv import load_dotenv |
| 15 | 13 | ||
| 16 | from cogs.voice import get_voice_manager | 14 | from cogs.voice import get_voice_manager |
| 15 | from cogs.utils import settings | ||
| 17 | 16 | ||
| 18 | # Configure logging | 17 | # Configure logging |
| 19 | logging.basicConfig( | 18 | logging.basicConfig( |
| @@ -32,49 +31,16 @@ asyncio.set_event_loop(loop) | |||
| 32 | intents = discord.Intents.all() | 31 | intents = discord.Intents.all() |
| 33 | bot = commands.Bot(intents=intents, loop=loop) | 32 | bot = commands.Bot(intents=intents, loop=loop) |
| 34 | 33 | ||
| 35 | settings = "settings.json" | ||
| 36 | 34 | ||
| 37 | @bot.event | 35 | @bot.event |
| 38 | async def on_ready(): | 36 | async def on_ready(): |
| 39 | logger.info("ŁUKASZ SPERMA AKTYWACJA") | 37 | logger.info("ŁUKASZ SPERMA AKTYWACJA") |
| 40 | 38 | ||
| 41 | # send the message to channel ID | ||
| 42 | channel = bot.get_channel(1081667823799111804) | 39 | channel = bot.get_channel(1081667823799111804) |
| 43 | 40 | ||
| 44 | await channel.send("ŁUKASZ SPERMA AKTYWACJA") | 41 | await channel.send("ŁUKASZ SPERMA AKTYWACJA") |
| 45 | 42 | ||
| 46 | # Create settings.json if it doesn't exist | 43 | await settings.load_settings() |
| 47 | if not os.path.exists(settings): | ||
| 48 | default_settings = { | ||
| 49 | 'volume': 1.0, | ||
| 50 | 'file_paths': ['audio', 'music', 'sounds', 'videos', 'images'], | ||
| 51 | 'baseurl': 'http://localhost:8080' | ||
| 52 | } | ||
| 53 | async with aiofiles.open(settings, 'w') as f: | ||
| 54 | await f.write(json.dumps(default_settings, indent=2)) | ||
| 55 | logger.info("settings.json created") | ||
| 56 | |||
| 57 | # Validate and fix settings.json if it exists | ||
| 58 | if os.path.exists(settings): | ||
| 59 | try: | ||
| 60 | async with aiofiles.open(settings, 'r') as f: | ||
| 61 | content = await f.read() | ||
| 62 | if not content.strip(): | ||
| 63 | raise json.JSONDecodeError("Empty file", "", 0) | ||
| 64 | data = json.loads(content) | ||
| 65 | assert 'volume' in data and isinstance(data['volume'], float) | ||
| 66 | assert 'file_paths' in data and isinstance(data['file_paths'], list) | ||
| 67 | assert 'baseurl' in data and isinstance(data['baseurl'], str) | ||
| 68 | except (json.JSONDecodeError, AssertionError) as error: | ||
| 69 | logger.error(f"Error loading settings.json: {error}") | ||
| 70 | default_settings = { | ||
| 71 | 'volume': 1.0, | ||
| 72 | 'file_paths': ['audio', 'music', 'sounds', 'videos', 'images'], | ||
| 73 | 'baseurl': 'http://localhost:8080' | ||
| 74 | } | ||
| 75 | async with aiofiles.open(settings, 'w') as f: | ||
| 76 | await f.write(json.dumps(default_settings, indent=2)) | ||
| 77 | logger.info("settings.json recreated") | ||
| 78 | 44 | ||
| 79 | 45 | ||
| 80 | 46 | ||
| @@ -95,6 +61,7 @@ if __name__ == "__main__": | |||
| 95 | 'cogs.music.stop', | 61 | 'cogs.music.stop', |
| 96 | 'cogs.music.join', | 62 | 'cogs.music.join', |
| 97 | 'cogs.search', | 63 | 'cogs.search', |
| 64 | 'cogs.trigger', | ||
| 98 | ] | 65 | ] |
| 99 | 66 | ||
| 100 | try: | 67 | try: |
