From 3b806f9161390fa837d80c2db54440408e0a9807 Mon Sep 17 00:00:00 2001 From: Georgios Atheridis Date: Fri, 30 Jun 2023 21:11:42 +0100 Subject: [PATCH] Add Subathon --- ihaspeks/main.py | 41 ++++--- ihaspeks/scripts/subathon.py | 208 +++++++++++++++++++++++++++++++++++ 2 files changed, 231 insertions(+), 18 deletions(-) create mode 100644 ihaspeks/scripts/subathon.py diff --git a/ihaspeks/main.py b/ihaspeks/main.py index 277be70..9c870fe 100644 --- a/ihaspeks/main.py +++ b/ihaspeks/main.py @@ -1,28 +1,30 @@ -from aptbot import Bot, Message, Commands -import os import importlib import importlib.util +import logging +import os +import time import traceback -import tools.raid -import tools.smart_privmsg -import tools.permissions -import tools.smart_start_stream_time +from importlib import reload +from threading import Event, Thread + +import analyze_auto_message import analyze_command -import scripts.unit_converter +import database_manager import scripts.alwase -import scripts.chatting import scripts.chat -import scripts.crylaugh +import scripts.chatting import scripts.clean_queue +import scripts.command_generator +import scripts.crylaugh import scripts.discord_start_stream +import scripts.subathon +import scripts.unit_converter import scripts.will_be_missed -import scripts.command_generator -import database_manager -import analyze_auto_message -import time -import logging -from threading import Event -from importlib import reload +import tools.permissions +import tools.raid +import tools.smart_privmsg +import tools.smart_start_stream_time +from aptbot import Bot, Commands, Message reload(tools.raid) reload(tools.smart_privmsg) @@ -37,6 +39,7 @@ reload(scripts.crylaugh) reload(scripts.clean_queue) reload(scripts.discord_start_stream) reload(scripts.will_be_missed) +reload(scripts.subathon) reload(scripts.command_generator) reload(database_manager) reload(analyze_auto_message) @@ -120,18 +123,19 @@ database_manager.update_auto_messages_in_database(auto_message_modules, auto_mes def start(bot: Bot, message: Message, stop_event: Event): i = 0 wait = 5 + scripts.subathon.donations(bot, message) while not stop_event.is_set(): i += wait started = tools.smart_start_stream_time.update_start_stream_timestamp() if started == "START": scripts.clean_queue.clean_queue() scripts.discord_start_stream.announce() - bot.send_privmsg( + bot.send_message( message.channel, "Stream has started, you can now use ?join" ) elif started == "END": scripts.clean_queue.clean_queue() - bot.send_privmsg(message.channel, "Stream has ended") + bot.send_message(message.channel, "Stream has ended") if i >= 30: analyze_auto_message.do_auto_message(bot, message, auto_message_modules) i = 0 @@ -152,6 +156,7 @@ def main(bot: Bot, message: Message): scripts.chat.chat(bot, message) scripts.crylaugh.crylaugh(bot, message) scripts.will_be_missed.will_be_missed(bot, message) + scripts.subathon.subathon(bot, message) # if message.command == Commands.PART: # if message.nick in {'jelemar', 'flauenn', 'ihaspeks', 'blobin_wobin', 'officiallysp'}: diff --git a/ihaspeks/scripts/subathon.py b/ihaspeks/scripts/subathon.py new file mode 100644 index 0000000..a71e1c0 --- /dev/null +++ b/ihaspeks/scripts/subathon.py @@ -0,0 +1,208 @@ +import json +import logging +import os +import socket +import sqlite3 + +import socketio +import tools.smart_privmsg +from aptbot.bot import Bot, Commands, Message +from numpy import array, ceil, exp, sum +from numpy.random import normal + +logger = logging.getLogger(__name__) + +SCRIPTS_PATH = os.path.dirname(os.path.realpath(__file__)) +PATH = os.path.join(SCRIPTS_PATH, "..") + +socket_file = os.getenv("SUBATHON_SOCKET", "~/.cache/subathon.sock") + +conn = sqlite3.connect(os.path.join(PATH, "subathon.db")) +c = conn.cursor() + +c.execute( + """ + CREATE TABLE IF NOT EXISTS subs ( + user_id TEXT NOT NULL, + display_name TEXT NOT NULL, + sub_count INTEGER NOT NULL, + PRIMARY KEY (user_id) + ); + """ +) +c.execute( + """ + CREATE TABLE IF NOT EXISTS raids ( + user_id TEXT NOT NULL, + display_name TEXT NOT NULL, + raid_count INTEGER NOT NULL, + PRIMARY KEY (user_id) + ); + """ +) +conn.commit() +c.close() + + +def subathon(bot: Bot, message: Message): + if message.command == Commands.USERNOTICE: + if message.tags["msg-id"] in {"sub", "resub", "subgift"}: + user_id = message.tags["user-id"] + sub_type = message.tags["msg-param-sub-plan"] + multiplier = 1 + if sub_type.lower() == "2000": + multiplier = 2 + elif sub_type.lower() == "3000": + multiplier = 6 + display_name = message.tags["display-name"] + + conn = sqlite3.connect(os.path.join(PATH, "subathon.db")) + c = conn.cursor() + + c.execute( + """SELECT sub_count FROM subs WHERE user_id = ?;""", + (user_id,), + ) + if sub_count := c.fetchone(): + c.execute( + """UPDATE subs + SET + sub_count = sub_count + 1 + WHERE + user_id = ?; + """, + (user_id,), + ) + else: + c.execute( + "INSERT OR IGNORE INTO subs VALUES (?, ?, ?)", + ( + user_id, + display_name, + 1, + ), + ) + conn.commit() + conn.close() + + # if None, then subcount is 0, else it's subcount + sub_count = sub_count or 0 + timer_add = calculate_increase(sub_count) + elif message.tags["msg-id"] == "raid": + raid_count = message.tags["msg-param-viewerCount"] + if int(raid_count) < 5: + return + raider_id = message.tags["user-id"] + display_name = message.tags["msg-param-displayName"] + + conn = sqlite3.connect(os.path.join(PATH, "subathon.db")) + c = conn.cursor() + + c.execute( + """SELECT raid_count FROM raids WHERE user_id = ?;""", + (raider_id,), + ) + + if c.fetchone(): + return + c.execute( + "INSERT OR IGNORE INTO raids VALUES (?, ?, ?)", + ( + raider_id, + display_name, + raid_count, + ), + ) + timer_add = int(raid_count) + multiplier = 10 * 60 + else: + return + elif message.command == Commands.PRIVMSG: + if bits := message.tags.get("bits"): + # Every 400 bits is the same as a sub, + # assuming you already subbed 10 times + div_count = (int(bits) // 400) * calculate_increase(10) + + # Add 3 seconds for every 1 bit under 400 bits + rest_count = (int(bits) % 400) * 3 + + timer_add = div_count + rest_count + multiplier = 1 + display_name = message.tags.get("display-name") or message.nick + else: + return + else: + return + + total_timer = timer_add * multiplier + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as client: + client.connect(socket_file) + data = { + "time": total_timer, + "name": display_name, + } + client.send(json.dumps(data).encode()) + client.close() + + verb = "INCREASED ihaspeHappy" if total_timer > 0 else "DECREASED ihaspeAngi" + msg = ( + f"{display_name} has {verb} the timer by {abs(total_timer) // 60} minutes " + + f"and {abs(total_timer) % 60} seconds." + ) + tools.smart_privmsg.send_safe(bot, message.channel, msg) + + +# tools.smart_privmsg.send(bot, message, msg_reply) + + +def donations(bot: Bot, message: Message): + io = socketio.Client() + socket_access_token = os.getenv("STREAMLABS_SOCKET") + + io.connect( + f"https://sockets.streamlabs.com?token={socket_access_token}", + transports="websocket", + ) + + @io.on("event") + def event(data): + match data["type"]: + case "donation": + amount_cents = int(float(data["message"][0]["amount"]) * 100) + div_count = (amount_cents // 400) * calculate_increase(10) + + # Add 3 seconds for every 1 cent under 400 cents + rest_count = (amount_cents % 400) * 3 + + timer_add = div_count + rest_count + display_name = data["message"][0]["from"] + + total_timer = timer_add + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as client: + client.connect(socket_file) + data = { + "time": total_timer, + "name": display_name, + } + client.send(json.dumps(data).encode()) + client.close() + logger.info("%s donated %s", display_name, amount_cents) + + verb = ( + "INCREASED ihaspeHappy" + if total_timer > 0 + else "DECREASED ihaspeAngi" + ) + msg = ( + f"{display_name} has {verb} the timer " + + f"by {abs(total_timer) // 60} minutes " + + f"and {abs(total_timer) % 60} seconds." + ) + tools.smart_privmsg.send_safe(bot, message.channel, msg) + + +def calculate_increase(sub_count: int) -> int: + scale = 0.006 + avg_time = ceil(30.0 * exp(-scale * sub_count) + 5.0) + var_time = 35.0 / (1 + exp(-0.15 * (sub_count - 10))) - 5.0 + return ceil(normal(avg_time, var_time) * 60.0) -- 2.30.2