feat: add config input for the automated generation option
This commit is contained in:
parent
3a33411dd9
commit
e574277839
5 changed files with 55 additions and 39 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
[project]
|
[project]
|
||||||
name = "markovbot-gui"
|
name = "markovbot-gui"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
description = "Markov Chain Bot GUI"
|
description = "Markov Chain Bot GUI"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = [
|
authors = [
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
import json
|
|
||||||
import logging
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from kivy.clock import Clock
|
from kivy.clock import Clock
|
||||||
|
|
@ -10,6 +8,9 @@ from kivy.uix.label import Label
|
||||||
from kivy.uix.popup import Popup
|
from kivy.uix.popup import Popup
|
||||||
from kivy.uix.textinput import TextInput
|
from kivy.uix.textinput import TextInput
|
||||||
|
|
||||||
|
from src.markovbot_gui.libs.settings import Settings
|
||||||
|
from src.markovbot_gui.libs.timer import logger
|
||||||
|
|
||||||
|
|
||||||
class ConfigWindow(BoxLayout):
|
class ConfigWindow(BoxLayout):
|
||||||
def __init__(self, config_path: Path, **kwargs):
|
def __init__(self, config_path: Path, **kwargs):
|
||||||
|
|
@ -20,14 +21,13 @@ class ConfigWindow(BoxLayout):
|
||||||
self.padding = dp(20)
|
self.padding = dp(20)
|
||||||
|
|
||||||
# Load existing configuration
|
# Load existing configuration
|
||||||
self.default_config = {
|
default_config = {
|
||||||
"Host": "irc.chat.twitch.tv",
|
"Host": "irc.chat.twitch.tv",
|
||||||
"Port": 6667,
|
"Port": 6667,
|
||||||
"Channel": "#<channel>",
|
"Channel": "#<channel>",
|
||||||
"Nickname": "<name>",
|
"Nickname": "<name>",
|
||||||
"Authentication": "oauth:<auth>",
|
"Authentication": "oauth:<auth>",
|
||||||
"DeniedUsers": ["StreamElements", "Nightbot", "Moobot", "Marbiebot"],
|
"DeniedUsers": ["StreamElements", "Nightbot", "Moobot", "Marbiebot"],
|
||||||
"AllowedUsers": [],
|
|
||||||
"Cooldown": 20,
|
"Cooldown": 20,
|
||||||
"KeyLength": 2,
|
"KeyLength": 2,
|
||||||
"MaxSentenceWordAmount": 25,
|
"MaxSentenceWordAmount": 25,
|
||||||
|
|
@ -38,19 +38,13 @@ class ConfigWindow(BoxLayout):
|
||||||
"EnableGenerateCommand": True,
|
"EnableGenerateCommand": True,
|
||||||
"SentenceSeparator": " - ",
|
"SentenceSeparator": " - ",
|
||||||
"AllowGenerateParams": True,
|
"AllowGenerateParams": True,
|
||||||
"GenerateCommands": ["!generate", "!g"],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
|
||||||
if config_path.exists():
|
if config_path.exists():
|
||||||
with config_path.open("r") as f:
|
self.s = Settings.read(config_path)
|
||||||
saved_config = json.load(f)
|
else:
|
||||||
# Update self.default_config with saved values
|
self.s = Settings(**default_config) # type: ignore[arg-type]
|
||||||
self.default_config.update(saved_config)
|
self.s.write(config_path)
|
||||||
except json.JSONDecodeError:
|
|
||||||
logging.exception(f"Failed to parse config file at {config_path}")
|
|
||||||
except Exception:
|
|
||||||
logging.exception("Error loading config file")
|
|
||||||
|
|
||||||
# Create widgets
|
# Create widgets
|
||||||
# Channel input
|
# Channel input
|
||||||
|
|
@ -63,7 +57,7 @@ class ConfigWindow(BoxLayout):
|
||||||
self.channel_input = TextInput(
|
self.channel_input = TextInput(
|
||||||
multiline=False,
|
multiline=False,
|
||||||
size_hint_x=0.7,
|
size_hint_x=0.7,
|
||||||
text=self.default_config["Channel"],
|
text=self.s.channel,
|
||||||
)
|
)
|
||||||
channel_layout.add_widget(channel_label)
|
channel_layout.add_widget(channel_label)
|
||||||
channel_layout.add_widget(self.channel_input)
|
channel_layout.add_widget(self.channel_input)
|
||||||
|
|
@ -78,7 +72,7 @@ class ConfigWindow(BoxLayout):
|
||||||
self.nickname_input = TextInput(
|
self.nickname_input = TextInput(
|
||||||
multiline=False,
|
multiline=False,
|
||||||
size_hint_x=0.7,
|
size_hint_x=0.7,
|
||||||
text=self.default_config["Nickname"],
|
text=self.s.nickname,
|
||||||
)
|
)
|
||||||
nickname_layout.add_widget(nickname_label)
|
nickname_layout.add_widget(nickname_label)
|
||||||
nickname_layout.add_widget(self.nickname_input)
|
nickname_layout.add_widget(self.nickname_input)
|
||||||
|
|
@ -94,11 +88,25 @@ class ConfigWindow(BoxLayout):
|
||||||
multiline=False,
|
multiline=False,
|
||||||
size_hint_x=0.7,
|
size_hint_x=0.7,
|
||||||
password=True,
|
password=True,
|
||||||
text=self.default_config["Authentication"],
|
text=self.s.authentication,
|
||||||
)
|
)
|
||||||
auth_layout.add_widget(auth_label)
|
auth_layout.add_widget(auth_label)
|
||||||
auth_layout.add_widget(self.auth_input)
|
auth_layout.add_widget(self.auth_input)
|
||||||
|
|
||||||
|
automatic_generation_label = Label(text="Automatic generation (seconds): ")
|
||||||
|
self.automatic_generation_input = TextInput(
|
||||||
|
multiline=False,
|
||||||
|
size_hint_x=0.7,
|
||||||
|
text=str(self.s.automatic_generation_timer),
|
||||||
|
)
|
||||||
|
automatic_generation_layout = BoxLayout(
|
||||||
|
orientation="horizontal",
|
||||||
|
size_hint_y=None,
|
||||||
|
height=dp(40),
|
||||||
|
)
|
||||||
|
automatic_generation_layout.add_widget(automatic_generation_label)
|
||||||
|
automatic_generation_layout.add_widget(self.automatic_generation_input)
|
||||||
|
|
||||||
# Save button
|
# Save button
|
||||||
save_button = Button(
|
save_button = Button(
|
||||||
text="Save",
|
text="Save",
|
||||||
|
|
@ -112,21 +120,23 @@ class ConfigWindow(BoxLayout):
|
||||||
self.add_widget(channel_layout)
|
self.add_widget(channel_layout)
|
||||||
self.add_widget(nickname_layout)
|
self.add_widget(nickname_layout)
|
||||||
self.add_widget(auth_layout)
|
self.add_widget(auth_layout)
|
||||||
|
self.add_widget(automatic_generation_layout)
|
||||||
self.add_widget(save_button)
|
self.add_widget(save_button)
|
||||||
|
|
||||||
def save_config(self, instance):
|
def save_config(self, instance):
|
||||||
# Get values from inputs
|
|
||||||
self.default_config["Channel"] = self.channel_input.text.strip()
|
|
||||||
self.default_config["Nickname"] = self.nickname_input.text.strip()
|
|
||||||
self.default_config["Authentication"] = self.auth_input.text.strip()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Create directory if it doesn't exist
|
self.s.channel = self.channel_input.text.strip()
|
||||||
self.config_path.parent.mkdir(parents=True, exist_ok=True)
|
self.s.nickname = self.nickname_input.text.strip()
|
||||||
|
self.s.authentication = self.auth_input.text.strip()
|
||||||
# Save configuration
|
self.s.automatic_generation_timer = int(
|
||||||
with self.config_path.open("w") as f:
|
self.automatic_generation_input.text
|
||||||
json.dump(self.default_config, f, indent=4)
|
)
|
||||||
|
if 0 < self.s.automatic_generation_timer < 29: # noqa: PLR2004
|
||||||
|
raise ValueError(
|
||||||
|
"Value for 'Automatic generation' must be at least 30 seconds, " # noqa: EM101
|
||||||
|
"or a negative number for no automatic generations."
|
||||||
|
)
|
||||||
|
self.s.write(self.config_path)
|
||||||
|
|
||||||
# Show success message
|
# Show success message
|
||||||
success_popup = Popup(
|
success_popup = Popup(
|
||||||
|
|
@ -140,7 +150,7 @@ class ConfigWindow(BoxLayout):
|
||||||
Clock.schedule_once(success_popup.dismiss, 1)
|
Clock.schedule_once(success_popup.dismiss, 1)
|
||||||
|
|
||||||
except Exception as e: # noqa: BLE001
|
except Exception as e: # noqa: BLE001
|
||||||
# Show error message if saving fails
|
self.show_error_message(f"Failed to save configuration:\n{e!s}")
|
||||||
error_popup = Popup(
|
error_popup = Popup(
|
||||||
title="Error",
|
title="Error",
|
||||||
content=Label(text=f"Failed to save configuration:\n{e!s}"),
|
content=Label(text=f"Failed to save configuration:\n{e!s}"),
|
||||||
|
|
@ -148,3 +158,4 @@ class ConfigWindow(BoxLayout):
|
||||||
size=(dp(400), dp(150)),
|
size=(dp(400), dp(150)),
|
||||||
)
|
)
|
||||||
error_popup.open()
|
error_popup.open()
|
||||||
|
logger.exception("Failed to save configuration")
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,8 @@ class MarkovChain:
|
||||||
if self.s.help_message_timer > 0:
|
if self.s.help_message_timer > 0:
|
||||||
if self.s.help_message_timer < 300: # noqa: PLR2004
|
if self.s.help_message_timer < 300: # noqa: PLR2004
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
'Value for "HelpMessageTimer" in must be at least 300 seconds, or a negative number for no help messages.', # noqa: EM101
|
'Value for "HelpMessageTimer" in must be at least 300 seconds, ' # noqa: EM101
|
||||||
|
"or a negative number for no help messages.",
|
||||||
)
|
)
|
||||||
t = LoopingTimer(self.s.help_message_timer, self._command_help)
|
t = LoopingTimer(self.s.help_message_timer, self._command_help)
|
||||||
t.start()
|
t.start()
|
||||||
|
|
@ -44,6 +45,9 @@ class MarkovChain:
|
||||||
'Value for "Automatic_generation_message" must be at least 30 seconds, or a negative number for no ' # noqa: EM101
|
'Value for "Automatic_generation_message" must be at least 30 seconds, or a negative number for no ' # noqa: EM101
|
||||||
"automatic generations.",
|
"automatic generations.",
|
||||||
)
|
)
|
||||||
|
logger.info(
|
||||||
|
f"Automatic generation enabled, will send messages every {self.s.automatic_generation_timer} seconds"
|
||||||
|
)
|
||||||
t = LoopingTimer(
|
t = LoopingTimer(
|
||||||
self.s.automatic_generation_timer,
|
self.s.automatic_generation_timer,
|
||||||
self._command_automatic_generation,
|
self._command_automatic_generation,
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,15 @@ class BotApp(App):
|
||||||
self.config_path = (
|
self.config_path = (
|
||||||
platformdirs.user_config_path("markovbot_gui") / "settings.json"
|
platformdirs.user_config_path("markovbot_gui") / "settings.json"
|
||||||
)
|
)
|
||||||
|
self.data_path = platformdirs.user_data_path("markovbot_gui")
|
||||||
|
|
||||||
def run_bot(self, instance):
|
def run_bot(self, instance):
|
||||||
bot_runner = BotRunner(settings_path=self.config_path)
|
bot_runner = BotRunner(settings_path=self.config_path)
|
||||||
popup = Popup(
|
popup = Popup(
|
||||||
title="Bot Running",
|
title=f"Bot runner, database available at {self.data_path}",
|
||||||
content=bot_runner,
|
content=bot_runner,
|
||||||
size_hint=(None, None),
|
size_hint=(None, None),
|
||||||
size=(dp(600), dp(400)),
|
size=(dp(600), dp(600)),
|
||||||
auto_dismiss=False,
|
auto_dismiss=False,
|
||||||
)
|
)
|
||||||
popup.open()
|
popup.open()
|
||||||
|
|
@ -31,10 +32,10 @@ class BotApp(App):
|
||||||
def run_config(self, instance):
|
def run_config(self, instance):
|
||||||
config_window = ConfigWindow(config_path=self.config_path)
|
config_window = ConfigWindow(config_path=self.config_path)
|
||||||
popup = Popup(
|
popup = Popup(
|
||||||
title=f"Bot Configuration, available at {self.config_path}",
|
title=f"Bot configuration, available at {self.config_path}",
|
||||||
content=config_window,
|
content=config_window,
|
||||||
size_hint=(None, None),
|
size_hint=(None, None),
|
||||||
size=(dp(400), dp(400)),
|
size=(dp(600), dp(400)),
|
||||||
auto_dismiss=False,
|
auto_dismiss=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
6
uv.lock
generated
6
uv.lock
generated
|
|
@ -246,7 +246,7 @@ wheels = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "markovbot-gui"
|
name = "markovbot-gui"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
source = { virtual = "." }
|
source = { virtual = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "kivy", extra = ["base"] },
|
{ name = "kivy", extra = ["base"] },
|
||||||
|
|
@ -260,7 +260,7 @@ dependencies = [
|
||||||
{ name = "twitchwebsocket" },
|
{ name = "twitchwebsocket" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependency-groups]
|
[package.dev-dependencies]
|
||||||
dev = [
|
dev = [
|
||||||
{ name = "mypy" },
|
{ name = "mypy" },
|
||||||
{ name = "pyright" },
|
{ name = "pyright" },
|
||||||
|
|
@ -280,7 +280,7 @@ requires-dist = [
|
||||||
{ name = "twitchwebsocket", specifier = ">=1.2.1" },
|
{ name = "twitchwebsocket", specifier = ">=1.2.1" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.metadata.dependency-groups]
|
[package.metadata.requires-dev]
|
||||||
dev = [
|
dev = [
|
||||||
{ name = "mypy", specifier = ">=1.13.0" },
|
{ name = "mypy", specifier = ">=1.13.0" },
|
||||||
{ name = "pyright", specifier = ">=1.1.387" },
|
{ name = "pyright", specifier = ">=1.1.387" },
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue