From f8e40228a75f0d44b153d33c74795c27ceb2e5d6 Mon Sep 17 00:00:00 2001 From: vylion Date: Fri, 22 Sep 2017 17:30:50 +0200 Subject: [PATCH] Velasco 1.5 - Modularized my own ID. Now everyone cas use it's own version of Velasco more easily - Added 50% random replies to replies of Velasco's messages - Rewritten some functions to better use resources in the libraries --- __pycache__/chatlog.cpython-36.pyc | Bin 2267 -> 2353 bytes __pycache__/markov.cpython-36.pyc | Bin 2702 -> 3200 bytes chatlog.py | 8 +- markov.py | 27 ++++- ocsalev.py | 180 ----------------------------- velasco.py | 54 ++++++--- 6 files changed, 71 insertions(+), 198 deletions(-) delete mode 100644 ocsalev.py diff --git a/__pycache__/chatlog.cpython-36.pyc b/__pycache__/chatlog.cpython-36.pyc index 123c799b9848a933864a40cd9da52ebb800c0c38..a98a4240327b680de587d7b7a40587adaa694072 100644 GIT binary patch delta 412 zcmXAkzfJ-{5XN_QxqllEfoOmN2@w;ok-})9p;1FgV=SP6f`fzw53?LGA%_+h3k$1_ zk6`RH#P|j_#uqU71jJXca8`GdU%vh3o7v1)dY*B1U6((6zBS(G&Itg2se{R&sm>A~ z&{HL&dKiI#FcA@9#t;J#p9(8NHKP&rX_jEc7EVmEN>sY) z(Ws?U1P|D-f;R;mQtHR>a!+XD01}fKMBqan#}BByQdP5j6jHRTJc%KqZRXn|fp5nr zH&lBw78=5g*k9F(s9-)D5IIF<2|FgbM_rqHz}2f+YAp@?N){1I6X7`vKE4?C!(l(@ zjwM5D!TLccT^%cFBoR%gCr9UPF&+hSRcD-_d)e-cCPC;WWJbp}bxakl?c6@9@fzZP t&oU$-gWGb|u-#SnX#6s zhAD+foS}vxi#>~@nL(T(m_d`-uZlG#Gr7d-79*D?=j55Jij()VI`i`}00AQhBM%S? zFmg>6X491D0tx~3GBh*PGS)DrFiJ9{Fl93pMNJN2Q;|zy&te7&a-=Y{GD$K3En_ZW z$zrWxZf2}uif5a=i_MggbMgl^Mb9DypfN95frKXeEw18%oXnD(%)Hd%B4(h_E#}O; zk|HG_s|e(RTbyY{`ML2~#rb(f{2(1HMM5As6_DKIe0B{XQy{At;aC+$p~>sndsz*D k!uFFLIpRd+KJ^e$C+q0N+YRXaE2J diff --git a/__pycache__/markov.cpython-36.pyc b/__pycache__/markov.cpython-36.pyc index 9644ffb8483d5503f2d415d816d76f27de3a73c4..cde2f1ec7ce30409fdb505b10629cf9b9e738a5c 100644 GIT binary patch delta 1641 zcmZux&2QX96rUM;y|%O7gl&>0C8SG2)taUhhy+ChlqfA!5eXm;Eh~Z9>`c=AvNvO= z8&-}MX>$W1Rp!Q-190TnD}MmzxgsHPLE_pI?~S8vh+=ErJo~+QpT9TX&wMk#yy|&w z`q%HD(+NWUBxfEI_;pzEM^Bbl7rDzPPDrizA>k$Noe=H`dt}rcPCp}l`AKJCi24Ss zO+2#)Bqc4vDQ6?rqTCqKW6I5AcC?kUgr#&u+eChq(v;1Umca`kH{d_$akFj8`>BDl zH4>I_e~+Y$TX)DY!~Jd859S__6rC4$6m2mx17ji`^q$&C$vIMT86hoU1m`mb~%~t z(M@V+ztE+j2Rc%dGH}Y;7fD-uJqvt{7vN6=*7(6%tiy^w0U}6^a#CY_nj73ap*4U7&wex(ug>r?pM)Pa zpW-h73>{wKmtc1_{ARO1jPGtcU_m*1GU^7cI0}{7X@(+i&Y5(BpcyukAh?x%YkvBA z70(p-VYe5{Mc{oZmtZ@8s+dID=37~*aBuk~t*9&nQMi9jS1yC}oh&Il+`!zR{*$mN z^Zvb!yUOPEq`q5^1^m{2Fy_2B|3{L%3WBxFvz~s8C6hi93{YA1UQdKvqsq5(D=(t7 zg5(mA8tbp-O+RPzRS>Rcmy7?b=*V1U0Zw?-RaWCs)NBatAa{kB)xDNCvp4MdEeuwf zadRNf_;L0{7-;NVh=OSl3t3M@(5=gM^fwTmH@ zfDpJyN-$YAtijZ_uE=X+HJ|N#0N7grJ%1wm)wwpj2CTe}1OcV-AhCgR6$#!P@?9j) zdpriYM1Z2HcnXM3UB@=yHEqxJY+FlxSKh+YRU{f*w~<4rYGldnIb;!g%8GVdqLJux d7r9gRS~uc{9q~TG>eQ#rOqh7v1Fx1{`VY;cJ-Yw^ delta 1100 zcmZuwNpI6Y6rQmi$99q~X`416AZ@x}Kok_IrwWQ%7J*uXI6xyID|Ck7G#g`gA*3o& zdPGHN_ytHkaN)v{3lhJ9%Un6NhyDOgyysLDs@j_8H*fvsedD*;-JyITm2wV#{#YKh z3He3-c?{6!U(!Qla)qJ|9vv3e zn1>b2fM}BnVYEZH=;mZdL#+*Zhc1w3nJv)UT9#CFrgbRlv*gvt6Vk>e`qFQjn`vn| z+ci`yXjc7D#YCxI=1Q;fI+#M?H(gyBA>RboMnkYbQU5a$j$EdTJr?vP)S+pbp&}{2 z(|Kx2LmQiLz%C+@08N=?9=&X@^D053u8gW*=Uwo}JuT1k>wf5YIk^{mbnPtW#MoM`8Hg 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))