Files
discord-havoc/cogs/radio.py

155 lines
5.5 KiB
Python
Raw Normal View History

2025-02-13 14:51:35 -05:00
import logging
import traceback
import asyncio
2025-02-14 07:10:09 -05:00
from typing import Optional
2025-02-13 14:51:35 -05:00
from discord.ext import bridge, commands, tasks
from util.radio_util import get_now_playing, skip
2025-02-13 14:51:35 -05:00
import discord
2025-02-15 08:36:45 -05:00
from disc_havoc import Havoc
2025-02-13 14:51:35 -05:00
2025-04-17 14:35:56 -04:00
2025-02-13 14:51:35 -05:00
class Radio(commands.Cog):
"""Radio Cog for Havoc"""
2025-04-17 14:35:56 -04:00
2025-02-15 08:36:45 -05:00
def __init__(self, bot: Havoc) -> None:
self.bot: Havoc = bot
self.channels: dict[str, tuple] = {
2025-04-17 14:35:56 -04:00
"sfm": (
1145182936002482196,
1221615558492029050,
), # Tuple: Guild Id, Chan Id
}
2025-03-10 09:59:42 -04:00
self.STREAM_URL: str = "https://stream.codey.lol/sfm.ogg"
2025-02-14 07:10:09 -05:00
self.LAST_NP_TRACK: Optional[str] = None
2025-02-13 14:51:35 -05:00
try:
self.radio_state_loop.cancel()
except Exception as e:
2025-04-17 14:35:56 -04:00
logging.debug("Failed to cancel radio_state_loop: %s", str(e))
2025-02-13 14:51:35 -05:00
@commands.Cog.listener()
async def on_ready(self) -> None:
"""Run on Bot Ready"""
await self.radio_init()
2025-04-17 14:35:56 -04:00
def is_radio_chan(): # type: ignore
2025-02-13 14:51:35 -05:00
"""Check if channel is radio chan"""
2025-04-17 14:35:56 -04:00
2025-02-13 14:51:35 -05:00
def predicate(ctx):
try:
return ctx.channel.id == 1221615558492029050
2025-04-26 21:59:46 -04:00
except Exception as e:
logging.debug("Exception: %s", str(e))
2025-02-13 14:51:35 -05:00
traceback.print_exc()
return False
2025-04-17 14:35:56 -04:00
return commands.check(predicate)
# @bridge.bridge_command()
# @commands.is_owner()
# async def reinitradio(self, ctx) -> None:
# """
# Reinitialize serious.FM
# """
# loop: discord.asyncio.AbstractEventLoop = self.bot.loop
# loop.create_task(self.radio_init())
# await ctx.respond("Done!", ephemeral=True)
# async def radio_init(self) -> None:
# """Init Radio"""
# try:
# (radio_guild, radio_chan) = self.channels["sfm"]
# guild: Optional[discord.Guild] = self.bot.get_guild(radio_guild)
# if not guild:
# return
# channel = guild.get_channel(radio_chan)
# if not isinstance(channel, discord.VoiceChannel):
# return
# if not self.bot.voice_clients:
# await channel.connect()
# try:
# try:
# self.radio_state_loop.cancel()
# except Exception as e:
# logging.debug("Failed to cancel radio_state_loop: %s", str(e))
# self.radio_state_loop.start()
# logging.info("radio_state_loop task started!")
# except Exception as e:
# logging.critical("Could not start task... Exception: %s", str(e))
# traceback.print_exc()
# except Exception as e:
# logging.debug("Exception: %s", str(e))
# traceback.print_exc()
# return
2025-04-17 14:35:56 -04:00
2025-02-13 14:51:35 -05:00
async def radio_init(self) -> None:
try:
self.radio_state_loop.start()
2025-04-26 21:59:46 -04:00
except Exception as e:
logging.critical("Failed to start radio state loop: %s", str(e))
2025-02-13 14:51:35 -05:00
traceback.print_exc()
2025-04-17 14:35:56 -04:00
2025-02-14 07:10:09 -05:00
@tasks.loop(seconds=5.0)
2025-02-13 14:51:35 -05:00
async def radio_state_loop(self) -> None:
"""Radio State Loop"""
try:
# (radio_guild, radio_chan) = self.channels["sfm"]
# try:
# vc: discord.VoiceProtocol = self.bot.voice_clients[-1]
# except Exception as e:
# logging.debug(
# "No voice client, establishing new VC connection... (Exception: %s)",
# str(e),
# )
# guild: Optional[discord.Guild] = self.bot.get_guild(radio_guild)
# if not guild:
# return
# channel = guild.get_channel(radio_chan)
# if not isinstance(channel, discord.VoiceChannel):
# return
# await channel.connect()
# vc = self.bot.voice_clients[-1]
# if not vc.is_playing() or vc.is_paused(): # type: ignore
# """
# Mypy does not seem aware of the is_playing, play, and is_paused methods,
# but they exist.
# """
# logging.info("Detected VC not playing... playing!")
# source: discord.FFmpegAudio = discord.FFmpegOpusAudio(self.STREAM_URL)
# vc.play( # type: ignore
# source,
# after=lambda e: logging.info("Error: %s", e) if e else None,
# )
2025-04-17 14:35:56 -04:00
# Get Now Playing
2025-04-10 19:52:29 -04:00
np_track: Optional[str] = await get_now_playing()
if not self.LAST_NP_TRACK or (np_track and not self.LAST_NP_TRACK == np_track):
logging.critical("Setting: %s", np_track)
2025-04-10 19:52:29 -04:00
self.LAST_NP_TRACK = np_track
2025-04-17 14:35:56 -04:00
await self.bot.change_presence(
activity=discord.Activity(
type=discord.ActivityType.listening, name=np_track
)
)
2025-04-26 21:59:46 -04:00
except Exception as e:
logging.debug("Exception: %s", str(e))
2025-02-13 14:51:35 -05:00
traceback.print_exc()
2025-04-17 14:35:56 -04:00
@bridge.bridge_command()
@commands.is_owner()
async def skip(self, ctx) -> None:
"""
Skip - Convenience Command
"""
2025-04-17 14:35:56 -04:00
await skip()
return await ctx.respond("OK", ephemeral=True)
2025-04-17 14:35:56 -04:00
2025-02-13 14:51:35 -05:00
def cog_unload(self) -> None:
2025-04-17 14:35:56 -04:00
"""Run on Cog Unload"""
2025-02-13 14:51:35 -05:00
self.radio_state_loop.cancel()
2025-04-17 14:35:56 -04:00
2025-02-13 14:51:35 -05:00
def setup(bot) -> None:
"""Run on Cog Load"""
2025-04-17 14:35:56 -04:00
bot.add_cog(Radio(bot))