from datetime import datetime, timedelta from obspython import * from services.Service import Service from threading import Thread import os.path import time KNOWN_COMMANDS = ["addmsg", "delmsg", "listmsg"] SEPARATOR = ";" SUBST_SEP = ".," class TimedMessageService(Service): title = "Timed Message Service" enabled = False msg_added = "" msg_deleted = "" msg_not_deleted = "" file = "" messages = {} interval = 60 running = False def knows(self, command): return command in KNOWN_COMMANDS def eval(self, command, response, users): can_manage = False for badge in response["tags"]["badges"]: if badge["name"] in ["broadcaster", "moderator"]: can_manage = True if not can_manage: return if command == "addmsg": self.queue.append(self.add(response)) elif command == "delmsg": self.queue.append(self.delete(response)) elif command == "listmsg": self.queue.append(self.list(response)) def list_commands(self): return KNOWN_COMMANDS def start(self): self.load_file() self.init_time() self.running = True thread = Thread(target=self.dispatch) thread.daemon = True thread.start() def load_file(self): if self.file == "" or not os.path.isfile(self.file): return with open(self.file, "r", encoding="utf-8") as file: content = file.read().splitlines() for line in content: self.load_message(line) def load_message(self, line): components = line.split(SEPARATOR) starting_time = datetime.now() self.messages[components[0]] = { "interval": int(components[1]), "next_time": "", "message": components[2].replace(SUBST_SEP, SEPARATOR) } def init_time(self): starting_time = datetime.now() times = [] for msg_id in self.messages: new_time = starting_time + timedelta(minutes = self.messages[msg_id]["interval"]) formatted = new_time.strftime("%H:%M") while formatted in times: new_time += timedelta(minutes = 3) formatted = new_time.strftime("%H:%M") times.append(formatted) self.messages[msg_id]["next_time"] = formatted def stop(self): self.running = False # OBS subset ----- def create_properties(self): props = obs_properties_create() obs_properties_add_path(props, "tmsg_file", "Messages list", OBS_PATH_FILE, "Text file (*.txt)", None) obs_properties_add_text(props, "tmsg_msg_added", "Message: Message added", OBS_TEXT_DEFAULT) obs_properties_add_text(props, "tmsg_msg_deleted", "Message: Message deleted", OBS_TEXT_DEFAULT) obs_properties_add_text(props, "tmsg_msg_not_deleted", "Message: Message not deleted", OBS_TEXT_DEFAULT) return props def update(self, settings): self.file = obs_data_get_string(settings, "tmsg_file") self.msg_added = obs_data_get_string(settings, "tmsg_msg_added") self.msg_deleted = obs_data_get_string(settings, "tmsg_msg_deleted") self.msg_not_deleted = obs_data_get_string(settings, "tmsg_msg_not_deleted") # Commands ----- def add(self, response): current_time = datetime.now() components = response["message"].split(" ", 3) print(components) self.messages[components[1]] = { "interval": int(components[2]), "next_time": "", "message": components[3], } next_time = current_time + timedelta(minutes = self.messages[components[1]]["interval"]) self.messages[components[1]]["next_time"] = next_time.strftime("%H:%M") self.write() return f"{self.msg_added}" def delete(self, response): msg_id = response["message"].split(" ", 2)[1] if msg_id not in self.messages: return f"{self.msg_not_deleted}" self.messages.pop(msg_id) self.write() return f"{self.msg_deleted}" def list(self, response): return " ".join(self.messages) def write(self): with open(self.file, "w", encoding="utf-8") as file: for msg_id, message in self.messages.items(): file.write(f"{msg_id}{SEPARATOR}{message['interval']}{SEPARATOR}{message['message'].replace(SEPARATOR, SUBST_SEP)}\n"); # Main function ----- def dispatch(self): while self.running: current_time = datetime.now() formatted = current_time.strftime("%H:%M") for msg_id in self.messages: if self.messages[msg_id]["next_time"] != formatted: continue self.queue.append(self.messages[msg_id]["message"]) new_time = current_time + timedelta(minutes = self.messages[msg_id]["interval"]) self.messages[msg_id]["next_time"] = new_time.strftime("%H:%M") break time.sleep(self.interval)