Compare commits

...

13 Commits

10 changed files with 58 additions and 43 deletions

View File

@@ -21,8 +21,11 @@ class Song:
format_duration(self.player.duration) if self.player.duration else "stream" format_duration(self.player.duration) if self.player.duration else "stream"
) )
if multiline: if multiline:
queue_time = (
self.trigger_message.edited_at or self.trigger_message.created_at
)
return f"{title}\n**duration:** {duration}" + ( return f"{title}\n**duration:** {duration}" + (
f", **queued by:** <@{self.trigger_message.author.id}>" f", **queued by:** <@{self.trigger_message.author.id}> <t:{round(queue_time.timestamp())}:R>"
if show_queuer if show_queuer
else "" else ""
) )
@@ -48,18 +51,20 @@ class Song:
else "[**stream**]" else "[**stream**]"
) )
), ),
timestamp=self.trigger_message.edited_at or self.trigger_message.created_at,
) )
uploader_value = None
if self.player.uploader_url: if self.player.uploader_url:
embed.add_field( if self.player.uploader:
name="Uploader", uploader_value = f"[{self.player.uploader}]({self.player.uploader_url})"
value=f"[{self.player.uploader}]({self.player.uploader_url})", else:
) uploader_value = self.player.uploader_url
elif self.player.uploader: elif self.player.uploader:
embed.add_field( uploader_value = self.player.uploader
name="Uploader",
value=self.player.uploader, if uploader_value:
) embed.add_field(name="Uploader", value=uploader_value)
if self.player.like_count: if self.player.like_count:
embed.add_field(name="Likes", value=f"{self.player.like_count:,}") embed.add_field(name="Likes", value=f"{self.player.like_count:,}")
if self.player.view_count: if self.player.view_count:
@@ -73,7 +78,7 @@ class Song:
embed.set_image(self.player.thumbnail_url) embed.set_image(self.player.thumbnail_url)
embed.set_footer( embed.set_footer(
text=f"queued by {self.trigger_message.author.name}", text=f"Queued by {self.trigger_message.author.name}",
icon_url=( icon_url=(
self.trigger_message.author.avatar.url self.trigger_message.author.avatar.url
if self.trigger_message.author.avatar if self.trigger_message.author.avatar

View File

@@ -165,7 +165,7 @@ async def clear(message):
tokens = commands.tokenize(message.content) tokens = commands.tokenize(message.content)
parser = arguments.ArgumentParser( parser = arguments.ArgumentParser(
tokens[0], tokens[0],
"bulk delete messages in the current channel matching certain criteria", "bulk delete messages in the current channel matching specified criteria",
) )
parser.add_argument( parser.add_argument(
"count", "count",

View File

@@ -90,13 +90,13 @@ async def pause(message):
async def fast_forward(message): async def fast_forward(message):
tokens = commands.tokenize(message.content) tokens = commands.tokenize(message.content)
parser = arguments.ArgumentParser(tokens[0], "skip current sponsorblock segment") parser = arguments.ArgumentParser(tokens[0], "skip the current sponsorblock segment")
parser.add_argument( parser.add_argument(
"-s", "-s",
"--seconds", "--seconds",
nargs="?", nargs="?",
type=lambda v: arguments.range_type(v, lower=0, upper=300), type=lambda v: arguments.range_type(v, lower=0, upper=300),
help="the amount of seconds to fast forward instead", help="the number of seconds to fast forward instead",
) )
if not (args := await parser.parse_args(message, tokens)): if not (args := await parser.parse_args(message, tokens)):
return return

View File

@@ -8,16 +8,13 @@ import audio
import commands import commands
import utils import utils
from constants import EMBED_COLOR from constants import EMBED_COLOR
from state import client, players from state import client, players, trusted_users
from .playback import resume from .playback import resume
from .utils import command_allowed, ensure_joined, play_next from .utils import command_allowed, ensure_joined, play_next
async def queue_or_play(message, edited=False): async def queue_or_play(message, edited=False):
if message.guild.id not in players:
players[message.guild.id] = audio.queue.Player()
tokens = commands.tokenize(message.content) tokens = commands.tokenize(message.content)
parser = arguments.ArgumentParser( parser = arguments.ArgumentParser(
tokens[0], tokens[0],
@@ -81,19 +78,23 @@ async def queue_or_play(message, edited=False):
elif not command_allowed(message): elif not command_allowed(message):
return return
if message.guild.id not in players:
players[message.guild.id] = audio.queue.Player()
if edited: if edited:
found = None found = next(
for queued in players[message.guild.id].queue: filter(
if queued.trigger_message.id == message.id: lambda queued: queued.trigger_message.id == message.id,
found = queued players[message.guild.id].queue,
break ),
None,
)
if found: if found:
players[message.guild.id].queue.remove(found) players[message.guild.id].queue.remove(found)
if args.clear: if args.clear:
players[message.guild.id].queue.clear() players[message.guild.id].queue.clear()
await utils.add_check_reaction(message) await utils.add_check_reaction(message)
return
elif indices := args.remove_index: elif indices := args.remove_index:
targets = [] targets = []
for i in indices: for i in indices:
@@ -114,15 +115,15 @@ async def queue_or_play(message, edited=False):
f"removed **{len(targets)}** queued {'song' if len(targets) == 1 else 'songs'}", f"removed **{len(targets)}** queued {'song' if len(targets) == 1 else 'songs'}",
) )
elif args.remove_title or args.remove_queuer: elif args.remove_title or args.remove_queuer:
targets = [] targets = set()
for queued in players[message.guild.id].queue: for queued in players[message.guild.id].queue:
if t := args.remove_title: if t := args.remove_title:
if t in queued.player.title: if t in queued.player.title:
targets.append(queued) targets.add(queued)
continue
if q := args.remove_queuer: if q := args.remove_queuer:
if q == queued.trigger_message.author.id: if q == queued.trigger_message.author.id:
targets.append(queued) targets.add(queued)
targets = list(targets)
if not args.match_multiple: if not args.match_multiple:
targets = targets[:1] targets = targets[:1]
@@ -146,6 +147,7 @@ async def queue_or_play(message, edited=False):
) )
>= 5 >= 5
and not len(message.guild.voice_client.channel.members) == 2 and not len(message.guild.voice_client.channel.members) == 2
and message.author.id not in trusted_users
): ):
await utils.reply( await utils.reply(
message, message,
@@ -239,7 +241,7 @@ async def queue_or_play(message, edited=False):
async def skip(message): async def skip(message):
tokens = commands.tokenize(message.content) tokens = commands.tokenize(message.content)
parser = arguments.ArgumentParser(tokens[0], "skip the currently playing song") parser = arguments.ArgumentParser(tokens[0], "skip the song currently playing")
parser.add_argument( parser.add_argument(
"-n", "-n",
"--next", "--next",

27
core.py
View File

@@ -3,6 +3,7 @@ import contextlib
import importlib import importlib
import inspect import inspect
import io import io
import signal
import textwrap import textwrap
import time import time
import traceback import traceback
@@ -59,17 +60,8 @@ async def on_message(message, edited=False):
match matched: match matched:
case C.RELOAD if message.author.id in OWNERS: case C.RELOAD if message.author.id in OWNERS:
reloaded_modules = set()
start = time.time() start = time.time()
reloaded_modules = reload()
rreload(reloaded_modules, __import__("core"))
rreload(reloaded_modules, __import__("extra"))
for module in filter(
lambda v: inspect.ismodule(v) and v.__name__ in RELOADABLE_MODULES,
globals().values(),
):
rreload(reloaded_modules, module)
end = time.time() end = time.time()
debug( debug(
f"reloaded {len(reloaded_modules)} modules in {round(end - start, 2)}s", f"reloaded {len(reloaded_modules)} modules in {round(end - start, 2)}s",
@@ -186,3 +178,18 @@ def rreload(reloaded_modules, module):
if "__reload_module__" in dir(module): if "__reload_module__" in dir(module):
module.__reload_module__() module.__reload_module__()
def reload(*_):
reloaded_modules = set()
rreload(reloaded_modules, __import__("core"))
rreload(reloaded_modules, __import__("extra"))
for module in filter(
lambda v: inspect.ismodule(v) and v.__name__ in RELOADABLE_MODULES,
globals().values(),
):
rreload(reloaded_modules, module)
return reloaded_modules
signal.signal(signal.SIGUSR1, reload)

View File

@@ -7,7 +7,7 @@ from state import client
if __name__ == "__main__": if __name__ == "__main__":
logging.basicConfig( logging.basicConfig(
format=( format=(
"%(asctime)s %(levelname)s %(name):%(module)s %(message)s" "%(asctime)s %(levelname)s %(name)s:%(module)s %(message)s"
if __debug__ if __debug__
else "%(asctime)s %(levelname)s %(message)s" else "%(asctime)s %(levelname)s %(message)s"
), ),

View File

@@ -5,4 +5,4 @@ disnake_paginator
psutil psutil
PyNaCl PyNaCl
youtube_transcript_api youtube_transcript_api
yt-dlp yt-dlp[default] @ https://github.com/yt-dlp/yt-dlp/archive/master.tar.gz

View File

@@ -15,5 +15,6 @@ idle_tracker = {"is_idle": False, "last_used": time.time()}
kill = {"transcript": False} kill = {"transcript": False}
message_responses = LimitedSizeDict() message_responses = LimitedSizeDict()
players = {} players = {}
sponsorblock_cache = LimitedSizeDict(size_limit=100) sponsorblock_cache = LimitedSizeDict()
start_time = time.time() start_time = time.time()
trusted_users = []

View File

@@ -11,7 +11,7 @@ async def cleanup():
debug("spawned cleanup thread") debug("spawned cleanup thread")
while True: while True:
await asyncio.sleep(3600 * 12) await asyncio.sleep(3600)
targets = [] targets = []
for guild_id, player in players.items(): for guild_id, player in players.items():

View File

@@ -50,7 +50,7 @@ def filter_secrets(text: str, secrets=SECRETS) -> str:
class LimitedSizeDict(OrderedDict): class LimitedSizeDict(OrderedDict):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.size_limit = kwargs.pop("size_limit", 1000) self.size_limit = kwargs.pop("size_limit", 100)
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self._check_size_limit() self._check_size_limit()