Compare commits

..

4 Commits

Author SHA1 Message Date
8ef4c85bd8
refactor: use aiohttp for requests 2025-01-22 14:49:29 -05:00
640e750e3d
feat: add sponsorblock integration
Add the -S option to the fast forward command.
2025-01-22 14:47:00 -05:00
3ca58a4c19
refactor(commands/voice/queue): allow query with spaces 2025-01-19 17:53:58 -05:00
a8d69e079d
refactor: allow reloading yt_dlp 2025-01-19 04:44:00 -05:00
6 changed files with 65 additions and 8 deletions

View File

@ -1,7 +1,7 @@
import re import re
import aiohttp
import disnake import disnake
import requests
import arguments import arguments
import commands import commands
@ -31,8 +31,9 @@ async def lookup(message):
return return
if args.application: if args.application:
response = requests.get( session = aiohttp.ClientSession()
f"https://discord.com/api/v9/applications/{args.id}/rpc" response = await (
await session.get(f"https://discord.com/api/v9/applications/{args.id}/rpc")
).json() ).json()
if "code" in response.keys(): if "code" in response.keys():
await utils.reply(message, "application not found!") await utils.reply(message, "application not found!")

View File

@ -2,6 +2,7 @@ import disnake_paginator
import arguments import arguments
import commands import commands
import sponsorblock
import utils import utils
from constants import EMBED_COLOR from constants import EMBED_COLOR
from state import players from state import players
@ -89,11 +90,19 @@ 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], "fast forward audio playback") parser = arguments.ArgumentParser(tokens[0], "fast forward audio playback")
parser.add_argument( group = parser.add_mutually_exclusive_group(required=True)
"seconds", group.add_argument(
"-s",
"--seconds",
type=lambda v: arguments.range_type(v, min=0, max=300), type=lambda v: arguments.range_type(v, min=0, max=300),
help="the amount of seconds to fast forward", help="the amount of seconds to fast forward",
) )
group.add_argument(
"-S",
"--sponsorblock",
action="store_true",
help="go to the end of the current sponsorblock segment",
)
if not (args := await parser.parse_args(message, tokens)): if not (args := await parser.parse_args(message, tokens)):
return return
@ -104,8 +113,28 @@ async def fast_forward(message):
await utils.reply(message, "nothing is playing!") await utils.reply(message, "nothing is playing!")
return return
seconds = args.seconds
if args.sponsorblock:
video = await sponsorblock.get_segments(
players[message.guild.id].current.player.id
)
if not video:
await utils.reply(
message, "no sponsorblock segments were found for this video!"
)
return
progress = message.guild.voice_client.source.original.progress
for segment in video["segments"]:
begin, end = map(float, segment["segment"])
if progress >= begin and progress < end:
seconds = end - message.guild.voice_client.source.original.progress
if not seconds:
await utils.reply(message, "no sponsorblock segment is currently playing!")
return
message.guild.voice_client.pause() message.guild.voice_client.pause()
message.guild.voice_client.source.original.fast_forward(args.seconds) message.guild.voice_client.source.original.fast_forward(seconds)
message.guild.voice_client.resume() message.guild.voice_client.resume()
await utils.add_check_reaction(message) await utils.add_check_reaction(message)

View File

@ -22,7 +22,7 @@ async def queue_or_play(message, edited=False):
parser = arguments.ArgumentParser( parser = arguments.ArgumentParser(
tokens[0], "queue a song, list the queue, or resume playback" tokens[0], "queue a song, list the queue, or resume playback"
) )
parser.add_argument("query", nargs="?", help="yt-dlp URL or query to get song") parser.add_argument("query", nargs="*", help="yt-dlp URL or query to get song")
parser.add_argument( parser.add_argument(
"-v", "-v",
"--volume", "--volume",
@ -155,7 +155,7 @@ async def queue_or_play(message, edited=False):
try: try:
async with message.channel.typing(): async with message.channel.typing():
player = await youtubedl.YTDLSource.from_url( player = await youtubedl.YTDLSource.from_url(
query, loop=client.loop, stream=True " ".join(query), loop=client.loop, stream=True
) )
player.volume = float(args.volume) / 100.0 player.volume = float(args.volume) / 100.0
except Exception as e: except Exception as e:

View File

@ -36,10 +36,13 @@ RELOADABLE_MODULES = [
"events", "events",
"extra", "extra",
"fun", "fun",
"sponsorblock",
"tasks", "tasks",
"utils", "utils",
"voice", "voice",
"youtubedl", "youtubedl",
"yt_dlp",
"yt_dlp.version",
] ]
PUBLIC_FLAGS = { PUBLIC_FLAGS = {
1: "Discord Employee", 1: "Discord Employee",

23
sponsorblock.py Normal file
View File

@ -0,0 +1,23 @@
import hashlib
import aiohttp
from state import sponsorblock_cache
async def get_segments(videoId: str):
if videoId in sponsorblock_cache:
return sponsorblock_cache[videoId]
hashPrefix = hashlib.sha256(videoId.encode()).hexdigest()[:4]
session = aiohttp.ClientSession()
response = await session.get(
f'https://sponsor.ajay.app/api/skipSegments/{hashPrefix}?categories=["music_offtopic"]'
)
if response.status == 200 and (
results := list(
filter(lambda v: videoId == v["videoID"], await response.json())
)
):
sponsorblock_cache[videoId] = results[0]
return results[0]

View File

@ -15,4 +15,5 @@ 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)
start_time = time.time() start_time = time.time()