diff --git a/pyproject.toml b/pyproject.toml index c16536e..207f2de 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "markovbot-gui" -version = "0.1.1" +version = "0.1.2" description = "Markov Chain Bot GUI" readme = "README.md" authors = [ diff --git a/src/markovbot_gui/libs/db.py b/src/markovbot_gui/libs/db.py index c5014f5..f547a81 100644 --- a/src/markovbot_gui/libs/db.py +++ b/src/markovbot_gui/libs/db.py @@ -101,6 +101,7 @@ class Database: self.update_v1(channel) self.update_v2() self.update_v3(channel) + self.update_v4() # Create database tables. for first_char in [*list(string.ascii_uppercase), "_"]: @@ -552,6 +553,28 @@ class Database: f'This updated "MarkovChain_{channel}.db" will be used to drive the Twitch bot.', ) + def update_v4(self): + """Update the db schema to allow storing quotes in a new `quotes` table. Besides the id, the table stores the + quote and the author. The quote is unique. + """ + # Get Database version. Throws OperationalError if the Version table does not exist, + # in which case we definitely want to upgrade. + try: + version = self.execute( + "SELECT version FROM Version ORDER BY version DESC LIMIT 1;", + fetch=True, + ) + except sqlite3.OperationalError: + version = [] + + if not version or version[0][0] < 4: # noqa: PLR2004 + logger.info("Updating db to the v4 version") + self.execute("""CREATE TABLE IF NOT EXISTS quotes ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + quote TEXT UNIQUE, + author TEXT + );""") + def add_execute_queue( self, sql: str, diff --git a/src/markovbot_gui/libs/markov_chain_bot.py b/src/markovbot_gui/libs/markov_chain_bot.py index ebc44cb..2e661b5 100644 --- a/src/markovbot_gui/libs/markov_chain_bot.py +++ b/src/markovbot_gui/libs/markov_chain_bot.py @@ -17,6 +17,8 @@ class Commands(StrEnum): GENERATE = "!g" BLACKLIST = "!blacklist" GENERATE_HELP = "!ghelp" + QUOTE = "!q" + QUOTE_ADD = "!qadd" class MarkovChain: @@ -160,6 +162,45 @@ class MarkovChain: "Attempted to output automatic generation message, but there is not enough learned information yet.", ) + def _command_quote(self): + """Retrieve a random quote from the `quotes` table and format it as + + > «» - + """ + data = self.db.execute( + "SELECT quote, author FROM quotes ORDER BY RANDOM() LIMIT 1;", fetch=True + ) + if data: + data = data[0] + quote, author = data[0], data[1] + self.ws.send_message(f"«{quote}» - {author}") + + def _command_add_quote(self, message: str): + """Add a quote to the quotes table. The message should follow the format: + + !qadd quote author + + The last word will be parsed as the author and anything in between !qadd and the author will be considered + as the quote itself + """ + # Split the message into quote and author + parts = message.split() + author = parts[-1] + quote = " ".join(parts[1:-1]) + + data = self.db.execute( + "SELECT 1 FROM quotes WHERE quote = ?", (quote,), fetch=True + ) + if data: + self.ws.send_message(f"Quote «{quote}» was already added.") + return + + self.db.execute( + "INSERT INTO quotes (quote, author) VALUES (?, ?)", + (quote, author), # type: ignore[arg-type] + ) + self.ws.send_message(f"Quote «{quote}» by {author} added.") + def store_sentence(self, message: str): logger.info(f"Processing {message} in order to store it") stripped_message = message.strip() @@ -206,7 +247,7 @@ class MarkovChain: # Add at the end of the sentence self.db.add_rule_queue([*key, self.end_tag]) - def message_handler(self, message: Message): # noqa: C901, PLR0912 + def message_handler(self, message: Message): # noqa: C901, PLR0911, PLR0912 try: if not message.user or message.user in self.s.denied_users: logger.debug(f"User {message.user} can't send messages") @@ -264,6 +305,28 @@ class MarkovChain: message=message.message, username=message.user, ) + + case Commands.QUOTE: + if not self._enabled: + logger.info("Bot not enabled, skipping") + return + if message.user not in self.s.denied_users: + logger.info( + f"User {message.user} allowed to generate, executing _command_quote()", + ) + self._command_quote() + + case Commands.QUOTE_ADD: + if self.is_mod(message.user, message.channel): + logger.info( + f"User {message.user} allowed to create quote, executing _command_quote()", + ) + self._command_add_quote(message.message) + return + self.ws.send_message( + f"@{message.user} you're not in the modlist, you can't add quotes" + ) + case _: logger.debug( f"Not a command: {msgs[0]}. Storing into db as a plain message", diff --git a/uv.lock b/uv.lock index f29669e..3f9f0ad 100644 --- a/uv.lock +++ b/uv.lock @@ -246,7 +246,7 @@ wheels = [ [[package]] name = "markovbot-gui" -version = "0.1.1" +version = "0.1.2" source = { virtual = "." } dependencies = [ { name = "kivy", extra = ["base"] },