mirror of
https://gitlab.com/vylion/velascobot.git
synced 2025-04-19 21:46:35 +02:00
Velasco 1.6
- Added ability to change Velasco's probability to answer replies to his messages, per chat - Rewritten save-to-file functions for slightly more readability, and rewritten load-from-file functions accordingly
This commit is contained in:
parent
14a92ef0f3
commit
7de67c0238
3 changed files with 81 additions and 18 deletions
49
chatlog.py
49
chatlog.py
|
@ -3,7 +3,7 @@
|
||||||
from markov import *
|
from markov import *
|
||||||
|
|
||||||
class Chatlog(object):
|
class Chatlog(object):
|
||||||
def __init__(self, ident, chattype, title, text=None, freq=None):
|
def __init__(self, ident, chattype, title, text=None, freq=None, answer=0.5):
|
||||||
self.id = str(ident)
|
self.id = str(ident)
|
||||||
self.type = chattype
|
self.type = chattype
|
||||||
self.title = title
|
self.title = title
|
||||||
|
@ -18,6 +18,7 @@ class Chatlog(object):
|
||||||
self.count = len(text)
|
self.count = len(text)
|
||||||
else:
|
else:
|
||||||
self.count = 0
|
self.count = 0
|
||||||
|
self.answer = answer
|
||||||
self.gen = Markov(text)
|
self.gen = Markov(text)
|
||||||
|
|
||||||
def set_title(self, title):
|
def set_title(self, title):
|
||||||
|
@ -31,6 +32,15 @@ class Chatlog(object):
|
||||||
self.freq = freq
|
self.freq = freq
|
||||||
return self.freq
|
return self.freq
|
||||||
|
|
||||||
|
def set_answer_freq(self, freq):
|
||||||
|
if freq > 1:
|
||||||
|
self.answer = 1
|
||||||
|
elif freq < 0:
|
||||||
|
self.answer = 0
|
||||||
|
else:
|
||||||
|
self.answer = freq
|
||||||
|
return self.answer
|
||||||
|
|
||||||
def add_msg(self, message):
|
def add_msg(self, message):
|
||||||
self.gen.add_text(message + " !kvl")
|
self.gen.add_text(message + " !kvl")
|
||||||
self.count += 1
|
self.count += 1
|
||||||
|
@ -41,19 +51,36 @@ class Chatlog(object):
|
||||||
def get_count(self):
|
def get_count(self):
|
||||||
return self.count
|
return self.count
|
||||||
|
|
||||||
|
def answering(self, rand):
|
||||||
|
if self.answer == 1:
|
||||||
|
return True
|
||||||
|
elif self.answer == 0:
|
||||||
|
return False
|
||||||
|
return rand <= self.answer
|
||||||
|
|
||||||
def to_txt(self):
|
def to_txt(self):
|
||||||
lines = [self.id]
|
lines = ["DICT=v2"]
|
||||||
lines.append(self.type)
|
lines.append("CHAT_ID=" + self.id)
|
||||||
lines.append(self.title)
|
lines.append("CHAT_TYPE=" + self.type)
|
||||||
lines.append(str(self.freq))
|
lines.append("CHAT_NAME=" + self.title)
|
||||||
lines.append("dict:")
|
lines.append("MESSAGE_FREQ=" + str(self.freq))
|
||||||
lines.append(str(self.count))
|
lines.append("ANSWER_FREQ=" + str(self.answer))
|
||||||
|
lines.append("WORD_COUNT=" + str(self.count))
|
||||||
|
lines.append("WORD_DICT=")
|
||||||
txt = '\n'.join(lines)
|
txt = '\n'.join(lines)
|
||||||
return txt + '\n' + self.gen.to_json()
|
return txt + '\n' + self.gen.to_json()
|
||||||
|
|
||||||
def from_txt(text):
|
def from_txt(text):
|
||||||
lines = text.splitlines()
|
lines = text.splitlines()
|
||||||
if(lines[4] == "dict:"):
|
if(parse_line(lines[0]) == "v2"):
|
||||||
|
new_log = Chatlog(parse_line(lines[1]), parse_line(lines[2]), parse_line(lines[3]), None, int(parse_line(lines[4])), float(parse_line(lines[5])))
|
||||||
|
new_log.count = int(parse_line(lines[6]))
|
||||||
|
cache = '\n'.join(lines[8:])
|
||||||
|
new_log.gen = Markov.from_json(cache)
|
||||||
|
if new_log.count < 0:
|
||||||
|
new_log.count = new_log.gen.new_count()
|
||||||
|
return new_log
|
||||||
|
elif(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]))
|
||||||
new_log.count = int(lines[5])
|
new_log.count = int(lines[5])
|
||||||
cache = '\n'.join(lines[6:])
|
cache = '\n'.join(lines[6:])
|
||||||
|
@ -64,6 +91,12 @@ class Chatlog(object):
|
||||||
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]))
|
||||||
|
|
||||||
|
def parse_line(line):
|
||||||
|
s = line.split('=')
|
||||||
|
if len(s) < 2:
|
||||||
|
return ""
|
||||||
|
return s[1]
|
||||||
|
|
||||||
def fuse_with(chatlog):
|
def fuse_with(chatlog):
|
||||||
self.count += chatlog.count
|
self.count += chatlog.count
|
||||||
self.gen.fuse_with(chatlog.gen)
|
self.gen.fuse_with(chatlog.gen)
|
||||||
|
|
|
@ -58,7 +58,8 @@ class Markov(object):
|
||||||
return Markov(string, True)
|
return Markov(string, True)
|
||||||
|
|
||||||
def add_text(self, text):
|
def add_text(self, text):
|
||||||
words = trim_and_split(HEAD + " " + text)
|
words = [HEAD]
|
||||||
|
words.extend(trim_and_split(text))
|
||||||
self.database(words)
|
self.database(words)
|
||||||
|
|
||||||
def database(self, wordlist):
|
def database(self, wordlist):
|
||||||
|
@ -81,7 +82,7 @@ class Markov(object):
|
||||||
for i in range(size):
|
for i in range(size):
|
||||||
gen_words.append(w1)
|
gen_words.append(w1)
|
||||||
if w2 == TAIL or not getkey(w1, w2) in self.cache:
|
if w2 == TAIL or not getkey(w1, w2) in self.cache:
|
||||||
print("Generated text")
|
# print("Generated text")
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
w1, w2 = w2, random.choice(self.cache[getkey(w1, w2)])
|
w1, w2 = w2, random.choice(self.cache[getkey(w1, w2)])
|
||||||
|
|
43
velasco.py
43
velasco.py
|
@ -9,7 +9,7 @@ import argparse
|
||||||
import random
|
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 - velascobot',
|
||||||
level=logging.INFO)
|
level=logging.INFO)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -55,7 +55,10 @@ def savechat(chatlog):
|
||||||
|
|
||||||
def loadchat(path):
|
def loadchat(path):
|
||||||
open_file = open(path, 'r')
|
open_file = open(path, 'r')
|
||||||
|
try:
|
||||||
chat = Chatlog.from_txt(open_file.read())
|
chat = Chatlog.from_txt(open_file.read())
|
||||||
|
except:
|
||||||
|
pass
|
||||||
open_file.close()
|
open_file.close()
|
||||||
return chat
|
return chat
|
||||||
|
|
||||||
|
@ -67,8 +70,9 @@ def help(bot, update):
|
||||||
/explain - I explain how I work.
|
/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 my messages. (Maximum of 100000)
|
||||||
/speak - Forces me to speak.
|
/speak - Forces me to speak.
|
||||||
|
/answer - Change the probability to answer to a reply. (Decimal between 0 and 1)
|
||||||
""")
|
""")
|
||||||
|
|
||||||
def about(bot, update):
|
def about(bot, update):
|
||||||
|
@ -78,7 +82,7 @@ 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.')
|
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, maxsplit=1)
|
||||||
if len(text) > 1:
|
if len(text) > 1:
|
||||||
text = text[1]
|
text = text[1]
|
||||||
chatlog.add_msg(text)
|
chatlog.add_msg(text)
|
||||||
|
@ -109,7 +113,8 @@ def read(bot, update):
|
||||||
chatlog = chatlogs[ident]
|
chatlog = chatlogs[ident]
|
||||||
chatlog.add_msg(update.message.text)
|
chatlog.add_msg(update.message.text)
|
||||||
replied = update.message.reply_to_message
|
replied = update.message.reply_to_message
|
||||||
if (replied is not None) and (replied.from_user.name == "@velascobot") and (random.random() <= 0.5):
|
if (replied is not None) and (replied.from_user.name == "@velascobot") and chatlog.answering(random.random()):
|
||||||
|
print("They're talking to me, I'm answering back")
|
||||||
msg = chatlog.speak()
|
msg = chatlog.speak()
|
||||||
update.message.reply_text(msg)
|
update.message.reply_text(msg)
|
||||||
if random.random() <= REPT_CHANCE:
|
if random.random() <= REPT_CHANCE:
|
||||||
|
@ -119,10 +124,13 @@ def read(bot, update):
|
||||||
msg = chatlog.speak()
|
msg = chatlog.speak()
|
||||||
try:
|
try:
|
||||||
if random.random() <= REPL_CHANCE:
|
if random.random() <= REPL_CHANCE:
|
||||||
|
print("I made a reply")
|
||||||
update.message.reply_text(msg)
|
update.message.reply_text(msg)
|
||||||
else:
|
else:
|
||||||
|
print("I sent a message")
|
||||||
bot.sendMessage(chatlog.id, msg)
|
bot.sendMessage(chatlog.id, msg)
|
||||||
if random.random() <= REPT_CHANCE:
|
if random.random() <= REPT_CHANCE:
|
||||||
|
print("And a followup")
|
||||||
msg = chatlog.speak()
|
msg = chatlog.speak()
|
||||||
bot.sendMessage(chatlog.id, msg)
|
bot.sendMessage(chatlog.id, msg)
|
||||||
except TimedOut:
|
except TimedOut:
|
||||||
|
@ -194,12 +202,32 @@ def set_freq(bot, update):
|
||||||
reply = "Format was confusing; frequency not changed from " + str(chatlogs[ident].freq)
|
reply = "Format was confusing; frequency not changed from " + str(chatlogs[ident].freq)
|
||||||
update.message.reply_text(reply)
|
update.message.reply_text(reply)
|
||||||
|
|
||||||
|
def set_answer_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 answer probability is " + str(chatlogs[ident].answer)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
value = update.message.text.split()[1]
|
||||||
|
value = float(value)
|
||||||
|
value = chatlogs[ident].set_answer_freq(value)
|
||||||
|
reply = "Probability of answering set to " + str(value)
|
||||||
|
savechat(chatlogs[ident])
|
||||||
|
except:
|
||||||
|
reply = "Format was confusing; answer probability not changed from " + str(chatlogs[ident].answer)
|
||||||
|
update.message.reply_text(reply)
|
||||||
|
|
||||||
def stop(bot, update):
|
def stop(bot, update):
|
||||||
global ADMIN_ID
|
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)
|
||||||
print("I got blocked. Removed user " + chatlog.id)
|
print("I got blocked by user " + chatlog.id)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description='A Telegram markov bot.')
|
parser = argparse.ArgumentParser(description='A Telegram markov bot.')
|
||||||
|
@ -226,6 +254,7 @@ def main():
|
||||||
dp.add_handler(CommandHandler("id", get_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))
|
||||||
|
dp.add_handler(CommandHandler("answer", set_answer_freq))
|
||||||
|
|
||||||
# on noncommand i.e message - echo the message on Telegram
|
# on noncommand i.e message - echo the message on Telegram
|
||||||
# dp.add_handler(MessageHandler(Filters.text, echo))
|
# dp.add_handler(MessageHandler(Filters.text, echo))
|
||||||
|
|
Loading…
Reference in a new issue