From 78e24a4641ba3bdde7a052c8f17abc7de211f207 Mon Sep 17 00:00:00 2001 From: Kami Date: Sun, 16 Feb 2025 18:07:07 +0100 Subject: [PATCH] Added Twitch channel game get function - This function returns the game being played on the specified channel - Implemented into quotes system: quotes automatically contain game name if quoted from a Twitch channel - Defaults to None if channel is not live - Discord quotes keep old logic: quotes never contain game information --- bot_twitch.py | 9 ++++--- cmd_common/common_commands.py | 13 +++++------ cmd_discord.py | 2 +- cmd_twitch.py | 17 ++++++++------ modules/utility.py | 44 +++++++++++++++++++++++++++++++---- 5 files changed, 60 insertions(+), 25 deletions(-) diff --git a/bot_twitch.py b/bot_twitch.py index 7b9054d..7d497e3 100644 --- a/bot_twitch.py +++ b/bot_twitch.py @@ -105,6 +105,9 @@ class TwitchBot(commands.Bot): async def event_ready(self): globals.log(f"Twitch bot is online as {self.nick}") + modules.utility.list_channels(self) + kami_status = "OokamiKunTV is currently LIVE" if await modules.utility.is_channel_live(self) else "OokamikunTV is currently not streaming" + globals.log(kami_status) log_bot_event(self.db_conn, "TWITCH_RECONNECTED", "Twitch bot logged in.") async def event_disconnected(self): @@ -202,11 +205,7 @@ class TwitchBot(commands.Bot): async def run(self): """ Run the Twitch bot, refreshing tokens if needed. - """ - # modules.utility.list_channels(self) - - # kami_status = "OokamiKunTV is currently LIVE" if await modules.utility.is_channel_live(self) else "OokamikunTV is currently not streaming" - # globals.log(kami_status) + """ retries = 0 while True: diff --git a/cmd_common/common_commands.py b/cmd_common/common_commands.py index 55587e3..a72c595 100644 --- a/cmd_common/common_commands.py +++ b/cmd_common/common_commands.py @@ -276,14 +276,14 @@ def is_sqlite(db_conn): return 'sqlite3' in str(type(db_conn)).lower() -async def handle_quote_command(db_conn, is_discord: bool, ctx, args, get_twitch_game_for_channel=None): +async def handle_quote_command(db_conn, is_discord: bool, ctx, args, game_name=None): """ Core logic for !quote command, shared by both Discord and Twitch. - `db_conn`: your active DB connection - `is_discord`: True if this command is being called from Discord, False if from Twitch - `ctx`: the context object (discord.py ctx or twitchio context) - `args`: a list of arguments (e.g. ["add", "some quote text..."], ["remove", "3"], ["info", "3"], ["search", "foo", "bar"], or ["2"] etc.) - - `get_twitch_game_for_channel`: function(channel_name) -> str or None + - `game_name`: function(channel_name) -> str or None Behavior: 1) `!quote add some text here` @@ -322,7 +322,7 @@ async def handle_quote_command(db_conn, is_discord: bool, ctx, args, get_twitch_ return "Please provide the quote text after 'add'." try: utility.wfetl() - return await add_new_quote(db_conn, is_discord, ctx, quote_text, get_twitch_game_for_channel) + return await add_new_quote(db_conn, is_discord, ctx, quote_text, game_name) except Exception as e: globals.log(f"handle_quote_command() failed to add a new quote: {e}", "ERROR", exec_info=True) elif sub == "remove": @@ -390,7 +390,7 @@ async def handle_quote_command(db_conn, is_discord: bool, ctx, args, get_twitch_ globals.log(f"handle_quote_command() failed to retrieve a random quote: {e}", "ERROR", exec_info=True) -async def add_new_quote(db_conn, is_discord, ctx, quote_text, get_twitch_game_for_channel): +async def add_new_quote(db_conn, is_discord, ctx, quote_text, game_name: str = None): """ Inserts a new quote with UUID instead of username. """ @@ -407,9 +407,8 @@ async def add_new_quote(db_conn, is_discord, ctx, quote_text, get_twitch_game_fo user_uuid = user_data["UUID"] channel_name = "Discord" if is_discord else ctx.channel.name - game_name = None - if not is_discord and get_twitch_game_for_channel: - game_name = get_twitch_game_for_channel(channel_name) # Retrieve game if Twitch + if is_discord or not game_name: + game_name = None # Insert quote insert_sql = """ diff --git a/cmd_discord.py b/cmd_discord.py index 79068ad..1c00909 100644 --- a/cmd_discord.py +++ b/cmd_discord.py @@ -79,7 +79,7 @@ def setup(bot): is_discord=True, ctx=ctx, args=args, - get_twitch_game_for_channel=None + game_name=None ) globals.log(f"'quote' result: {result}", "DEBUG") if hasattr(result, "to_dict"): diff --git a/cmd_twitch.py b/cmd_twitch.py index d1370f6..7332a70 100644 --- a/cmd_twitch.py +++ b/cmd_twitch.py @@ -6,7 +6,7 @@ import globals from cmd_common import common_commands as cc from modules.permissions import has_permission -from modules.utility import handle_help_command, is_channel_live, command_allowed_twitch +from modules.utility import handle_help_command, is_channel_live, command_allowed_twitch, get_current_twitch_game def setup(bot, db_conn=None): """ @@ -14,13 +14,20 @@ def setup(bot, db_conn=None): We also attach the db_conn and log so the commands can use them. """ + @bot.command(name='getgame') + @command_allowed_twitch + async def cmd_getgame(ctx: commands.Context): + channel_name = ctx.channel.name + game_name = await get_current_game(bot, channel_name) + await ctx.reply(game_name) + @bot.command(name='funfact', aliases=['fun-fact']) @command_allowed_twitch async def cmd_funfact(ctx: commands.Context, *keywords: str): # Convert keywords tuple to list and pass to get_fun_fact. fact = cc.get_fun_fact(list(keywords)) # Reply to the invoking user by prefixing their name. - await ctx.reply(f"@{ctx.author.name} {fact}") + await ctx.reply(fact) @bot.command(name="greet") @command_allowed_twitch @@ -165,16 +172,12 @@ def setup(bot, db_conn=None): globals.log(f"'quote' command initiated with arguments: {args}", "DEBUG") globals.log(f"'quote' command message content: {ctx.message.content}", "DEBUG") - def get_twitch_game_for_channel(chan_name): - # Placeholder for your actual logic to fetch the current game - return "SomeGame" - result = await cc.handle_quote_command( db_conn=globals.init_db_conn, is_discord=False, ctx=ctx, args=args, - get_twitch_game_for_channel=get_twitch_game_for_channel + game_name=await get_twitch_current_game(bot, ctx.channel.name) ) globals.log(f"'quote' result: {result}", "DEBUG") diff --git a/modules/utility.py b/modules/utility.py index c1fefff..232340d 100644 --- a/modules/utility.py +++ b/modules/utility.py @@ -993,14 +993,48 @@ async def get_guild_info(bot: discord.Client, guild_id: Union[int, str]) -> dict } return info -async def is_channel_live(bot = None) -> bool: - streams = await bot.fetch_streams(user_logins=["ookamikuntv"]) if bot else [] +async def get_current_twitch_game(bot, channel_name: str) -> str: + """ + Retrieve the name of the game currently being played on the given Twitch channel. + + Parameters: + bot: A TwitchIO bot instance (or any object with a `fetch_streams` method). + channel_name (str): The Twitch channel's username. + + Returns: + str: The game name as string + """ + # Fetch stream data for the specified channel. + streams = await bot.fetch_streams(user_logins=[channel_name]) + + if streams: + # Assume the first stream is the one we're interested in. + stream = streams[0] + # Depending on your TwitchIO version, the attribute may be `game_name` or `game`. + game_name = getattr(stream, 'game_name') + game_id = getattr(stream, 'game_id') + globals.log(f"'get_current_twitch_game()' result for Twitch channel '{channel_name}': Game ID: {game_id}, Game Name: {game_name}", "DEBUG") + return game_name + + return "" + + +async def is_channel_live(bot=None, channel_name="ookamikuntv") -> bool: + """ + Returns True if the specified channel is live, otherwise False. + Defaults to "ookamikuntv" if no channel_name is provided. + """ + streams = await bot.fetch_streams(user_logins=[channel_name]) if bot else [] return bool(streams) def list_channels(self): - # Command to list connected channels. - connected_channels = ", ".join(channel.name for channel in self.connected_channels) - globals.log(f"Currently connected to {connected_channels}") + """Logs the names of all connected Twitch channels.""" + channels_list = [channel.name for channel in self.connected_channels] + connected_channels_str = ", ".join(channels_list) + num_connected_channels = len(channels_list) + globals.log( + f"Currently connected to {num_connected_channels} Twitch channel(s): {connected_channels_str}" + ) def command_allowed_twitch(func): """