Added start and end position for each track
This commit is contained in:
@@ -30,7 +30,6 @@ from function import (
|
|||||||
settings,
|
settings,
|
||||||
send,
|
send,
|
||||||
time as ctime,
|
time as ctime,
|
||||||
formatTime,
|
|
||||||
format_time,
|
format_time,
|
||||||
get_source,
|
get_source,
|
||||||
get_user,
|
get_user,
|
||||||
@@ -122,10 +121,14 @@ class Basic(commands.Cog):
|
|||||||
await send(ctx, 'connect', player.channel)
|
await send(ctx, 'connect', player.channel)
|
||||||
|
|
||||||
@commands.hybrid_command(name="play", aliases=get_aliases("play"))
|
@commands.hybrid_command(name="play", aliases=get_aliases("play"))
|
||||||
@app_commands.describe(query="Input a query or a searchable link.")
|
@app_commands.describe(
|
||||||
|
query="Input a query or a searchable link.",
|
||||||
|
start="Specify a time you would like to start, e.g. 1:00",
|
||||||
|
end="Specify a time you would like to end, e.g. 4:00"
|
||||||
|
)
|
||||||
@app_commands.autocomplete(query=play_autocomplete)
|
@app_commands.autocomplete(query=play_autocomplete)
|
||||||
@commands.dynamic_cooldown(cooldown_check, commands.BucketType.guild)
|
@commands.dynamic_cooldown(cooldown_check, commands.BucketType.guild)
|
||||||
async def play(self, ctx: commands.Context, *, query: str) -> None:
|
async def play(self, ctx: commands.Context, *, query: str, start: str = "0", end: str = "0") -> None:
|
||||||
"Loads your input and added it to the queue."
|
"Loads your input and added it to the queue."
|
||||||
player: voicelink.Player = ctx.guild.voice_client
|
player: voicelink.Player = ctx.guild.voice_client
|
||||||
if not player:
|
if not player:
|
||||||
@@ -140,10 +143,10 @@ class Basic(commands.Cog):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
if isinstance(tracks, voicelink.Playlist):
|
if isinstance(tracks, voicelink.Playlist):
|
||||||
index = await player.add_track(tracks.tracks)
|
index = await player.add_track(tracks.tracks, start_time=format_time(start), end_time=format_time(end))
|
||||||
await send(ctx, "playlistLoad", tracks.name, index)
|
await send(ctx, "playlistLoad", tracks.name, index)
|
||||||
else:
|
else:
|
||||||
position = await player.add_track(tracks[0])
|
position = await player.add_track(tracks[0], start_time=format_time(start), end_time=format_time(end))
|
||||||
texts = await get_lang(ctx.guild.id, "live", "trackLoad_pos", "trackLoad")
|
texts = await get_lang(ctx.guild.id, "live", "trackLoad_pos", "trackLoad")
|
||||||
await ctx.send((f"`{texts[0]}`" if tracks[0].is_stream else "") + (texts[1].format(tracks[0].title, tracks[0].uri, tracks[0].author, tracks[0].formatted_length, position) if position >= 1 and player.is_playing else texts[2].format(tracks[0].title, tracks[0].uri, tracks[0].author, tracks[0].formatted_length)), allowed_mentions=False)
|
await ctx.send((f"`{texts[0]}`" if tracks[0].is_stream else "") + (texts[1].format(tracks[0].title, tracks[0].uri, tracks[0].author, tracks[0].formatted_length, position) if position >= 1 and player.is_playing else texts[2].format(tracks[0].title, tracks[0].uri, tracks[0].author, tracks[0].formatted_length)), allowed_mentions=False)
|
||||||
except voicelink.QueueFull as e:
|
except voicelink.QueueFull as e:
|
||||||
@@ -250,10 +253,14 @@ class Basic(commands.Cog):
|
|||||||
await player.do_next()
|
await player.do_next()
|
||||||
|
|
||||||
@commands.hybrid_command(name="playtop", aliases=get_aliases("playtop"))
|
@commands.hybrid_command(name="playtop", aliases=get_aliases("playtop"))
|
||||||
@app_commands.describe(query="Input a query or a searchable link.")
|
@app_commands.describe(
|
||||||
|
query="Input a query or a searchable link.",
|
||||||
|
start="Specify a time you would like to start, e.g. 1:00",
|
||||||
|
end="Specify a time you would like to end, e.g. 4:00"
|
||||||
|
)
|
||||||
@app_commands.autocomplete(query=play_autocomplete)
|
@app_commands.autocomplete(query=play_autocomplete)
|
||||||
@commands.dynamic_cooldown(cooldown_check, commands.BucketType.guild)
|
@commands.dynamic_cooldown(cooldown_check, commands.BucketType.guild)
|
||||||
async def playtop(self, ctx: commands.Context, *, query: str):
|
async def playtop(self, ctx: commands.Context, *, query: str, start: str = "0", end: str = "0"):
|
||||||
"Adds a song with the given url or query on the top of the queue."
|
"Adds a song with the given url or query on the top of the queue."
|
||||||
player: voicelink.Player = ctx.guild.voice_client
|
player: voicelink.Player = ctx.guild.voice_client
|
||||||
if not player:
|
if not player:
|
||||||
@@ -268,10 +275,10 @@ class Basic(commands.Cog):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
if isinstance(tracks, voicelink.Playlist):
|
if isinstance(tracks, voicelink.Playlist):
|
||||||
index = await player.add_track(tracks.tracks, at_font=True)
|
index = await player.add_track(tracks.tracks, start_time=format_time(start), end_time=format_time(end), at_font=True)
|
||||||
await send(ctx, "playlistLoad", tracks.name, index)
|
await send(ctx, "playlistLoad", tracks.name, index)
|
||||||
else:
|
else:
|
||||||
position = await player.add_track(tracks[0], at_font=True)
|
position = await player.add_track(tracks[0], start_time=format_time(start), end_time=format_time(end), at_font=True)
|
||||||
texts = await get_lang(ctx.guild.id, "live", "trackLoad_pos", "trackLoad")
|
texts = await get_lang(ctx.guild.id, "live", "trackLoad_pos", "trackLoad")
|
||||||
await ctx.send((f"`{texts[0]}`" if tracks[0].is_stream else "") + (texts[1].format(tracks[0].title, tracks[0].uri, tracks[0].author, tracks[0].formatted_length, position) if position >= 1 and player.is_playing else texts[2].format(tracks[0].title, tracks[0].uri, tracks[0].author, tracks[0].formatted_length)), allowed_mentions=False)
|
await ctx.send((f"`{texts[0]}`" if tracks[0].is_stream else "") + (texts[1].format(tracks[0].title, tracks[0].uri, tracks[0].author, tracks[0].formatted_length, position) if position >= 1 and player.is_playing else texts[2].format(tracks[0].title, tracks[0].uri, tracks[0].author, tracks[0].formatted_length)), allowed_mentions=False)
|
||||||
|
|
||||||
@@ -283,9 +290,13 @@ class Basic(commands.Cog):
|
|||||||
await player.do_next()
|
await player.do_next()
|
||||||
|
|
||||||
@commands.hybrid_command(name="forceplay", aliases=get_aliases("forceplay"))
|
@commands.hybrid_command(name="forceplay", aliases=get_aliases("forceplay"))
|
||||||
@app_commands.describe(query="Input a query or a searchable link.")
|
@app_commands.describe(
|
||||||
|
query="Input a query or a searchable link.",
|
||||||
|
start="Specify a time you would like to start, e.g. 1:00",
|
||||||
|
end="Specify a time you would like to end, e.g. 4:00"
|
||||||
|
)
|
||||||
@commands.dynamic_cooldown(cooldown_check, commands.BucketType.guild)
|
@commands.dynamic_cooldown(cooldown_check, commands.BucketType.guild)
|
||||||
async def forceplay(self, ctx: commands.Context, query: str):
|
async def forceplay(self, ctx: commands.Context, *, query: str, start: str = "0", end: str = "0"):
|
||||||
"Enforce playback using the given URL or query."
|
"Enforce playback using the given URL or query."
|
||||||
player: voicelink.Player = ctx.guild.voice_client
|
player: voicelink.Player = ctx.guild.voice_client
|
||||||
if not player:
|
if not player:
|
||||||
@@ -300,11 +311,11 @@ class Basic(commands.Cog):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
if isinstance(tracks, voicelink.Playlist):
|
if isinstance(tracks, voicelink.Playlist):
|
||||||
index = await player.add_track(tracks.tracks, at_font=True)
|
index = await player.add_track(tracks.tracks, start_time=format_time(start), end_time=format_time(end), at_font=True)
|
||||||
await send(ctx, "playlistLoad", tracks.name, index)
|
await send(ctx, "playlistLoad", tracks.name, index)
|
||||||
else:
|
else:
|
||||||
texts = await get_lang(ctx.guild.id, "live", "trackLoad")
|
texts = await get_lang(ctx.guild.id, "live", "trackLoad")
|
||||||
await player.add_track(tracks[0], at_font=True)
|
await player.add_track(tracks[0], start_time=format_time(start), end_time=format_time(end), at_font=True)
|
||||||
await ctx.send((f"`{texts[0]}`" if tracks[0].is_stream else "") + texts[1].format(tracks[0].title, tracks[0].uri, tracks[0].author, tracks[0].formatted_length), allowed_mentions=False)
|
await ctx.send((f"`{texts[0]}`" if tracks[0].is_stream else "") + texts[1].format(tracks[0].title, tracks[0].uri, tracks[0].author, tracks[0].formatted_length), allowed_mentions=False)
|
||||||
|
|
||||||
except voicelink.QueueFull as e:
|
except voicelink.QueueFull as e:
|
||||||
@@ -404,7 +415,7 @@ class Basic(commands.Cog):
|
|||||||
return await send(ctx, "noPlayer", ephemeral=True)
|
return await send(ctx, "noPlayer", ephemeral=True)
|
||||||
|
|
||||||
if not player.node._available:
|
if not player.node._available:
|
||||||
return await send(ctx, "nnodeReconnectode")
|
return await send(ctx, "nodeReconnectode")
|
||||||
|
|
||||||
if not player.is_privileged(ctx.author):
|
if not player.is_privileged(ctx.author):
|
||||||
if ctx.author in player.previous_votes:
|
if ctx.author in player.previous_votes:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import time
|
import time
|
||||||
|
import time, re
|
||||||
import function as func
|
import function as func
|
||||||
|
|
||||||
from datetime import timezone
|
from datetime import timezone
|
||||||
@@ -8,6 +9,7 @@ from typing import List, Dict, Union, Optional
|
|||||||
from discord import User, Member, VoiceChannel
|
from discord import User, Member, VoiceChannel
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from voicelink import Player, Track, Playlist, NodePool, decode, LoopType
|
from voicelink import Player, Track, Playlist, NodePool, decode, LoopType
|
||||||
|
from addons import lyricsPlatform
|
||||||
|
|
||||||
RATELIMIT_COUNTER: Dict[int, Dict[str, float]] = {}
|
RATELIMIT_COUNTER: Dict[int, Dict[str, float]] = {}
|
||||||
SCOPES = {
|
SCOPES = {
|
||||||
@@ -560,6 +562,21 @@ async def getSettings(bot: commands.Bot, data: Dict) -> Dict:
|
|||||||
"user_id": str(user_id)
|
"user_id": str(user_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async def getLyrics(bot: commands.Bot, data: Dict) -> Dict:
|
||||||
|
title, artist, platform = data.get("title", ""), data.get("artist", ""), data.get("platform", "")
|
||||||
|
if not platform or platform not in lyricsPlatform:
|
||||||
|
platform = func.settings.lyrics_platform
|
||||||
|
|
||||||
|
song: dict[str, str] = await lyricsPlatform.get(platform)().get_lyrics(title, artist)
|
||||||
|
payload = {
|
||||||
|
"op": "getLyrics",
|
||||||
|
"user_id": data.get("user_id"),
|
||||||
|
"lyrics": {_: re.findall(r'.*\n(?:.*\n){,22}', v) for _, v in song.items()} if song else {},
|
||||||
|
"callback": data.get("callback")
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload
|
||||||
|
|
||||||
async def updateSettings(bot: commands.Bot, data: Dict) -> None:
|
async def updateSettings(bot: commands.Bot, data: Dict) -> None:
|
||||||
user_id = int(data.get("user_id"))
|
user_id = int(data.get("user_id"))
|
||||||
guild_id = int(data.get("guild_id"))
|
guild_id = int(data.get("guild_id"))
|
||||||
@@ -588,22 +605,23 @@ async def updateSettings(bot: commands.Bot, data: Dict) -> None:
|
|||||||
|
|
||||||
await func.update_settings(guild.id, {"$set": data})
|
await func.update_settings(guild.id, {"$set": data})
|
||||||
|
|
||||||
methods: Dict[str, Union[SystemMethod, PlayerMethod]] = {
|
METHODS: Dict[str, Union[SystemMethod, PlayerMethod]] = {
|
||||||
"initBot": SystemMethod(initBot, credit=0),
|
"initBot": SystemMethod(initBot, credit=0),
|
||||||
"initUser": SystemMethod(initUser, credit=0),
|
"initUser": SystemMethod(initUser, credit=0),
|
||||||
"getPlaylist": SystemMethod(getPlaylist),
|
"getPlaylist": SystemMethod(getPlaylist),
|
||||||
"updatePlaylist": SystemMethod(updatePlaylist),
|
"updatePlaylist": SystemMethod(updatePlaylist),
|
||||||
"getMutualGuilds": SystemMethod(getMutualGuilds),
|
"getMutualGuilds": SystemMethod(getMutualGuilds),
|
||||||
"getSettings": SystemMethod(getSettings),
|
"getSettings": SystemMethod(getSettings),
|
||||||
|
"getLyrics": SystemMethod(getLyrics),
|
||||||
"updateSettings": SystemMethod(updateSettings),
|
"updateSettings": SystemMethod(updateSettings),
|
||||||
"getRecommendation": SystemMethod(getRecommendation, credit=5),
|
"getRecommendation": SystemMethod(getRecommendation, credit=5),
|
||||||
"closeConnection": SystemMethod(closeConnection, credit=0),
|
"closeConnection": SystemMethod(closeConnection, credit=0),
|
||||||
|
"getTracks": SystemMethod(getTracks, credit=5),
|
||||||
"initPlayer": PlayerMethod(initPlayer),
|
"initPlayer": PlayerMethod(initPlayer),
|
||||||
"skipTo": PlayerMethod(skipTo),
|
"skipTo": PlayerMethod(skipTo),
|
||||||
"backTo": PlayerMethod(backTo),
|
"backTo": PlayerMethod(backTo),
|
||||||
"moveTrack": PlayerMethod(moveTrack),
|
"moveTrack": PlayerMethod(moveTrack),
|
||||||
"addTracks": PlayerMethod(addTracks, auto_connect=True),
|
"addTracks": PlayerMethod(addTracks, auto_connect=True),
|
||||||
"getTracks": PlayerMethod(getTracks, auto_connect=True),
|
|
||||||
"shuffleTrack": PlayerMethod(shuffleTrack, credit=3),
|
"shuffleTrack": PlayerMethod(shuffleTrack, credit=3),
|
||||||
"repeatTrack": PlayerMethod(repeatTrack),
|
"repeatTrack": PlayerMethod(repeatTrack),
|
||||||
"removeTrack": PlayerMethod(removeTrack),
|
"removeTrack": PlayerMethod(removeTrack),
|
||||||
@@ -615,7 +633,7 @@ methods: Dict[str, Union[SystemMethod, PlayerMethod]] = {
|
|||||||
|
|
||||||
async def process_methods(ipc_client, bot: commands.Bot, data: Dict) -> None:
|
async def process_methods(ipc_client, bot: commands.Bot, data: Dict) -> None:
|
||||||
op: str = data.get("op", "")
|
op: str = data.get("op", "")
|
||||||
method = methods.get(op)
|
method = METHODS.get(op)
|
||||||
if not method or not (user_id := data.get("user_id")):
|
if not method or not (user_id := data.get("user_id")):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -187,5 +187,8 @@
|
|||||||
"voicelinkOutofList": "請提供有效的歌曲索引!",
|
"voicelinkOutofList": "請提供有效的歌曲索引!",
|
||||||
"voicelinkDuplicateTrack": "抱歉,此歌曲已在隊列中。",
|
"voicelinkDuplicateTrack": "抱歉,此歌曲已在隊列中。",
|
||||||
|
|
||||||
"deocdeError": "解碼文件時出現問題!"
|
"deocdeError": "解碼文件時出現問題!",
|
||||||
|
"invalidStartTime": "無效的開始時間! 時間必須在 `00:00` 和 `{0}` 之間。",
|
||||||
|
"invalidEndTime": "無效的結束時間! 時間必須在 `00:00` 和 `{0}` 之間。",
|
||||||
|
"invalidTimeOrder": "結束時間不能小於或等於開始時間。"
|
||||||
}
|
}
|
||||||
@@ -187,5 +187,8 @@
|
|||||||
"voicelinkOutofList": "Bitte gib einen gültigen Track-Index an!",
|
"voicelinkOutofList": "Bitte gib einen gültigen Track-Index an!",
|
||||||
"voicelinkDuplicateTrack": "Entschuldigung, dieser Track ist bereits in der Warteschlange.",
|
"voicelinkDuplicateTrack": "Entschuldigung, dieser Track ist bereits in der Warteschlange.",
|
||||||
|
|
||||||
"deocdeError": "Beim Dekodieren der Datei ist etwas schief gelaufen!"
|
"deocdeError": "Beim Dekodieren der Datei ist etwas schief gelaufen!",
|
||||||
|
"invalidStartTime": "Ungültiger Startzeit! Die Zeit muss innerhalb von `00:00` und `{0}` liegen.",
|
||||||
|
"invalidEndTime": "Ungültiger Endzeit! Die Zeit muss innerhalb von `00:00` und `{0}` liegen.",
|
||||||
|
"invalidTimeOrder": "Der Endzeit darf nicht kleiner oder gleich dem Startzeit sein."
|
||||||
}
|
}
|
||||||
@@ -187,5 +187,8 @@
|
|||||||
"voicelinkOutofList": "Please provide a valid track index!",
|
"voicelinkOutofList": "Please provide a valid track index!",
|
||||||
"voicelinkDuplicateTrack": "Sorry, this track is already in the queue.",
|
"voicelinkDuplicateTrack": "Sorry, this track is already in the queue.",
|
||||||
|
|
||||||
"deocdeError": "Something went wrong while decoding the file!"
|
"deocdeError": "Something went wrong while decoding the file!",
|
||||||
|
"invalidStartTime": "Invalid start time, it must be between `00:00` and `{0}`",
|
||||||
|
"invalidEndTime": "Invalid end time, it must be between `00:00` and `{0}`",
|
||||||
|
"invalidTimeOrder": "End time cannot be less than or equal to start time"
|
||||||
}
|
}
|
||||||
@@ -187,5 +187,8 @@
|
|||||||
"voicelinkOutofList": "¡Proporcione un índice de pista válido!",
|
"voicelinkOutofList": "¡Proporcione un índice de pista válido!",
|
||||||
"voicelinkDuplicateTrack": "Lo siento, esta canción ya está en la cola.",
|
"voicelinkDuplicateTrack": "Lo siento, esta canción ya está en la cola.",
|
||||||
|
|
||||||
"deocdeError": "¡Algo salió mal al decodificar el archivo!"
|
"deocdeError": "¡Algo salió mal al decodificar el archivo!",
|
||||||
|
"invalidStartTime": "Tiempo de inicio inválido! El tiempo debe estar entre `00:00` y `{0}`.",
|
||||||
|
"invalidEndTime": "Tiempo de finalización inválido! El tiempo debe estar entre `00:00` y `{0}`.",
|
||||||
|
"invalidTimeOrder": "El tiempo final no puede ser menor o igual que el tiempo de inicio."
|
||||||
}
|
}
|
||||||
@@ -187,5 +187,8 @@
|
|||||||
"voicelinkOutofList": "有効なトラックインデックスを指定してください!",
|
"voicelinkOutofList": "有効なトラックインデックスを指定してください!",
|
||||||
"voicelinkDuplicateTrack": "申し訳ありませんが、このトラックは既にキューに存在します。",
|
"voicelinkDuplicateTrack": "申し訳ありませんが、このトラックは既にキューに存在します。",
|
||||||
|
|
||||||
"deocdeError": "ファイルのデコード中に問題が発生しました!"
|
"deocdeError": "ファイルのデコード中に問題が発生しました!",
|
||||||
|
"invalidStartTime": "無効な開始時間!時間は `00:00` と `{0}` の間に設定する必要があります。",
|
||||||
|
"invalidEndTime": "無効な終了時間!時間は `00:00` と `{0}` の間に設定する必要があります。",
|
||||||
|
"invalidTimeOrder": "終了時間は開始時間より大きくない必要があります。"
|
||||||
}
|
}
|
||||||
@@ -187,5 +187,8 @@
|
|||||||
"voicelinkOutofList": "유효한 트랙 인덱스를 제공해주세요!",
|
"voicelinkOutofList": "유효한 트랙 인덱스를 제공해주세요!",
|
||||||
"voicelinkDuplicateTrack": "죄송합니다. 이 트랙은 이미 큐에 있습니다.",
|
"voicelinkDuplicateTrack": "죄송합니다. 이 트랙은 이미 큐에 있습니다.",
|
||||||
|
|
||||||
"deocdeError": "파일 디코딩 중 문제가 발생했습니다!"
|
"deocdeError": "파일 디코딩 중 문제가 발생했습니다!",
|
||||||
|
"invalidStartTime": "효력 없는 시작 시간! 시간은 `00:00` 과 `{0}` 사이에 설정해야 합니다.",
|
||||||
|
"invalidEndTime": "효력 없는 종료 시간! 시간은 `00:00` 과 `{0}` 사이에 설정해야 합니다.",
|
||||||
|
"invalidTimeOrder": "종료 시간은 시작 시간보다 클수 있어야 합니다."
|
||||||
}
|
}
|
||||||
@@ -186,5 +186,8 @@
|
|||||||
"voicelinkOutofList": "Пожалуйста, предоставьте действительный индекс трека!",
|
"voicelinkOutofList": "Пожалуйста, предоставьте действительный индекс трека!",
|
||||||
"voicelinkDuplicateTrack": "Извините, этот трек уже есть в очереди.",
|
"voicelinkDuplicateTrack": "Извините, этот трек уже есть в очереди.",
|
||||||
|
|
||||||
"deocdeError": "Что-то пошло не так при декодировании файла!"
|
"deocdeError": "Что-то пошло не так при декодировании файла!",
|
||||||
|
"invalidStartTime": "Hевозможное время начала! Вход времени должен быть внутри `00:00` и `{0}`.",
|
||||||
|
"invalidEndTime": "Невозможное время конца! Вход времени должен быть внутри `00:00` и `{0}`.",
|
||||||
|
"invalidTimeOrder": "Время конца не может быть меньше или равно времени начала."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,5 +186,8 @@
|
|||||||
"voicelinkOutofList": "Будь ласка, надайте дійсний індекс треку!",
|
"voicelinkOutofList": "Будь ласка, надайте дійсний індекс треку!",
|
||||||
"voicelinkDuplicateTrack": "Вибачте, цей трек уже є в черзі.",
|
"voicelinkDuplicateTrack": "Вибачте, цей трек уже є в черзі.",
|
||||||
|
|
||||||
"deocdeError": "Щось пішло не так під час декодування файлу!"
|
"deocdeError": "Щось пішло не так під час декодування файлу!",
|
||||||
|
"invalidStartTime": "Недійснений час початку! Час має бути в межах `00:00` та `{0}`.",
|
||||||
|
"invalidEndTime": "Недійснений час закінчення! Час має бути в межах `00:00` та `{0}`.",
|
||||||
|
"invalidTimeOrder": "Час закінчення не може бути меншим або рівним часу початку."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import requests, zipfile, os, shutil, argparse
|
|||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
__version__ = "v2.6.9b3"
|
__version__ = "v2.6.9b4"
|
||||||
|
|
||||||
GITHUB_API_URL = "https://api.github.com/repos/ChocoMeow/Vocard/releases/latest"
|
GITHUB_API_URL = "https://api.github.com/repos/ChocoMeow/Vocard/releases/latest"
|
||||||
VOCARD_URL = "https://github.com/ChocoMeow/Vocard/archive/"
|
VOCARD_URL = "https://github.com/ChocoMeow/Vocard/archive/"
|
||||||
|
|||||||
@@ -62,7 +62,8 @@ class Track:
|
|||||||
"requester",
|
"requester",
|
||||||
"is_stream",
|
"is_stream",
|
||||||
"is_seekable",
|
"is_seekable",
|
||||||
"position"
|
"position",
|
||||||
|
"end_time"
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -102,6 +103,8 @@ class Track:
|
|||||||
self.is_seekable: bool = info.get("isSeekable", True)
|
self.is_seekable: bool = info.get("isSeekable", True)
|
||||||
self.position: int = info.get("position", 0)
|
self.position: int = info.get("position", 0)
|
||||||
|
|
||||||
|
self.end_time: Optional[int] = None
|
||||||
|
|
||||||
def __eq__(self, other) -> bool:
|
def __eq__(self, other) -> bool:
|
||||||
if not isinstance(other, Track):
|
if not isinstance(other, Track):
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -496,7 +496,7 @@ class Player(VoiceProtocol):
|
|||||||
|
|
||||||
self._node._players.pop(self.guild.id)
|
self._node._players.pop(self.guild.id)
|
||||||
await self.send(method=RequestMethod.delete)
|
await self.send(method=RequestMethod.delete)
|
||||||
|
|
||||||
async def play(
|
async def play(
|
||||||
self,
|
self,
|
||||||
track: Track,
|
track: Track,
|
||||||
@@ -511,41 +511,58 @@ class Player(VoiceProtocol):
|
|||||||
|
|
||||||
if track.spotify:
|
if track.spotify:
|
||||||
if not track.original:
|
if not track.original:
|
||||||
search: Track = (await self._node.get_tracks(
|
search_results = await self._node.get_tracks(f"ytmsearch:{track.author} - {track.title}", requester=track.requester)
|
||||||
f"ytsearch:{track.author} - {track.title}",
|
if not search_results:
|
||||||
requester=track.requester
|
raise TrackLoadError("Can't find a playable source!")
|
||||||
))
|
track.original = search_results[0]
|
||||||
|
|
||||||
if not search:
|
|
||||||
raise TrackLoadError("Can't not found a playable source!")
|
|
||||||
|
|
||||||
track.original = search[0]
|
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"encodedTrack": track.original.track_id if track.original else track.track_id,
|
"encodedTrack": track.original.track_id if track.original else track.track_id,
|
||||||
"position": str(start if start else track.position),
|
"position": str(start if start else track.position)
|
||||||
"endTime": str(end if end else track.original.length)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if end or track.end_time:
|
||||||
|
data["endTime"] = str(end if end else track.end_time)
|
||||||
|
|
||||||
await self.send(method=RequestMethod.patch, query=f"noReplace={ignore_if_playing}", data=data)
|
await self.send(method=RequestMethod.patch, query=f"noReplace={ignore_if_playing}", data=data)
|
||||||
|
|
||||||
self._current = track
|
self._current = track
|
||||||
|
|
||||||
if self.volume != 100:
|
if self.volume != 100:
|
||||||
await self.set_volume(self.volume)
|
await self.set_volume(self.volume)
|
||||||
|
|
||||||
self._logger.debug(f"Player in {self.guild.name}({self.guild.id}) playing {track.title} from uri {track.uri} with a length of {track.length}")
|
self._logger.debug(f"Player in {self.guild.name}({self.guild.id}) playing {track.title} from uri {track.uri} with a length of {track.length}")
|
||||||
return self._current
|
return self._current
|
||||||
|
|
||||||
async def add_track(self, raw_tracks: Union[Track, List[Track]], *, at_font: bool = False, duplicate: bool = True) -> int:
|
def _validate_time(self, track: Track, start_time: int, end_time: int) -> None:
|
||||||
|
if start_time or end_time:
|
||||||
|
if not end_time:
|
||||||
|
end_time = track.length
|
||||||
|
|
||||||
|
if start_time >= end_time:
|
||||||
|
raise VoicelinkException(self.get_msg("invalidStartTime"))
|
||||||
|
|
||||||
|
track_length = track.length
|
||||||
|
if not 0 <= start_time <= track_length:
|
||||||
|
raise VoicelinkException(self.get_msg("invalidStartTime", func.time(track_length)))
|
||||||
|
if not 0 <= end_time <= track_length:
|
||||||
|
raise VoicelinkException(self.get_msg("invalidEndTime", func.time(track_length)))
|
||||||
|
|
||||||
|
track.position = start_time
|
||||||
|
track.end_time = end_time
|
||||||
|
|
||||||
|
async def add_track(self, raw_tracks: Union[Track, List[Track]], *, start_time: int = 0, end_time: int = 0, at_front: bool = False, duplicate: bool = True) -> int:
|
||||||
tracks: List[Track] = []
|
tracks: List[Track] = []
|
||||||
_duplicate_tracks = [] if self.queue._allow_duplicate and duplicate else [track.uri for track in self.queue._queue]
|
_duplicate_tracks = [] if self.queue._allow_duplicate and duplicate else [track.uri for track in self.queue._queue]
|
||||||
raw_tracks = raw_tracks[0] if isinstance(raw_tracks, List) and len(raw_tracks) == 1 else raw_tracks
|
raw_tracks = raw_tracks[0] if isinstance(raw_tracks, List) and len(raw_tracks) == 1 else raw_tracks
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if (is_list := isinstance(raw_tracks, List)):
|
if (is_list := isinstance(raw_tracks, List)):
|
||||||
for track in raw_tracks:
|
for track in raw_tracks:
|
||||||
if track.uri in _duplicate_tracks:
|
if track.uri in _duplicate_tracks:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
self._validate_time(track, start_time, end_time)
|
||||||
self.queue.put_at_front(track) if at_front else self.queue.put(track)
|
self.queue.put_at_front(track) if at_front else self.queue.put(track)
|
||||||
tracks.append(track)
|
tracks.append(track)
|
||||||
_duplicate_tracks.append(track.uri)
|
_duplicate_tracks.append(track.uri)
|
||||||
@@ -553,7 +570,8 @@ class Player(VoiceProtocol):
|
|||||||
if raw_tracks.uri in _duplicate_tracks:
|
if raw_tracks.uri in _duplicate_tracks:
|
||||||
raise DuplicateTrack(self.get_msg("voicelinkDuplicateTrack"))
|
raise DuplicateTrack(self.get_msg("voicelinkDuplicateTrack"))
|
||||||
|
|
||||||
position = self.queue.put_at_front(raw_tracks) if at_font else self.queue.put(raw_tracks)
|
self._validate_time(raw_tracks, start_time, end_time)
|
||||||
|
position = self.queue.put_at_front(raw_tracks) if at_front else self.queue.put(raw_tracks)
|
||||||
tracks.append(raw_tracks)
|
tracks.append(raw_tracks)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
Reference in New Issue
Block a user