2024-01-30 21:36:36 +01:00
|
|
|
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")
|
2024-01-31 10:43:29 +01:00
|
|
|
# avoids two messages to spawn at the same time, inducing a 3 minutes delay
|
2024-01-30 21:36:36 +01:00
|
|
|
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)
|