aboutsummaryrefslogtreecommitdiff
path: root/modules/markov.py
blob: 43e3fdb91795909711b83de92d1c8df07b789645 (about) (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import random
from src import ModuleManager, utils

class Module(ModuleManager.BaseModule):
    def _on_load(self):
        if not self.bot.database.has_table("markov"):
            self.bot.database.execute("""CREATE TABLE markov
                (channel_id INTEGER, first_word TEXT, second_word TEXT,
                third_word TEXT, frequency INT,
                FOREIGN KEY (channel_id) REFERENCES channels(channel_id),
                PRIMARY KEY (channel_id, first_word, second_word))""")

    @utils.hook("received.message.channel")
    def channel_message(self, event):
        words = event["message_split"]
        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("""SELECT frequency
                    FROM markov WHERE channel_id=? AND first_word=?
                    AND second_word=? AND third_word=?""",
                    [event["channel"].id]+insert)
                frequency = (frequency or [0])[0]+1

                self.bot.database.execute(
                    "INSERT OR REPLACE INTO markov VALUES (?, ?, ?, ?, ?)",
                    [event["channel"].id]+insert+[frequency])

            print(self.generate(event["channel"].id))

    def _choose(self, words):
        words, frequencies = list(zip(*words))
        return random.choices(words, weights=frequencies, k=1)[0]

    def generate(self, channel_id):
        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])
        if not first_words:
            return None
        first_word = self._choose(first_words)

        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])
        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:]
            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)

            third_word = self._choose(third_words)
            if third_word == None:
                break
            words.append(third_word)

        return " ".join(words)