From fdcbbe96e08082b8329860e017a13e90fa8131bd Mon Sep 17 00:00:00 2001 From: yupix Date: Sun, 20 Feb 2022 11:15:27 +0900 Subject: [PATCH] feat: support Mi.py v3.9.9 --- rdbot.py | 60 ++++++++------------- roboduck.py | 149 ++++++++++++++++++++++++++++------------------------ 2 files changed, 102 insertions(+), 107 deletions(-) diff --git a/rdbot.py b/rdbot.py index 1b0ba37..1088e68 100644 --- a/rdbot.py +++ b/rdbot.py @@ -1,29 +1,21 @@ -from datetime import datetime -import os import asyncio -from random import * -import mi -import sys -import configparser import threading -from pathlib import Path -from mi import Note + from mi.ext import commands, tasks -from mi.note import Note -from mi.router import Router +from mi.framework import Note +from mi.framework.router import Router + from roboduck import * - - -#Load Misskey configuration +# Load Misskey configuration config = configparser.ConfigParser() -config.read((Path(__file__).parent).joinpath('bot.cfg')) -uri="wss://"+config.get("misskey","instance_write")+"/streaming" -token=config.get("misskey","token") +config.read(Path(__file__).parent.joinpath('bot.cfg')) +uri = config.get("misskey", "instance_write") +token = config.get("misskey", "token") class MyBot(commands.Bot): - text_model = None #Holds the markov object, so it won't be recreated everytime + text_model = None # Holds the markov object, so it won't be recreated everytime def __init__(self): super().__init__() @@ -35,36 +27,30 @@ class MyBot(commands.Bot): @tasks.loop(43200) async def loop_12h(self): - thread_update = threading.Thread(target=update) - thread_update.setDaemon(True) - thread_update.start() + thread_update = threading.Thread(target=update) + thread_update.setDaemon(True) + thread_update.start() async def on_ready(self, ws): - await Router(ws).connect_channel(["global", "main"]) #Connect to global and main channels - await bot.client.note.send(content=datetime.now().strftime('%Y-%m-%d %H:%M:%S') + " :roboduck: Bot started!", visibility="specified") - self.loop_12h.start() #Launching renew posts every 12 hours - self.loop_1h.start() # - print(datetime.now().strftime('%Y-%m-%d %H:%M:%S')+" Roboduck Bot started!") - + await Router(ws).connect_channel(["global", "main"]) # Connect to global and main channels + await bot.client.note.send(content=datetime.now().strftime('%Y-%m-%d %H:%M:%S') + " :roboduck: Bot started!", + visibility="specified") + self.loop_12h.start() # Launching renew posts every 12 hours + self.loop_1h.start() # + print(datetime.now().strftime('%Y-%m-%d %H:%M:%S') + " Roboduck Bot started!") async def on_mention(self, note: Note): - text="" - if (not note.author.is_bot): - inhalt=note.content - if (note.author.host is None): - text = "@" + note.author.name + " " #Building the reply on same instance - else: - text = "@" + note.author.name + "@" + note.author.host + " " #Building the reply on foreign instance - + if not note.author.is_bot: + text = note.author.action.get_mention() text += create_sentence() - await note.reply(content=text) #Reply to a note + await note.reply(content=text) # Reply to a note if __name__ == "__main__": - databasepath = (Path(__file__).parent).joinpath('roboduck.db') + databasepath = Path(__file__).parent.joinpath('roboduck.db') - if (not (os.path.exists(databasepath) and os.stat(databasepath).st_size != 0)): + if not (os.path.exists(databasepath) and os.stat(databasepath).st_size != 0): init_bot() bot = MyBot() diff --git a/roboduck.py b/roboduck.py index d983ff1..8db326c 100644 --- a/roboduck.py +++ b/roboduck.py @@ -10,6 +10,7 @@ from pathlib import Path from datetime import * from time import sleep + def check_str_to_bool(text) -> bool: if (text == "True" or text == "true" or text == "TRUE"): return True @@ -18,6 +19,7 @@ def check_str_to_bool(text) -> bool: else: return True + def get_notes(**kwargs): noteid = "k" sinceid = "" @@ -27,12 +29,12 @@ def get_notes(**kwargs): if (kwargs): if ("min_notes" in kwargs): - #print("min_notes found!") + # print("min_notes found!") init = True min_notes = kwargs["min_notes"] elif ("lastnote" in kwargs): - #print("Lastnote found!") + # print("Lastnote found!") init = False sinceid = kwargs["lastnote"] @@ -45,41 +47,40 @@ def get_notes(**kwargs): print("Exiting routine") return None - #Load configuration + # Load configuration config = configparser.ConfigParser() config.read(os.path.join(os.path.dirname(__file__), 'bot.cfg')) - #print(os.path.join(os.path.dirname(__file__), 'bot.cfg')) + # print(os.path.join(os.path.dirname(__file__), 'bot.cfg')) - url="https://"+config.get("misskey","instance_read")+"/api/users/show" - host=config.get("misskey","instance_read") + url = "https://" + config.get("misskey", "instance_read") + "/api/users/show" + host = config.get("misskey", "instance_read") try: - req = requests.post(url, json={"username" : config.get("misskey","user_read"), "host" : host}) + req = requests.post(url, json={"username": config.get("misskey", "user_read"), "host": host}) req.raise_for_status() except requests.exceptions.HTTPError as err: print("Couldn't get Username! " + str(err)) sys.exit(1) - userid = req.json()["id"] - #Read & Sanitize Inputs from Config File + # Read & Sanitize Inputs from Config File try: - includeReplies = check_str_to_bool(config.get("markov","includeReplies")) + includeReplies = check_str_to_bool(config.get("markov", "includeReplies")) except (TypeError, ValueError) as err: includeReplies = True try: - includeMyRenotes = check_str_to_bool(config.get("markov","includeMyRenotes")) + includeMyRenotes = check_str_to_bool(config.get("markov", "includeMyRenotes")) except (TypeError, ValueError) as err: includeMyRenotes = False try: - excludeNsfw = check_str_to_bool(config.get("markov","excludeNsfw")) + excludeNsfw = check_str_to_bool(config.get("markov", "excludeNsfw")) except (TypeError, ValueError) as err: excludeNsfw = True run = True - oldnote="" + oldnote = "" while run: @@ -87,19 +88,19 @@ def get_notes(**kwargs): break try: - req = requests.post("https://"+config.get("misskey","instance_read")+"/api/users/notes", json = { - "userId": userid, - "includeReplies" : includeReplies, - "limit" : 100, - "includeMyRenotes" : includeMyRenotes, - "withFiles" : False, - "excludeNsfw" : excludeNsfw, - "untilId" : noteid, - "sinceId" : sinceid - }) + req = requests.post("https://" + config.get("misskey", "instance_read") + "/api/users/notes", json={ + "userId": userid, + "includeReplies": includeReplies, + "limit": 100, + "includeMyRenotes": includeMyRenotes, + "withFiles": False, + "excludeNsfw": excludeNsfw, + "untilId": noteid, + "sinceId": sinceid + }) req.raise_for_status() except requests.exceptions.HTTPError as err: - print("Couldn't get Posts! "+str(err)) + print("Couldn't get Posts! " + str(err)) sys.exit(1) for jsonObj in req.json(): @@ -110,36 +111,38 @@ def get_notes(**kwargs): oldnote = noteid - noteid = notesList[len(notesList)-1]["id"] + noteid = notesList[len(notesList) - 1]["id"] print(str(len(notesList)) + " Notes read.") print("Processing notes...") for element in notesList: lastTime = element["createdAt"] - lastTimestamp = int(datetime.timestamp(datetime.strptime(lastTime, '%Y-%m-%dT%H:%M:%S.%f%z'))*1000) + lastTimestamp = int(datetime.timestamp(datetime.strptime(lastTime, '%Y-%m-%dT%H:%M:%S.%f%z')) * 1000) content = element["text"] - if content is None: #Skips empty notes (I don't know how there could be empty notes) + if content is None: # Skips empty notes (I don't know how there could be empty notes) continue - content = regex.sub(r"(?>@(?>[\w\-])+)(?>@(?>[\w\-\.])+)?", '', content) #Remove instance name with regular expression - content = content.replace("::",": :") #Break long emoji chains - content = content.replace("@", "@"+chr(8203)) + content = regex.sub(r"(?>@(?>[\w\-])+)(?>@(?>[\w\-\.])+)?", '', + content) # Remove instance name with regular expression + content = content.replace("::", ": :") # Break long emoji chains + content = content.replace("@", "@" + chr(8203)) - dict = {"id" : element["id"], "text" : content, "timestamp" : lastTimestamp} + dict = {"id": element["id"], "text": content, "timestamp": lastTimestamp} returnList.append(dict) return returnList + def calculate_markov_chain(): text = "" - #Load configuration + # Load configuration config = configparser.ConfigParser() config.read((Path(__file__).parent).joinpath('bot.cfg')) try: - max_notes = config.get("markov","max_notes") + max_notes = config.get("markov", "max_notes") except (TypeError, ValueError) as err: max_notes = "10000" @@ -161,13 +164,14 @@ def calculate_markov_chain(): text += row[0] + "\n" markovchain = markovify.Text(text) - markovchain.compile(inplace = True) + markovchain.compile(inplace=True) markov_json = markovchain.to_json() with open((Path(__file__).parent).joinpath('markov.json'), "w", encoding="utf-8") as markov: json.dump(markov_json, markov) + def clean_database(): databasepath = (Path(__file__).parent).joinpath('roboduck.db') if (not (os.path.exists(databasepath) and os.stat(databasepath).st_size != 0)): @@ -178,12 +182,12 @@ def clean_database(): with open(databasepath, "a", encoding="utf-8") as f: database = sqlite3.connect(databasepath) - #Reading config file bot.cfg with config parser + # Reading config file bot.cfg with config parser config = configparser.ConfigParser() config.read((Path(__file__).parent).joinpath('bot.cfg')) - #print((Path(__file__).parent).joinpath('bot.cfg')) + # print((Path(__file__).parent).joinpath('bot.cfg')) try: - max_notes = config.get("markov","max_notes") + max_notes = config.get("markov", "max_notes") except (TypeError, ValueError) as err: max_notes = "10000" @@ -193,59 +197,60 @@ def clean_database(): database.commit() database.close() + def create_sentence(): with open((os.path.join((Path(__file__).parent), 'markov.json')), "r", encoding="utf-8") as markov: markov_json = json.load(markov) text_model = markovify.Text.from_json(markov_json) - note="" + note = "" - #Reading config file bot.cfg with config parser + # Reading config file bot.cfg with config parser config = configparser.ConfigParser() config.read((Path(__file__).parent).joinpath('bot.cfg')) - #print((Path(__file__).parent).joinpath('bot.cfg')) - #Read & Sanitize Inputs + # print((Path(__file__).parent).joinpath('bot.cfg')) + # Read & Sanitize Inputs try: - test_output = check_str_to_bool(config.get("markov","test_output")) + test_output = check_str_to_bool(config.get("markov", "test_output")) except (TypeError, ValueError) as err: - #print("test_output: " + str(err)) + # print("test_output: " + str(err)) test_output = True if (test_output): try: - tries = int(config.get("markov","tries")) + tries = int(config.get("markov", "tries")) except (TypeError, ValueError) as err: - #print("tries: " + str(err)) + # print("tries: " + str(err)) tries = 250 try: - max_overlap_ratio = float(config.get("markov","max_overlap_ratio")) + max_overlap_ratio = float(config.get("markov", "max_overlap_ratio")) except (TypeError, ValueError) as err: - #print("max_overlap_ratio: " + str(err)) + # print("max_overlap_ratio: " + str(err)) max_overlap_ratio = 0.7 try: - max_overlap_total = int(config.get("markov","max_overlap_total")) + max_overlap_total = int(config.get("markov", "max_overlap_total")) except (TypeError, ValueError) as err: - #print("max_overlap_total: " + str(err)) + # print("max_overlap_total: " + str(err)) max_overlap_total = 10 try: - max_words = int(config.get("markov","max_words")) + max_words = int(config.get("markov", "max_words")) except (TypeError, ValueError) as err: - #print("max_words: " + str(err)) + # print("max_words: " + str(err)) max_words = None try: - min_words = int(config.get("markov","min_words")) + min_words = int(config.get("markov", "min_words")) except (TypeError, ValueError) as err: - #print("min_words: " + str(err)) + # print("min_words: " + str(err)) min_words = None if (max_words is not None and min_words is not None): if (min_words >= max_words): - #print("min_words ("+str(min_words)+") bigger than max_words ("+str(max_words)+")! Swapping values!") + # print("min_words ("+str(min_words)+") bigger than max_words ("+str(max_words)+")! Swapping values!") swap = min_words min_words = max_words max_words = swap @@ -268,20 +273,21 @@ def create_sentence(): print("min_words: " + str(min_words)) """ - #Applying Inputs + # Applying Inputs note = text_model.make_sentence( - test_output = test_output, - tries = tries, - max_overlap_ratio = max_overlap_ratio, - max_overlap_total = max_overlap_total, - max_words = max_words, - min_words = min_words - ) + test_output=test_output, + tries=tries, + max_overlap_ratio=max_overlap_ratio, + max_overlap_total=max_overlap_total, + max_words=max_words, + min_words=min_words + ) if (note is not None): return note else: return "Error in markov chain sentence creation: Couldn't calculate sentence!\n\n☹ Please try again! " + def update(): notesList = [] databasepath = (Path(__file__).parent).joinpath('roboduck.db') @@ -299,7 +305,7 @@ def update(): sinceNote = data.fetchone()[0] - notesList = get_notes(lastnote = sinceNote) + notesList = get_notes(lastnote=sinceNote) if (notesList == 0): database.close() @@ -307,7 +313,8 @@ def update(): print("Insert new notes to database...") for note in notesList: - database.execute("INSERT OR IGNORE INTO notes (id, text, timestamp) VALUES(?, ?, ?)", [note["id"], note["text"], note["timestamp"]]) + database.execute("INSERT OR IGNORE INTO notes (id, text, timestamp) VALUES(?, ?, ?)", + [note["id"], note["text"], note["timestamp"]]) database.commit() print("Notes updated!") @@ -326,6 +333,7 @@ def update(): print("\nUpdate done!") + def init_bot(): notesList = [] databasepath = (Path(__file__).parent).joinpath('roboduck.db') @@ -345,23 +353,24 @@ def init_bot(): print("Table NOTES created...") - #Load configuration + # Load configuration config = configparser.ConfigParser() config.read((Path(__file__).parent).joinpath('bot.cfg')) try: - initnotes = int(config.get("markov","min_notes")) + initnotes = int(config.get("markov", "min_notes")) except (TypeError, ValueError) as err: - #print(err) - initnotes=1000 + # print(err) + initnotes = 1000 print("Try reading first " + str(initnotes) + " notes.") - notesList = get_notes(min_notes = initnotes) + notesList = get_notes(min_notes=initnotes) print("Writing notes into database...") for note in notesList: - database.execute("INSERT INTO notes (id, text, timestamp) VALUES(?, ?, ?)", [note["id"], note["text"], note["timestamp"]]) + database.execute("INSERT INTO notes (id, text, timestamp) VALUES(?, ?, ?)", + [note["id"], note["text"], note["timestamp"]]) database.commit() database.close()