commit cb33edc3cdce325d945ab6fbf250523b0aa66bf2 Author: vylion Date: Tue Sep 19 13:00:56 2017 +0200 Initial commit. Uploading Velasco v1.1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6ec0a37 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +chatlogs/* \ No newline at end of file diff --git a/__pycache__/chatlog.cpython-36.pyc b/__pycache__/chatlog.cpython-36.pyc new file mode 100644 index 0000000..2237ed8 Binary files /dev/null and b/__pycache__/chatlog.cpython-36.pyc differ diff --git a/__pycache__/markov.cpython-36.pyc b/__pycache__/markov.cpython-36.pyc new file mode 100644 index 0000000..69fd75e Binary files /dev/null and b/__pycache__/markov.cpython-36.pyc differ diff --git a/chatlog.py b/chatlog.py new file mode 100644 index 0000000..f57a380 --- /dev/null +++ b/chatlog.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 + +from markov import * + +class Chatlog(object): + def __init__(self, ident, chattype, title, msgs=None, freq=None): + if msgs is not None: + self.msgs = msgs + else: + self.msgs = [] + self.id = str(ident) + self.type = chattype + self.title = title + if freq is None: + if "group" in chattype: + freq = 20 + #elif chattype is "private": + else: + freq = 5 + self.freq = freq + + def add_msg(self, message): + msg = message.split() + msg.append("!kvl") + self.msgs.append(msg) + + def get_markov_gen(self): + msgs = [] + for m in self.msgs: + msgs.append(' '.join(m)) + text = ' '.join(msgs) + self.gen = Markov(text) + + def speak(self): + self.get_markov_gen() + return self.gen.generate_markov_text() + + def get_count(self): + return len(self.msgs) + + def set_freq(self, freq): + self.freq = freq + + def to_txt(self): + lines = [self.id] + lines.append(self.type) + lines.append(self.title) + lines.append(str(self.freq)) + for m in self.msgs: + lines.append(' '.join(m)) + return '\n'.join(lines) + + def from_txt(text): + lines = text.splitlines() + msgs = [] + for m in lines[4:]: + msgs.append(m.split()) + return Chatlog(lines[0], lines[1], lines[2], msgs, int(lines[3])) diff --git a/markov.py b/markov.py new file mode 100644 index 0000000..bc0725f --- /dev/null +++ b/markov.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 + +import random + +class Markov(object): + def __init__(self, text=None): + self.cache = {} + self.words = [] + if text is None: + text = "" + self.words = text.split() + self.word_size = len(self.words) + self.database() + + def triples(self): + """ Generates triples from the given data string. So if our string were + "What a lovely day", we'd generate (What, a, lovely) and then + (a, lovely, day). + """ + + 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_markov_text(self, size=50): + seed = random.randint(0, self.word_size-3) + seed_word, next_word = self.words[seed], self.words[seed+1] + while "!kvl" in seed_word: + 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) + if "!kvl" in w2 or not (w1, w2) in self.cache: + print("Generated text") + break + else: + w1, w2 = w2, random.choice(self.cache[(w1, w2)]) + return ' '.join(gen_words) diff --git a/velasco.py b/velasco.py new file mode 100755 index 0000000..73deaf7 --- /dev/null +++ b/velasco.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python3 + +import sys, os +from telegram.ext import Updater, CommandHandler, MessageHandler, Filters +from chatlog import * +import logging +import argparse + +# Enable logging +logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + level=logging.INFO) + +logger = logging.getLogger(__name__) + +chatlogs = {} +disabled = {} + +GUILLERMO_ID = 8379173 + +def wake(bot): + directory = os.fsencode("chatlogs/") + + for file in os.listdir(directory): + filename = os.fsdecode(file) + if filename.endswith(".txt"): + chat = loadchat("chatlogs/" + filename) + chatlogs[chat.id] = chat + print("loaded chat " + chat.id) + continue + else: + continue +""" + for c in chatlogs: + try: + bot.sendMessage(chatlogs[c].id, "Good morning. I just woke up") + except: + pass + #del chatlogs[c] +""" + +def start(bot, update): + update.message.reply_text('cowabunga') + +def savechat(chatlog): + open_file = open('chatlogs/' + chatlog.id + '.txt', 'w') + open_file.write(chatlog.to_txt()) + open_file.close() + +def loadchat(path): + open_file = open(path, 'r') + chat = Chatlog.from_txt(open_file.read()) + open_file.close() + return chat + +def help(bot, update): + update.message.reply_text("""I answer to the following commands: + +/start - I say hi. +/about - What I'm about. +/help - I send this message. +/count - I tell you how many messages from this chat I remember. +/freq - Change the frequency of both my messages and the times I save my learned vocabulary. + """) + +def about(bot, update): + update.message.reply_text('I am yet another Markov Bot experiment. I read everything you type to me and then spit back nonsensical messages that look like yours') + +def echo(bot, update): + update.message.reply_text(update.message.text) + +def error(bot, update, error): + logger.warn('Update "%s" caused error "%s"' % (update, error)) + +def get_chatname(chat): + if chat.title is not None: + return chat.title + elif chat.first_name is not None: + if chat.last_name is not None: + return chat.first_name + " " + chat.last_name + else: + return chat.first_name + else: + return "" + +def read(bot, update): + global chatlogs + ident = str(update.message.chat.id) + if not ident in chatlogs: + chat = update.message.chat + title = get_chatname(chat) + chatlog = Chatlog(chat.id, chat.type, title) + else: + chatlog = chatlogs[ident] + chatlog.add_msg(update.message.text) + if chatlog.get_count()%chatlog.freq == 0: + msg = chatlog.speak() + bot.sendMessage(chatlog.id, msg) + savechat(chatlog) + + chatlogs[chatlog.id] = chatlog + +def get_chatlogs(bot, update): + global GUILLERMO_ID + if update.message.chat.id is GUILLERMO_ID: + m = "I have these chatlogs:" + for c in chatlogs: + m += "\n" + chatlogs[c].id + " " + chatlogs[c].title + bot.sendMessage(GUILLERMO_ID, m) + +def get_count(bot, update): + ident = str(update.message.chat.id) + reply = "I remember " + if ident in chatlogs: + reply += str(chatlogs[ident].get_count()) + else: + reply += "no" + reply += " messages." + update.message.reply_text(reply) + +def set_freq(bot, update): + ident = str(update.message.chat.id) + if not ident in chatlogs: + chat = update.message.chat + title = get_chatname(chat) + chatlog = Chatlog(chat.id, chat.type, title) + chatlogs[chatlog.id] = chatlog + if not len(update.message.text.split()) > 1: + reply = "Current frequency is " + str(chatlogs[ident].freq) + else: + try: + value = update.message.text.split()[1] + value = int(value) + chatlogs[ident].set_freq(value) + reply = "Frequency of speaking set to " + str(value) + except: + reply = "Format was confusing; requency not changed from " + str(chatlogs[ident].freq) + update.message.reply_text(reply) + +def stop(bot, update): + chatlog = chatlogs[update.message.chat.id] + del chatlogs[chatlog.id] + os.remove("chatlogs/" + chatlog.id + ".txt") + print("I got blocked. Removed user " + chatlog.id) + +def main(): + parser = argparse.ArgumentParser(description='A Telegram markovbot.') + parser.add_argument('token', metavar='TOKEN', help='The Bot Token to work with the Telegram Bot API') + + args = parser.parse_args() + + # Create the EventHandler and pass it your bot's token. + updater = Updater(args.token) + + # Get the dispatcher to register handlers + dp = updater.dispatcher + + # on different commands - answer in Telegram + dp.add_handler(CommandHandler("start", start)) + dp.add_handler(CommandHandler("about", about)) + dp.add_handler(CommandHandler("help", help)) + dp.add_handler(CommandHandler("count", get_count)) + dp.add_handler(CommandHandler("freq", set_freq)) + dp.add_handler(CommandHandler("list", get_chatlogs)) + dp.add_handler(CommandHandler("stop", stop)) + + # on noncommand i.e message - echo the message on Telegram + # dp.add_handler(MessageHandler(Filters.text, echo)) + dp.add_handler(MessageHandler(Filters.text, read)) + + # chatlog all errors + dp.add_error_handler(error) + + wake(updater.bot) + + # Start the Bot + updater.start_polling() + + # Run the bot until you press Ctrl-C or the process receives SIGINT, + # SIGTERM or SIGABRT. This should be used most of the time, since + # start_polling() is non-blocking and will stop the bot gracefully. + updater.idle() + +if __name__ == '__main__': + main()