2020-03-03 11:00:27 -08:00
import aiohttp
import discord
import lavalink
import struct
import re
from redbot . core import commands
class IcyParser ( commands . Cog ) :
2020-09-06 23:48:49 -07:00
""" Icyparser/Shoutcast stream reader. """
2020-08-26 17:57:43 +01:00
async def red_delete_data_for_user ( self , * * kwargs ) :
""" Nothing to delete """
return
2020-03-03 11:00:27 -08:00
def __init__ ( self , bot ) :
self . bot = bot
self . session = aiohttp . ClientSession ( )
async def _icyparser ( self , url : str ) :
try :
async with self . session . get ( url , headers = { " Icy-MetaData " : " 1 " } ) as resp :
metaint = int ( resp . headers [ " icy-metaint " ] )
for _ in range ( 5 ) :
await resp . content . readexactly ( metaint )
metadata_length = struct . unpack ( " B " , await resp . content . readexactly ( 1 ) ) [ 0 ] * 16
metadata = await resp . content . readexactly ( metadata_length )
m = re . search ( br " StreamTitle= ' ([^ ' ]*) ' ; " , metadata . rstrip ( b " \0 " ) )
if m :
title = m . group ( 1 )
if title :
title = title . decode ( " utf-8 " , errors = " replace " )
else :
title = None
image = False
t = re . search ( br " StreamUrl= ' ([^ ' ]*) ' ; " , metadata . rstrip ( b " \0 " ) )
if t :
streamurl = t . group ( 1 )
if streamurl :
streamurl = streamurl . decode ( " utf-8 " , errors = " replace " )
image_ext = [ " webp " , " png " , " jpg " , " gif " ]
if streamurl . split ( " . " ) [ - 1 ] in image_ext :
image = True
else :
streamurl = None
return title , streamurl , image
except ( KeyError , aiohttp . client_exceptions . ClientConnectionError ) :
return None , None , None
def cog_unload ( self ) :
self . bot . loop . create_task ( self . session . close ( ) )
2020-09-09 10:19:00 -07:00
@commands.guild_only ( )
2020-03-03 11:00:27 -08:00
@commands.command ( aliases = [ " icynp " ] )
2020-03-11 09:19:16 -07:00
async def icyparser ( self , ctx , url = None ) :
""" Show Icecast or Shoutcast stream information, if any. """
if not url :
audiocog = self . bot . get_cog ( " Audio " )
if not audiocog :
return await ctx . send ( " Audio is not loaded. " )
try :
player = lavalink . get_player ( ctx . guild . id )
except KeyError :
return await ctx . send ( " The bot is not playing any music. " )
if not player . current :
return await ctx . send ( " The bot is not playing any music. " )
if not player . current . is_stream :
return await ctx . send ( " The bot is not playing a stream. " )
icy = await self . _icyparser ( player . current . uri )
else :
icy = await self . _icyparser ( url )
2020-03-03 11:00:27 -08:00
if not icy [ 0 ] :
return await ctx . send (
2020-03-11 09:19:16 -07:00
f " Can ' t read the stream information for < { player . current . uri if not url else url } >, it may not be an Icecast or Shoutcast radio station or there may be no stream information available. "
2020-03-03 11:00:27 -08:00
)
2020-03-11 09:19:16 -07:00
song = f " **[ { icy [ 0 ] } ]( { player . current . uri if not url else url } )** \n "
2020-08-26 17:57:43 +01:00
embed = discord . Embed ( colour = await ctx . embed_colour ( ) , title = " Now Playing " , description = song )
2020-03-03 11:00:27 -08:00
if icy [ 2 ] :
embed . set_thumbnail ( url = icy [ 1 ] )
await ctx . send ( embed = embed )