From: Georgios Atheridis Date: Fri, 1 Apr 2022 16:22:54 +0000 (+0300) Subject: added auto messages for stream and a smart stream offline checker X-Git-Url: https://git.atheridis.org/?a=commitdiff_plain;h=4ea8a8dbee9a325478ca4a6cba91586df66039ff;p=ihaspeks%2Faptbot-ihaspeks.git added auto messages for stream and a smart stream offline checker --- diff --git a/skgyorugo/README.md b/skgyorugo/README.md index dd1f015..b601724 100644 --- a/skgyorugo/README.md +++ b/skgyorugo/README.md @@ -18,6 +18,7 @@ - [ ] specific word in message {message.0}, {message.1}, etc. - [ ] replied variable {reply.nick} {reply.message} {reply.message.0} - [ ] sub sellout bot +- [ ] schedule ## Basic Commands - [ ] int diff --git a/skgyorugo/analyze_auto_message.py b/skgyorugo/analyze_auto_message.py new file mode 100644 index 0000000..5031b03 --- /dev/null +++ b/skgyorugo/analyze_auto_message.py @@ -0,0 +1,57 @@ +from aptbot.bot import Bot, Message, Commands +import os +import sqlite3 +import time +import tools.smart_privmsg +from tools.smart_start_stream_time import start_stream_timestamp as stream_ts + +PATH = os.path.dirname(os.path.realpath(__file__)) + + +def do_auto_message(bot: Bot, message: Message, auto_message_modules: dict): + conn = sqlite3.connect(os.path.join(PATH, "database.db")) + c = conn.cursor() + + start_stream_ts = stream_ts() + if not start_stream_ts: + return + + c.execute( + """ + SELECT + name, + cooldown, + end_time, + last_used, + value + FROM + auto_messages + LEFT JOIN auto_message_values USING (name) + """ + ) + fetched = c.fetchall() + if not fetched: + conn.close() + return + + for auto_message in fetched: + name, cooldown, end_time, last_used, value = auto_message + if time.time() < last_used + cooldown: + continue + if time.time() > start_stream_ts + end_time and end_time != 0: + continue + if value: + tools.smart_privmsg.send(bot, message, value) + else: + auto_message_modules[name].main(bot, message) + c.execute( + "REPLACE INTO auto_messages VALUES (?, ?, ?, ?)", + ( + name, + cooldown, + end_time, + int(time.time()), + ) + ) + conn.commit() + conn.close() diff --git a/skgyorugo/analyze_command.py b/skgyorugo/analyze_command.py index 559070f..d071dd7 100644 --- a/skgyorugo/analyze_command.py +++ b/skgyorugo/analyze_command.py @@ -55,6 +55,7 @@ def do_command(bot: Bot, message: Message, command_modules: dict): fetched = c.fetchall() print(fetched) if not fetched: + conn.close() return (_, value, @@ -68,6 +69,7 @@ def do_command(bot: Bot, message: Message, command_modules: dict): f"The command '{prefix}{command}' is on cooldown. \ Please wait {int(avail_time - message_timestamp) + 1} seconds." ) + conn.close() return c.execute( @@ -86,6 +88,7 @@ def do_command(bot: Bot, message: Message, command_modules: dict): ) ) conn.commit() + conn.close() if value is None: command_modules[command].main(bot, message) else: diff --git a/skgyorugo/auto_messages/latege.py b/skgyorugo/auto_messages/latege.py new file mode 100644 index 0000000..b56a29d --- /dev/null +++ b/skgyorugo/auto_messages/latege.py @@ -0,0 +1,30 @@ +from aptbot.bot import Message, Commands, Bot +import datetime as dt +from datetime import datetime +import tools.smart_start_stream_time + +COOLDOWN = 120 +END_TIME = COOLDOWN * 6 + +STREAM_SCHEDULE = dt.time(17, 30) + + +def main(bot: Bot, message: Message): + start_stream_ts = tools.smart_start_stream_time.start_stream_timestamp() + if not start_stream_ts: + return + start_stream_dt = datetime.utcfromtimestamp(start_stream_ts) + stream_schedule_dt = datetime.combine(datetime.now(), STREAM_SCHEDULE) + latege_amount = (start_stream_dt - stream_schedule_dt).total_seconds() + if latege_amount > 45 * 60: + msg = f"{message.channel} is so Latege he might as well have not \ + streamed today. At least he's early for tomorrow COPIUM . \ + {message.channel} is Latege by {latege_amount} seconds Madge" + elif latege_amount > 0: + msg = f"{message.channel} is Latege by {latege_amount} seconds again Madge" + elif latege_amount == 0: + msg = f"Amazing!!! {message.channel} is EXACTLY on time today ihaspeHappy" + else: + msg = f"UNBELIEVABLE!!!!! {message.channel} is EARLY by {-latege_amount} seconds!!!!\ + This has NEVER happened before POGGERS" + bot.send_privmsg(message.channel, msg) diff --git a/skgyorugo/auto_messages/youtube.py b/skgyorugo/auto_messages/youtube.py new file mode 100644 index 0000000..c898490 --- /dev/null +++ b/skgyorugo/auto_messages/youtube.py @@ -0,0 +1,17 @@ +from aptbot.bot import Message, Commands, Bot +import yt_api.videos + +COOLDOWN = 20 * 60 +END_TIME = 0 + +CHANNEL_ID = "UCQ7C3NUKY6TSkURdUdVoYFw" + + +def main(bot: Bot, message: Message): + video = yt_api.videos.get_newest_video(CHANNEL_ID) + if video: + video_link = f"https://www.youtube.com/watch?v={video.video_id}" + msg = f"Watch Peks' latest video \" {video.video_name} \" here: {video_link}" + else: + msg = f"Check out my youtube channel here -> https://www.youtube.com/channel/{CHANNEL_ID}" + bot.send_privmsg(message.channel, msg) diff --git a/skgyorugo/commands/youtube.py b/skgyorugo/commands/youtube.py index 1829fa1..b034c29 100644 --- a/skgyorugo/commands/youtube.py +++ b/skgyorugo/commands/youtube.py @@ -14,7 +14,7 @@ def main(bot: Bot, message: Message): video = yt_api.videos.get_newest_video(CHANNEL_ID) if video: video_link = f"https://www.youtube.com/watch?v={video.video_id}" - msg = f"Watch my latest video \"{video.video_name}\" here -> {video_link}" - bot.send_privmsg(message.channel, msg) + msg = f"Watch Peks' latest video \" {video.video_name} \" here: {video_link}" else: msg = f"Check out my youtube channel here -> https://www.youtube.com/channel/{CHANNEL_ID}" + bot.send_privmsg(message.channel, msg) diff --git a/skgyorugo/database_manager.py b/skgyorugo/database_manager.py new file mode 100644 index 0000000..98dbae9 --- /dev/null +++ b/skgyorugo/database_manager.py @@ -0,0 +1,169 @@ +import sqlite3 +import os +import ttv_api.users + +PATH = os.path.dirname(os.path.realpath(__file__)) + + +def create_database(): + conn = sqlite3.connect(os.path.join(PATH, "database.db")) + c = conn.cursor() + try: + c.execute( + """ + CREATE TABLE commands ( + command TEXT NOT NULL, + prefix TEXT NOT NULL, + permission INTEGER NOT NULL, + description TEXT, + user_cooldown INTEGER NOT NULL, + global_cooldown INTEGER NOT NULL, + last_used INTEGER NOT NULL, + PRIMARY KEY (command) + ) + """ + ) + except sqlite3.OperationalError: + print("Table commands exists") + + try: + c.execute( + """ + CREATE TABLE users ( + user_id text NOT NULL, + permission INTEGER NOT NULL, + PRIMARY KEY (user_id) + ) + """ + ) + except sqlite3.OperationalError as e: + print(f"Table users exists: {e}") + else: + admin_id = ttv_api.users.get_users(user_logins=["skgyorugo"]) + if admin_id: + c.execute("INSERT INTO users VALUES (?, ?)", + (admin_id[0].user_id, 0)) + + try: + c.execute( + """ + CREATE TABLE cooldowns ( + user_id TEXT NOT NULL, + command TEXT NOT NULL, + user_cooldown INTEGER NOT NULL, + FOREIGN KEY(user_id) REFERENCES users(user_id) + FOREIGN KEY(command) REFERENCES commands(command) + PRIMARY KEY (user_id, command) + ) + """ + ) + except sqlite3.OperationalError: + print("Table cooldowns exists") + + try: + c.execute( + """ + CREATE TABLE command_values ( + command TEXT NOT NULL, + value TEXT NOT NULL, + FOREIGN KEY(command) REFERENCES commands(command) + ) + """ + ) + except sqlite3.OperationalError: + print("Table cooldowns exists") + + try: + c.execute( + """ + CREATE TABLE auto_messages ( + name TEXT NOT NULL, + cooldown INTEGER NOT NULL, + end_time INTEGER NOT NULL, + last_used INTEGER NOT NULL, + PRIMARY KEY (name) + ) + """ + ) + except sqlite3.OperationalError: + print("Table commands exists") + + try: + c.execute( + """ + CREATE TABLE auto_message_values ( + name TEXT NOT NULL, + value TEXT NOT NULL, + FOREIGN KEY(name) REFERENCES auto_messages(name) + ) + """ + ) + except sqlite3.OperationalError: + print("Table cooldowns exists") + + try: + c.execute( + """ + CREATE TABLE streamer_info ( + start_stream_ts INTEGER NOT NULL, + last_checked INTEGER NOT NULL, + ended INTEGER NOT NULL, + PRIMARY KEY (start_stream_ts) + ) + """ + ) + except sqlite3.OperationalError as e: + print(f"Table users exists: {e}") + + conn.commit() + conn.close() + + +def update_commands_in_database(modules, commands): + conn = sqlite3.connect(os.path.join(PATH, "database.db")) + c = conn.cursor() + + for command in commands: + command_name = command.split('.')[0] + command_permission = modules[command_name].PERMISSION + command_prefix = modules[command_name].PREFIX + command_description = modules[command_name].DESCRIPTION + command_user_cooldown = modules[command_name].USER_COOLDOWN + command_global_cooldown = modules[command_name].GLOBAL_COOLDOWN + command_last_used = 0 + c.execute( + "REPLACE INTO commands VALUES (?, ?, ?, ?, ?, ?, ?)", + ( + command_name, + command_prefix, + command_permission, + command_description, + command_user_cooldown, + command_global_cooldown, + command_last_used, + ) + ) + conn.commit() + conn.close() + + +def update_auto_messages_in_database(modules, auto_messages): + conn = sqlite3.connect(os.path.join(PATH, "database.db")) + c = conn.cursor() + + for auto_message in auto_messages: + auto_message_name = auto_message.split('.')[0] + auto_message_cooldown = modules[auto_message_name].COOLDOWN + auto_message_end_time = modules[auto_message_name].END_TIME + auto_message_last_used = 0 + c.execute( + "REPLACE INTO commands VALUES (?, ?, ?, ?)", + ( + auto_message_name, + auto_message_cooldown, + auto_message_end_time, + auto_message_last_used, + ) + ) + conn.commit() + conn.close() diff --git a/skgyorugo/main.py b/skgyorugo/main.py index de62fb6..0908c85 100644 --- a/skgyorugo/main.py +++ b/skgyorugo/main.py @@ -2,26 +2,29 @@ from aptbot.bot import Bot, Message, Commands import os import importlib import importlib.util -import sqlite3 -from importlib import reload import traceback -import ttv_api.users import tools.raid import tools.smart_privmsg import tools.permissions import analyze_command import scripts.unit_converter -import yt_api.videos +import database_manager +from importlib import reload reload(tools.raid) reload(tools.smart_privmsg) reload(tools.permissions) reload(analyze_command) reload(scripts.unit_converter) +reload(database_manager) + PATH = os.path.dirname(os.path.realpath(__file__)) COMMANDS_PATH = os.path.join(PATH, "commands") +AUTO_MESSAGES_PATH = os.path.join(PATH, "auto_messages") +specs = {} +modules = {} commands = [ c for c in os.listdir(COMMANDS_PATH) if os.path.isfile(os.path.join(COMMANDS_PATH, c)) @@ -29,7 +32,6 @@ commands = [ commands = filter(lambda x: not x.startswith('.'), commands) commands = filter(lambda x: os.path.splitext(x)[1] == ".py", commands) commands = list(commands) -specs = {} for command in commands: specs[command.split('.')[0]] = ( importlib.util.spec_from_file_location( @@ -38,122 +40,37 @@ for command in commands: ) ) -modules = {} -for command in specs: - modules[command] = importlib.util.module_from_spec(specs[command]) - if not specs[command]: +auto_messages = [ + c for c in os.listdir(COMMANDS_PATH) if os.path.isfile(os.path.join(COMMANDS_PATH, c)) +] +auto_messages = filter(lambda x: not x.startswith('.'), auto_messages) +auto_messages = filter( + lambda x: os.path.splitext(x)[1] == ".py", + auto_messages +) +auto_messages = list(auto_messages) +for auto_message in auto_messages: + specs[auto_message.split('.')[0]] = ( + importlib.util.spec_from_file_location( + f"{auto_message.split('.')[0]}", + os.path.join(COMMANDS_PATH, auto_message) + ) + ) + +for spec in specs: + modules[spec] = importlib.util.module_from_spec(specs[spec]) + if not specs[spec]: continue try: - specs[command].loader.exec_module(modules[command]) + specs[spec].loader.exec_module(modules[spec]) except Exception as e: print() print(traceback.format_exc()) print(f"Problem Loading Module: {e}") -def create_database(): - conn = sqlite3.connect(os.path.join(PATH, "database.db")) - c = conn.cursor() - try: - c.execute( - """ - CREATE TABLE commands ( - command TEXT NOT NULL, - prefix TEXT NOT NULL, - permission INTEGER NOT NULL, - description TEXT, - user_cooldown INTEGER NOT NULL, - global_cooldown INTEGER NOT NULL, - last_used INTEGER NOT NULL, - PRIMARY KEY (command) - ) - """ - ) - except sqlite3.OperationalError: - print("Table commands exists") - - try: - c.execute( - """ - CREATE TABLE users ( - user_id text NOT NULL, - permission INTEGER NOT NULL, - PRIMARY KEY (user_id) - ) - """ - ) - except sqlite3.OperationalError as e: - print(f"Table users exists: {e}") - else: - aptbot_id = ttv_api.users.get_users(user_logins=["skgyorugo"]) - if aptbot_id: - c.execute("INSERT INTO users VALUES (?, ?)", - (aptbot_id[0].user_id, 0)) - - try: - c.execute( - """ - CREATE TABLE cooldowns ( - user_id TEXT NOT NULL, - command TEXT NOT NULL, - user_cooldown INTEGER NOT NULL, - FOREIGN KEY(user_id) REFERENCES users(user_id) - FOREIGN KEY(command) REFERENCES commands(command) - PRIMARY KEY (user_id, command) - ) - """ - ) - except sqlite3.OperationalError: - print("Table cooldowns exists") - - try: - c.execute( - """ - CREATE TABLE command_values ( - command TEXT NOT NULL, - value TEXT NOT NULL, - FOREIGN KEY(command) REFERENCES commands(command) - ) - """ - ) - except sqlite3.OperationalError: - print("Table cooldowns exists") - - conn.commit() - conn.close() - - -def update_commands_in_database(): - conn = sqlite3.connect(os.path.join(PATH, "database.db")) - c = conn.cursor() - - for command in commands: - command_name = command.split('.')[0] - command_permission = modules[command_name].PERMISSION - command_prefix = modules[command_name].PREFIX - command_description = modules[command_name].DESCRIPTION - command_user_cooldown = modules[command_name].USER_COOLDOWN - command_global_cooldown = modules[command_name].GLOBAL_COOLDOWN - command_last_used = 0 - # try: - c.execute( - "REPLACE INTO commands VALUES (?, ?, ?, ?, ?, ?, ?)", - ( - command_name, - command_prefix, - command_permission, - command_description, - command_user_cooldown, - command_global_cooldown, - 0, - ) - ) - conn.commit() - conn.close() - - -create_database() -update_commands_in_database() +database_manager.create_database() +database_manager.update_commands_in_database(modules, commands) def main(bot: Bot, message: Message): diff --git a/skgyorugo/tools/smart_start_stream_time.py b/skgyorugo/tools/smart_start_stream_time.py new file mode 100644 index 0000000..5218936 --- /dev/null +++ b/skgyorugo/tools/smart_start_stream_time.py @@ -0,0 +1,91 @@ +import time +import os +import ttv_api.users +import ttv_api.stream +import ttv_api.channel +import sqlite3 +from typing import Optional + +STREAMER_PATH = os.path.abspath(os.path.join(__file__, "../..")) +TOOLS_PATH = os.path.dirname(os.path.realpath(__file__)) +PATH = os.path.join(TOOLS_PATH, "..") + + +CHECK_STREAMTIME_CD = 5 * 60 +MAX_OFF_STREAM_MARGIN = 60 * 60 + + +def start_stream_timestamp() -> Optional[int]: + streamer_login = os.path.split(STREAMER_PATH)[1] + + conn = sqlite3.connect(os.path.join(PATH, "database.db")) + c = conn.cursor() + + c.execute( + """ + SELECT + start_stream_ts, + last_checked, + ended + FROM + stream_info + WHERE + last_checked = (SELECT MAX(last_checked) FROM stream_info); + AND ended = 0 + """ + ) + + fetched = c.fetchone() + if fetched: + start_stream_ts, last_checked, _ = fetched + if last_checked + CHECK_STREAMTIME_CD < time.time(): + return start_stream_ts + + stream_info = ttv_api.stream.get_streams(user_logins=[streamer_login]) + if not stream_info and not fetched: + return + + if not stream_info: + start_stream_ts, last_checked, _ = fetched + if last_checked + MAX_OFF_STREAM_MARGIN < time.time(): + conn.close() + return + + c.execute( + "REPLACE INTO commands VALUES (?, ?, ?)", + ( + start_stream_ts, + last_checked, + 1, + ) + ) + conn.commit() + conn.close() + return + + if not fetched: + start_stream_ts = int(stream_info[0].started_at.timestamp()) + c.execute( + "REPLACE INTO commands VALUES (?, ?, ?)", + ( + start_stream_ts, + int(time.time()), + 0, + ) + ) + conn.commit() + conn.close() + return start_stream_ts + + start_stream_ts, last_checked, _ = fetched + c.execute( + "REPLACE INTO commands VALUES (?, ?, ?)", + ( + start_stream_ts, + int(time.time()), + 0, + ) + ) + conn.commit() + conn.close() + return start_stream_ts