From 360705a04c3ff34bf767cabc6640ff85ab3f8412 Mon Sep 17 00:00:00 2001 From: Zac Herd Date: Sun, 3 Apr 2016 16:03:40 +0100 Subject: [PATCH] Added .markov command that generates markov chain sentences based on a user's chat history, v0.10.0 --- bot.py | 20 +++++++++++++++++++- markov.py | 42 ++++++++++++++++++++++++++++++++++++++++++ markovs/.gitignore | 2 ++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 markov.py create mode 100644 markovs/.gitignore diff --git a/bot.py b/bot.py index ef05d3b..5d99baf 100644 --- a/bot.py +++ b/bot.py @@ -12,6 +12,7 @@ import os import time import datetime import json +import markov # file in this directory called "secret.py" should contain these variables from secret import email,pwd @@ -23,7 +24,7 @@ from secret import email,pwd name = "Maki" # bot version -version = "v0.9.4" +version = "v0.10.0" # text shown by .help command helptext = """I am a bot written in Python by MrDetonia @@ -40,6 +41,7 @@ My commands are: .seen - prints when user was last seen .tell - send message to user when they are next active .say - say something +.markov - generate sentence using markov chains over a user's chat history ```""" # IDs of admin users @@ -145,6 +147,8 @@ def on_message(message): # print messages to terminal for info print(message.author.name + ': ' + message.content) + + # ensure we store this user's ID if message.author.name not in users: users[message.author.name] = message.author.id @@ -252,12 +256,26 @@ def on_message(message): # echo message yield from client.send_message(message.channel, message.content[5:]) + elif message.content.startswith('.markov'): + # generate a markov chain sentence based on the user's chat history + tmp = message.content[8:].split(' ',1) + if os.path.isfile('./markovs/' + users[tmp[0]]): + mc = markov.Markov(open('./markovs/' + users[tmp[0]])) + yield from client.send_message(message.channel, mc.generate_text()) + else: + yield from client.send_message(message.channel, 'I haven\'t seen that user speak yet!') + + # Stuff that happens when message is not a bot command: else: # log each message against users history[message.author.name] = (message.content, time.time()) with open('hist.json', 'w') as fp: json.dump(history, fp) + # log user messages for markov chains + with open('./markovs/' + message.author.id, 'a') as fp: + fp.write('\n' + message.content) + # Ben meme trackers if '/ck/' in message.content and message.author.name == "Ben.H": bentrack['ck'] += 1 diff --git a/markov.py b/markov.py new file mode 100644 index 0000000..554f2b5 --- /dev/null +++ b/markov.py @@ -0,0 +1,42 @@ +import random + +class Markov(object): + + def __init__(self, open_file): + self.cache = {} + self.open_file = open_file + self.words = self.file_to_words() + self.word_size = len(self.words) + self.database() + + def file_to_words(self): + self.open_file.seek(0) + data = self.open_file.read() + words = data.split() + return words + + def triples(self): + if len(self.words) < 3: + return + + for i in range(len(self.words) - 2): + yield (self.words[i], self.words[i+1], self.words[i+2]) + + def database(self): + for w1, w2, w3 in self.triples(): + key = (w1, w2) + if key in self.cache: + self.cache[key].append(w3) + else: + self.cache[key] = [w3] + + def generate_text(self, size=25): + seed = random.randint(0, self.word_size - 3) + seed_word, next_word = self.words[seed], self.words[seed+1] + w1, w2 = seed_word, next_word + gen_words = [] + for i in range(size): + gen_words.append(w1) + w1, w2 = w2, random.choice(self.cache[(w1, w2)]) + gen_words.append(w2) + return ' '.join(gen_words) diff --git a/markovs/.gitignore b/markovs/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/markovs/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore