bitbot-3.11-fork/modules/markov.py

83 lines
3.3 KiB
Python
Raw Normal View History

2019-09-20 15:56:00 +00:00
import random
from src import ModuleManager, utils
class Module(ModuleManager.BaseModule):
2019-09-20 16:15:21 +00:00
def on_load(self):
2019-09-20 15:57:17 +00:00
if not self.bot.database.has_table("markov"):
self.bot.database.execute("""CREATE TABLE markov
2019-09-20 15:56:00 +00:00
(channel_id INTEGER, first_word TEXT, second_word TEXT,
third_word TEXT, frequency INT,
FOREIGN KEY (channel_id) REFERENCES channels(channel_id),
2019-09-20 15:58:42 +00:00
PRIMARY KEY (channel_id, first_word, second_word))""")
2019-09-20 15:56:00 +00:00
@utils.hook("received.message.channel")
def channel_message(self, event):
2019-09-20 16:48:18 +00:00
words = [word.lower() for word in event["message_split"]]
2019-09-20 15:56:00 +00:00
words_n = len(words)
if words_n > 2 and event["channel"].get_setting("markov", False):
inserts = []
inserts.append([None, None, words[0]])
inserts.append([None, words[0], words[1]])
for i in range(words_n-2):
inserts.append(words[i:i+3])
inserts.append([words[-2], words[-1], None])
inserts.append([words[-1], None, None])
for insert in inserts:
frequency = self.bot.database.execute_fetchone("""SELECT
frequency FROM markov WHERE channel_id=? AND first_word=?
2019-09-20 15:56:00 +00:00
AND second_word=? AND third_word=?""",
[event["channel"].id]+insert)
frequency = (frequency or [0])[0]+1
2019-09-20 15:57:17 +00:00
self.bot.database.execute(
2019-09-20 15:56:00 +00:00
"INSERT OR REPLACE INTO markov VALUES (?, ?, ?, ?, ?)",
[event["channel"].id]+insert+[frequency])
def _choose(self, words):
words, frequencies = list(zip(*words))
return random.choices(words, weights=frequencies, k=1)[0]
@utils.hook("received.command.markov")
@utils.kwarg("channel_only", True)
def generate(self, event):
if not event["target"].get_setting("markov", False):
raise utils.EventError("Markov chains not enabled in this channel")
out = self._generate(event["target"].id)
if not out == None:
event["stdout"].write(out)
else:
event["stderr"].write("Failed to generate markov chain")
def _generate(self, channel_id):
2019-09-20 16:12:17 +00:00
first_words = self.bot.database.execute_fetchall("""SELECT third_word,
frequency FROM markov WHERE channel_id=? AND first_word IS NULL AND
second_word IS NULL AND third_word NOT NULL""", [channel_id])
2019-09-20 15:56:00 +00:00
if not first_words:
return None
first_word = self._choose(first_words)
2019-09-20 16:12:17 +00:00
second_words = self.bot.database.execute_fetchall("""SELECT third_word,
frequency FROM markov WHERE channel_id=? AND first_word IS NULL AND
second_word=? AND third_word NOT NULL""", [channel_id, first_word])
2019-09-20 15:56:00 +00:00
if not second_words:
return None
second_word = self._choose(second_words)
words = [first_word, second_word]
for i in range(30):
two_words = words[-2:]
2019-09-20 16:12:17 +00:00
third_words = self.bot.database.execute_fetchall("""SELECT
third_word, frequency FROM markov WHERE channel_id=? AND
first_word=? AND second_word=?""", [channel_id]+two_words)
2019-09-20 15:56:00 +00:00
third_word = self._choose(third_words)
if third_word == None:
break
words.append(third_word)
return " ".join(words)