Translate yt-dlp errors and drop the redundant prefix hint
Errors reached people as raw tool output: "Unsupported URL: https://...%D0%B0%D1%83..." says nothing to whoever pasted a link. The common cases now map to plain descriptions with the next step where there is one (age gate and bot checks point at YTDLP_COOKIES, a stale extractor at updating yt-dlp), URLs are decoded, and anything unrecognised still falls through verbatim. The panel's prefix hint is gone now that the source picker does the same job visibly; prefixes keep working and stay documented for chat. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
971fd65b1f
commit
ffcf88efb7
+29
-1
@@ -103,13 +103,41 @@ function runYtDlp(args: string[], timeoutMs = 45_000): Promise<YtDlpRun> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** yt-dlp messages people actually hit, in words that suggest what to do. */
|
||||||
|
const ERROR_PATTERNS: Array<[RegExp, string]> = [
|
||||||
|
[/unsupported url/i, "Не понимаю эту ссылку — проверьте, что она открывается в браузере"],
|
||||||
|
[/is not a valid url/i, "Это не похоже на ссылку"],
|
||||||
|
[/video unavailable|this video is not available/i, "Видео недоступно"],
|
||||||
|
[/private video/i, "Видео приватное"],
|
||||||
|
[/members[- ]only|join this channel/i, "Видео только для участников канала"],
|
||||||
|
[/confirm your age|age[- ]restricted/i, "Возрастное ограничение — нужны cookies аккаунта (YTDLP_COOKIES)"],
|
||||||
|
[/confirm you'?re not a bot|sign in to confirm/i, "YouTube требует вход — добавьте cookies.txt (YTDLP_COOKIES)"],
|
||||||
|
[/not available in your country|geo[- ]?restricted|blocked it in your country/i, "Недоступно в регионе сервера"],
|
||||||
|
[/page needs to be reloaded/i, "YouTube сменил API — обновите yt-dlp (см. README)"],
|
||||||
|
[/unable to download|network|timed out|connection/i, "Не удалось связаться с источником"],
|
||||||
|
];
|
||||||
|
|
||||||
|
/** Percent-encoded URLs are unreadable in a chat message. */
|
||||||
|
function decodeUrls(text: string): string {
|
||||||
|
return text.replace(/https?:\/\/\S+/g, (url) => {
|
||||||
|
try {
|
||||||
|
return decodeURI(url);
|
||||||
|
} catch {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function firstUsefulError(stderr: string): string {
|
function firstUsefulError(stderr: string): string {
|
||||||
const line = stderr
|
const line = stderr
|
||||||
.split(/\r?\n/)
|
.split(/\r?\n/)
|
||||||
.map((l) => l.trim())
|
.map((l) => l.trim())
|
||||||
.find((l) => l.toUpperCase().startsWith("ERROR"));
|
.find((l) => l.toUpperCase().startsWith("ERROR"));
|
||||||
if (!line) return "Не удалось получить трек";
|
if (!line) return "Не удалось получить трек";
|
||||||
return line.replace(/^ERROR:\s*/i, "").slice(0, 300);
|
|
||||||
|
const raw = decodeUrls(line.replace(/^ERROR:\s*/i, "")).slice(0, 300);
|
||||||
|
const known = ERROR_PATTERNS.find(([pattern]) => pattern.test(raw));
|
||||||
|
return known ? known[1] : raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sourceOf(entry: YtDlpEntry): SourceKind {
|
function sourceOf(entry: YtDlpEntry): SourceKind {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ const SOURCE_BADGE: Record<Track["source"], string> = {
|
|||||||
interface Props {
|
interface Props {
|
||||||
serverId: string;
|
serverId: string;
|
||||||
canControl: boolean;
|
canControl: boolean;
|
||||||
|
/** Adds the local library to the source picker. */
|
||||||
localLibrary: boolean;
|
localLibrary: boolean;
|
||||||
onError(message: string | null): void;
|
onError(message: string | null): void;
|
||||||
}
|
}
|
||||||
@@ -126,16 +127,6 @@ export function SearchPanel({ serverId, canControl, localLibrary, onError }: Pro
|
|||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<p className="hint">
|
|
||||||
Префиксы: <code>sc:</code> — искать в SoundCloud, <code>yt:</code> — в YouTube
|
|
||||||
{localLibrary ? (
|
|
||||||
<>
|
|
||||||
, <code>local:</code> — в локальной медиатеке
|
|
||||||
</>
|
|
||||||
) : null}
|
|
||||||
.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user