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
This commit is contained in:
vylion 2017-09-22 17:30:50 +02:00
parent 6682510176
commit f8e40228a7
6 changed files with 71 additions and 198 deletions

Binary file not shown.

Binary file not shown.

View file

@ -9,7 +9,7 @@ class Chatlog(object):
self.title = title self.title = title
if freq is None: if freq is None:
if "group" in chattype: if "group" in chattype:
freq = 15 freq = 10
#elif chattype is "private": #elif chattype is "private":
else: else:
freq = 2 freq = 2
@ -47,6 +47,7 @@ class Chatlog(object):
lines.append(self.title) lines.append(self.title)
lines.append(str(self.freq)) lines.append(str(self.freq))
lines.append("dict:") lines.append("dict:")
lines.append(str(self.count))
txt = '\n'.join(lines) txt = '\n'.join(lines)
return txt + '\n' + self.gen.to_json() return txt + '\n' + self.gen.to_json()
@ -54,8 +55,11 @@ class Chatlog(object):
lines = text.splitlines() lines = text.splitlines()
if(lines[4] == "dict:"): if(lines[4] == "dict:"):
new_log = Chatlog(lines[0], lines[1], lines[2], None, int(lines[3])) 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) new_log.gen = Markov.from_json(cache)
if new_log.count < 0:
new_log.count = new_log.gen.new_count()
return new_log return new_log
else: else:
return Chatlog(lines[0], lines[1], lines[2], lines[4:], int(lines[3])) return Chatlog(lines[0], lines[1], lines[2], lines[4:], int(lines[3]))

View file

@ -7,15 +7,28 @@ HEAD = "\n!kvl"
TAIL = "!kvl" TAIL = "!kvl"
def trim_and_split(text): def trim_and_split(text):
words = text.split(' ') words = text.replace('\n', '\n ').split(' ')
for i in range(len(words)): i = 0
words[i] = words[i].strip(' \t') 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 return words
def getkey(w1, w2): def getkey(w1, w2):
key = (w1.strip().casefold(), w2.strip().casefold()) key = (w1.strip().casefold(), w2.strip().casefold())
return str(key) return str(key)
def getwords(key):
words = key.strip('()').split(', ')
for i in range(len(words)):
words[i].strip('\'')
return words
def triples(wordlist): def triples(wordlist):
""" Generates triples from the given data string. So if our string were """ Generates triples from the given data string. So if our string were
"What a lovely day", we'd generate (What, a, lovely) and then "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]) self.cache[key].extend(d[key])
else: else:
self.cache[key] = list(d[key]) 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

View file

@ -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()

View file

@ -6,6 +6,7 @@ from telegram.error import *
from chatlog import * from chatlog import *
import logging import logging
import argparse import argparse
import random
# Enable logging # Enable logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', 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__) logger = logging.getLogger(__name__)
chatlogs = {} chatlogs = {}
disabled = {}
GUILLERMO_ID = "8379173" ADMIN_ID = 0
CHAT_INC = 5 CHAT_INC = 5
CHAT_SAVE = 15 CHAT_SAVE = 15
LOG_DIR = "chatlogs/" LOG_DIR = "chatlogs/"
LOG_EXT = ".txt" LOG_EXT = ".txt"
REPL_CHANCE = 10/100
REPT_CHANCE = 5/100
def wake(bot): def wake(bot):
directory = os.fsencode(LOG_DIR) directory = os.fsencode(LOG_DIR)
@ -62,6 +64,7 @@ def help(bot, update):
/start - I say hi. /start - I say hi.
/about - What I'm about. /about - What I'm about.
/explain - I explain how I work.
/help - I send this message. /help - I send this message.
/count - I tell you how many messages from this chat I remember. /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) /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): 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): def echo(bot, update):
text = update.message.text.split(None, 2) text = update.message.text.split(None, 2)
@ -102,10 +108,22 @@ def read(bot, update):
else: else:
chatlog = chatlogs[ident] chatlog = chatlogs[ident]
chatlog.add_msg(update.message.text) 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()
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() msg = chatlog.speak()
# TO DO: añadir % de que haga reply en vez de send
try: 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) bot.sendMessage(chatlog.id, msg)
except TimedOut: except TimedOut:
chatlog.set_freq(chatlog.freq + CHAT_INC) chatlog.set_freq(chatlog.freq + CHAT_INC)
@ -135,11 +153,16 @@ def speak(bot, update):
chatlogs[chatlog.id] = chatlog chatlogs[chatlog.id] = chatlog
def get_chatlogs(bot, update): def get_chatlogs(bot, update):
if str(update.message.chat.id) == GUILLERMO_ID:
m = "I have these chatlogs:" m = "I have these chatlogs:"
for c in chatlogs: for c in chatlogs:
m += "\n" + chatlogs[c].id + " " + chatlogs[c].title m += "\n" + chatlogs[c].id + " " + chatlogs[c].title
bot.sendMessage(GUILLERMO_ID, m) 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): def get_count(bot, update):
ident = str(update.message.chat.id) ident = str(update.message.chat.id)
@ -172,6 +195,7 @@ def set_freq(bot, update):
update.message.reply_text(reply) update.message.reply_text(reply)
def stop(bot, update): def stop(bot, update):
global ADMIN_ID
chatlog = chatlogs[update.message.chat.id] chatlog = chatlogs[update.message.chat.id]
del chatlogs[chatlog.id] del chatlogs[chatlog.id]
os.remove(LOG_DIR + chatlog.id + LOG_EXT) os.remove(LOG_DIR + chatlog.id + LOG_EXT)
@ -180,11 +204,13 @@ def stop(bot, update):
def main(): def main():
parser = argparse.ArgumentParser(description='A Telegram markov bot.') 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('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() args = parser.parse_args()
# Create the EventHandler and pass it your bot's token. # Create the EventHandler and pass it your bot's token.
updater = Updater(args.token) updater = Updater(args.token)
ADMIN_ID = args.admin_id
# Get the dispatcher to register handlers # Get the dispatcher to register handlers
dp = updater.dispatcher dp = updater.dispatcher
@ -195,7 +221,9 @@ def main():
dp.add_handler(CommandHandler("help", help)) dp.add_handler(CommandHandler("help", help))
dp.add_handler(CommandHandler("count", get_count)) dp.add_handler(CommandHandler("count", get_count))
dp.add_handler(CommandHandler("freq", set_freq)) 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("stop", stop))
dp.add_handler(CommandHandler("speak", speak)) dp.add_handler(CommandHandler("speak", speak))