108 lines
3.7 KiB
Python
108 lines
3.7 KiB
Python
|
#!/usr/bin/env python3.12
|
||
|
# pylint: disable=bare-except, broad-exception-caught, invalid-name
|
||
|
|
||
|
import logging
|
||
|
import traceback
|
||
|
from discord.ext import bridge, commands, tasks
|
||
|
import discord
|
||
|
|
||
|
class Radio(commands.Cog):
|
||
|
"""Radio Cog for Havoc"""
|
||
|
def __init__(self, bot: discord.Bot) -> None:
|
||
|
self.bot: discord.Bot = bot
|
||
|
self.channels: dict[tuple] = {
|
||
|
'sfm': (1145182936002482196, 1221615558492029050), # Tuple: Guild Id, Chan Id
|
||
|
}
|
||
|
self.STREAM_URL: str = "https://relay.sfm.codey.lol/aces.ogg"
|
||
|
|
||
|
try:
|
||
|
self.radio_state_loop.cancel()
|
||
|
except Exception as e:
|
||
|
logging.debug("Failed to cancel radio_state_loop: %s",
|
||
|
str(e))
|
||
|
|
||
|
@commands.Cog.listener()
|
||
|
async def on_ready(self) -> None:
|
||
|
"""Run on Bot Ready"""
|
||
|
await self.radio_init()
|
||
|
|
||
|
def is_radio_chan(): # pylint: disable=no-method-argument
|
||
|
"""Check if channel is radio chan"""
|
||
|
def predicate(ctx):
|
||
|
try:
|
||
|
return ctx.channel.id == 1221615558492029050
|
||
|
except:
|
||
|
traceback.print_exc()
|
||
|
return False
|
||
|
return commands.check(predicate)
|
||
|
|
||
|
@bridge.bridge_command()
|
||
|
@commands.is_owner()
|
||
|
async def reinitradio(self, ctx) -> None:
|
||
|
"""
|
||
|
Reinitialize serious.FM
|
||
|
Args:
|
||
|
ctx (Any): Discord context
|
||
|
Returns:
|
||
|
None
|
||
|
"""
|
||
|
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']
|
||
|
channel: discord.TextChannel = self.bot.get_guild(radio_guild)\
|
||
|
.get_channel(radio_chan)
|
||
|
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:
|
||
|
logging.critical("Could not start task...")
|
||
|
traceback.print_exc()
|
||
|
except:
|
||
|
traceback.print_exc()
|
||
|
return
|
||
|
|
||
|
@tasks.loop(seconds=2.0)
|
||
|
async def radio_state_loop(self) -> None:
|
||
|
"""Radio State Loop"""
|
||
|
try:
|
||
|
(radio_guild, radio_chan) = self.channels['sfm']
|
||
|
try:
|
||
|
vc: discord.VoiceClient = self.bot.voice_clients[-1]
|
||
|
except:
|
||
|
logging.debug("No voice client, establishing new VC connection...")
|
||
|
channel = self.bot.get_guild(radio_guild)\
|
||
|
.get_channel(radio_chan)
|
||
|
await channel.connect()
|
||
|
vc = self.bot.voice_clients[-1]
|
||
|
if not(vc.is_playing()) or vc.is_paused():
|
||
|
logging.info("Detected VC not playing... playing!")
|
||
|
source = discord.FFmpegOpusAudio(self.STREAM_URL,
|
||
|
before_options="-timeout 3000000")
|
||
|
vc.play(source, after=lambda e: logging.info("Error: %s", e)\
|
||
|
if e else None)
|
||
|
except:
|
||
|
traceback.print_exc()
|
||
|
|
||
|
# pylint: enable=superfluous-parens
|
||
|
|
||
|
def cog_unload(self) -> None:
|
||
|
"""Run on Cog Unload"""
|
||
|
self.radio_state_loop.cancel()
|
||
|
|
||
|
def setup(bot) -> None:
|
||
|
"""Run on Cog Load"""
|
||
|
bot.add_cog(Radio(bot))
|