diff --git a/__pycache__/chatlog.cpython-36.pyc b/__pycache__/chatlog.cpython-36.pyc index 123c799..a98a424 100644 Binary files a/__pycache__/chatlog.cpython-36.pyc and b/__pycache__/chatlog.cpython-36.pyc differ diff --git a/__pycache__/markov.cpython-36.pyc b/__pycache__/markov.cpython-36.pyc index 9644ffb..cde2f1e 100644 Binary files a/__pycache__/markov.cpython-36.pyc and b/__pycache__/markov.cpython-36.pyc differ diff --git a/chatlog.py b/chatlog.py index 7da5994..3814b00 100644 --- a/chatlog.py +++ b/chatlog.py @@ -9,7 +9,7 @@ class Chatlog(object): self.title = title if freq is None: if "group" in chattype: - freq = 15 + freq = 10 #elif chattype is "private": else: freq = 2 @@ -47,6 +47,7 @@ class Chatlog(object): lines.append(self.title) lines.append(str(self.freq)) lines.append("dict:") + lines.append(str(self.count)) txt = '\n'.join(lines) return txt + '\n' + self.gen.to_json() @@ -54,8 +55,11 @@ class Chatlog(object): lines = text.splitlines() if(lines[4] == "dict:"): new_log = Chatlog(lines[0], lines[1], lines[2], None, int(lines[3])) - cache = '\n'.join(lines[5:]) + new_log.count = int(lines[5]) + cache = '\n'.join(lines[6:]) new_log.gen = Markov.from_json(cache) + if new_log.count < 0: + new_log.count = new_log.gen.new_count() return new_log else: return Chatlog(lines[0], lines[1], lines[2], lines[4:], int(lines[3])) diff --git a/markov.py b/markov.py index f8b42aa..faf0d48 100644 --- a/markov.py +++ b/markov.py @@ -7,15 +7,28 @@ HEAD = "\n!kvl" TAIL = "!kvl" def trim_and_split(text): - words = text.split(' ') - for i in range(len(words)): - words[i] = words[i].strip(' \t') + words = text.replace('\n', '\n ').split(' ') + i = 0 + while i < len(words): + w = words[i].strip(' \t') + if len(w) > 0: + words[i] = w + else: + del words[i] + i -= 1 + i += 1 return words def getkey(w1, w2): key = (w1.strip().casefold(), w2.strip().casefold()) return str(key) +def getwords(key): + words = key.strip('()').split(', ') + for i in range(len(words)): + words[i].strip('\'') + return words + def triples(wordlist): """ Generates triples from the given data string. So if our string were "What a lovely day", we'd generate (What, a, lovely) and then @@ -81,3 +94,11 @@ class Markov(object): self.cache[key].extend(d[key]) else: self.cache[key] = list(d[key]) + + def new_count(self): + count = 0 + for key in self.cache: + for word in self.cache[key]: + if word == "!kvl": + count += 1 + return count diff --git a/ocsalev.py b/ocsalev.py deleted file mode 100644 index 7d9e80b..0000000 --- a/ocsalev.py +++ /dev/null @@ -1,180 +0,0 @@ -#!/usr/bin/env python3 - -# FAILED ATTEMPT TO MAKE BOT THAT USES VELASCO MEMORY IN ALL GROUPS SIMULTANEOUSLY - -import sys, os -from telegram.ext import Updater, CommandHandler, MessageHandler, Filters -from telegram.error import * -from markov import * -from velasco import GUILLERMO_ID, LOG_DIR, LOG_EXT -import logging -import argparse - -# Enable logging -logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - level=logging.INFO) - -logger = logging.getLogger(__name__) - -generator = Markov() -chatfreqs = {} - -DEFAULT_FREQ = 10 - -def parse_file(text): - lines = text.splitlines() - if lines[1] != "private": - ident = lines[0] - freq = int(lines[3]) - chatfreqs[ident] = (freq, 0) - if lines[4] == "dict:": - cache = '\n'.join(lines[5:]) - gen = Markov.from_json(cache) - return gen - else: - return Markov(lines[4:]) - else: - return Markov() - -def load_gen(path): - open_file = open(path, 'r') - gen = parse_file(open_file.read()) - open_file.close() - return gen - -def wake(bot): - global generator - directory = os.fsencode(LOG_DIR) - - for file in os.listdir(directory): - filename = os.fsdecode(file) - if filename.endswith(LOG_EXT): - gen = load_gen(LOG_DIR + filename) - generator.fuse_with(gen) - -def start(bot, update): - update.message.reply_text('WHADDUP NERD') - -def help(bot, update): - update.message.reply_text("""I ANSWER TO - -/start - HELLO -/about - MY BIOGRAPHY -/help - THIS -/freq - HOW LONG I WAIT TO SPEAK -/speak - I SPEAK - """) - -def about(bot, update): - update.message.reply_text('I AM LIKE @velascobot BUT STRONGER. THE TRUE SELF') - -def echo(bot, update): - text = update.message.text.split(None, 2) - if len(text) > 1: - text = text[1] - update.message.reply_text(text) - -def error(bot, update, error): - logger.warn('Update "%s" caused error "%s"' % (update, error)) - -def read(bot, update): - global generator - if not "group" in update.message.chat.type: - update.message.reply_text("I ONLY TALK IN GROUPS") - return - generator.add_text(update.message.text + TAIL) - chat = update.message.chat - ident = str(chat.id) - if not ident in chatfreqs: - chatfreqs[ident] = (DEFAULT_FREQ, 0) - freq, count = chatfreqs[ident] - if count%freq == 0: - msg = generator.generate_markov_text() - try: - bot.sendMessage(ident, msg) - count = 0 - except TimedOut: - chatfreqs[ident] = (freq + CHAT_INC, count) - print("Increased freq for chat " + chat.title + " [" + ident + "]") - chatfreqs[ident] = (freq, count+1) - -def speak(bot, update): - global generator - if not "group" in update.message.chat.type: - update.message.reply_text("I ONLY TALK IN GROUPS") - return - chat = update.message.chat - ident = str(chat.id) - if not ident in chatfreqs: - chatfreqs[ident] = (DEFAULT_FREQ, 0) - msg = generator.generate_markov_text() - update.message.reply_text(msg) - -def get_chatlogs(bot, update): - if str(update.message.chat.id) == GUILLERMO_ID: - bot.sendMessage(GUILLERMO_ID, "HECK YOU") - -def set_freq(bot, update): - ident = str(update.message.chat.id) - if not ident in chatfreqs: - chatfreqs[ident] = (DEFAULT_FREQ, 0) - freq, count = chatfreqs[ident] - if not len(update.message.text.split()) > 1: - reply = "I WAIT FOR " + str(freq) + " MESSAGES" - else: - try: - value = update.message.text.split()[1] - value = int(value) - chatfreqs[ident] = (value, count) - reply = "I NOW WAIT FOR " + str(value) + " MESSAGES" - if value > freq: - reply += "\nYOU WILL NOT SILENCE ME" - except: - reply = "WHAT THE HECK. IMMA STILL WAIT FOR " + str(freq) + " MESSAGES" - update.message.reply_text(reply) - -def stop(bot, update): - chat = update.message.chat - ident = str(chat.id) - del chatfreqs[ident] - -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("freq", set_freq)) - dp.add_handler(CommandHandler("list", get_chatlogs)) - dp.add_handler(CommandHandler("stop", stop)) - dp.add_handler(CommandHandler("speak", speak)) - - # on noncommand i.e message - echo the message on Telegram - # dp.add_handler(MessageHandler(Filters.text, echo)) - dp.add_handler(MessageHandler(Filters.text, read)) - - # log 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() diff --git a/velasco.py b/velasco.py index 7a935ac..7644b0e 100755 --- a/velasco.py +++ b/velasco.py @@ -6,6 +6,7 @@ from telegram.error import * from chatlog import * import logging import argparse +import random # Enable logging logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', @@ -14,13 +15,14 @@ logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s logger = logging.getLogger(__name__) chatlogs = {} -disabled = {} -GUILLERMO_ID = "8379173" +ADMIN_ID = 0 CHAT_INC = 5 CHAT_SAVE = 15 LOG_DIR = "chatlogs/" LOG_EXT = ".txt" +REPL_CHANCE = 10/100 +REPT_CHANCE = 5/100 def wake(bot): directory = os.fsencode(LOG_DIR) @@ -62,6 +64,7 @@ def help(bot, update): /start - I say hi. /about - What I'm about. +/explain - I explain how I work. /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. (Maximum of 100000) @@ -69,7 +72,10 @@ def help(bot, update): """) 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') + 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\n\nYou can send /explain if you want further explanation') + +def explain(bot, update): + update.message.reply_text('I decompose every message I read in groups of 3 consecutive words, so for each consecutive pair I save the word that can follow them. I then use this to make my own messages. At first I will only repeat your messages because for each 2 words I will have very few possible following words.\n\nI also separate my vocabulary by chats, so anything I learn in one chat I will only say in that chat. For privacy, you know. Also, I save my vocabulary in the form of a json dictionary, so no logs are kept.\n\nMy default frequency in private chats is one message of mine from each 2 messages received, and in group chats it\'s 10 messages I read for each message I send.') def echo(bot, update): text = update.message.text.split(None, 2) @@ -102,11 +108,23 @@ def read(bot, update): else: chatlog = chatlogs[ident] chatlog.add_msg(update.message.text) - if chatlog.get_count()%chatlog.freq == 0: + replied = update.message.reply_to_message + if (replied is not None) and (replied.from_user.name == "@velascobot") and (random.random() <= 0.5): msg = chatlog.speak() - # TO DO: aƱadir % de que haga reply en vez de send - try: + update.message.reply_text(msg) + if random.random() <= REPT_CHANCE: + msg = chatlog.speak() bot.sendMessage(chatlog.id, msg) + elif chatlog.get_count()%chatlog.freq == 0: + msg = chatlog.speak() + try: + if random.random() <= REPL_CHANCE: + update.message.reply_text(msg) + else: + bot.sendMessage(chatlog.id, msg) + if random.random() <= REPT_CHANCE: + msg = chatlog.speak() + bot.sendMessage(chatlog.id, msg) except TimedOut: chatlog.set_freq(chatlog.freq + CHAT_INC) print("Increased freq for chat " + chatlog.title + " [" + chatlog.id + "]") @@ -135,11 +153,16 @@ def speak(bot, update): chatlogs[chatlog.id] = chatlog def get_chatlogs(bot, update): - if str(update.message.chat.id) == GUILLERMO_ID: - m = "I have these chatlogs:" - for c in chatlogs: - m += "\n" + chatlogs[c].id + " " + chatlogs[c].title - bot.sendMessage(GUILLERMO_ID, m) + m = "I have these chatlogs:" + for c in chatlogs: + m += "\n" + chatlogs[c].id + " " + chatlogs[c].title + update.message.reply_text(m) + +def get_id(bot, update): + update.message.reply_text("This chat's id is: " + str(update.message.chat.id)) + +def get_name(bot, update): + update.message.reply_text("Your name is: " + update.message.from_user.name) def get_count(bot, update): ident = str(update.message.chat.id) @@ -172,19 +195,22 @@ def set_freq(bot, update): update.message.reply_text(reply) def stop(bot, update): + global ADMIN_ID chatlog = chatlogs[update.message.chat.id] del chatlogs[chatlog.id] os.remove(LOG_DIR + chatlog.id + LOG_EXT) print("I got blocked. Removed user " + chatlog.id) def main(): - parser = argparse.ArgumentParser(description='A Telegram markovbot.') + parser = argparse.ArgumentParser(description='A Telegram markov bot.') parser.add_argument('token', metavar='TOKEN', help='The Bot Token to work with the Telegram Bot API') + parser.add_argument('admin_id', metavar='ADMIN_ID', type=int, help='The ID of the Telegram user that manages this bot') args = parser.parse_args() # Create the EventHandler and pass it your bot's token. updater = Updater(args.token) + ADMIN_ID = args.admin_id # Get the dispatcher to register handlers dp = updater.dispatcher @@ -195,7 +221,9 @@ def main(): 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("list", get_chatlogs, Filters.chat(args.admin_id))) + dp.add_handler(CommandHandler("user", get_name, Filters.chat(args.admin_id))) + dp.add_handler(CommandHandler("id", get_id)) dp.add_handler(CommandHandler("stop", stop)) dp.add_handler(CommandHandler("speak", speak))