fix: word-boundary variant filter; reattempt ALTCHA verify payload structure

- ytdlp.js: use \b word boundaries in all variant filter regexes so that
  partial matches like "nightcoreals" containing "nightcore" no longer
  falsely reject official videos; also fixes sped regression (!~= \bsped\b
  instead of the too-narrow "sped up" pattern)
- squid.js: restructure verify payload to mirror challenge response layout
  { parameters, solution: { number, derivedKey }, signature }

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-05-03 01:48:29 +02:00
1 parent b9692e6f08
commit 8f8c38fcf0
2 files changed
+20 -14

No files matched your search

+7 -2
View File
@@ -106,8 +106,13 @@ async function getAltchaCookie() {
// 2. Solve PoW // 2. Solve PoW
const solution = await solveAltcha(challenge); const solution = await solveAltcha(challenge);
// 3. Verify — include the top-level signature so the server can authenticate the challenge // 3. Verify — mirror the challenge response structure: { parameters, signature } + solution fields
const payload = Buffer.from(JSON.stringify({ challenge, solution, signature: chBody.signature })).toString('base64'); const verifyBody = {
parameters: challenge,
solution: { number: solution.counter, derivedKey: solution.derivedKey },
signature: chBody.signature,
};
const payload = Buffer.from(JSON.stringify(verifyBody)).toString('base64');
const vRes = await httpsPost(`${SQUID_BASE}/api/altcha/verify`, { payload }); const vRes = await httpsPost(`${SQUID_BASE}/api/altcha/verify`, { payload });
if (vRes.status !== 200) throw new Error(`ALTCHA verify HTTP ${vRes.status}`); if (vRes.status !== 200) throw new Error(`ALTCHA verify HTTP ${vRes.status}`);
+13 -12
View File
@@ -28,19 +28,20 @@ function buildTitleKeywords(title) {
function buildVariantFilter(title) { function buildVariantFilter(title) {
const t = (title || '').toLowerCase(); const t = (title || '').toLowerCase();
// !~= (?i) is yt-dlp's case-insensitive "does not match regex" — catches Remix/REMIX/remix etc. // !~= (?i) = case-insensitive regex "does not match". Use \b word boundaries so that
// partial matches like "nightcoreals" containing "nightcore" don't falsely reject results.
const RULES = [ const RULES = [
{ key: 'sped', expr: 'title !~= (?i)sped up' }, { key: 'sped', expr: 'title !~= (?i)\\bsped\\b' },
{ key: 'speedup', expr: 'title !~= (?i)speed\\s*up' }, { key: 'speedup', expr: 'title !~= (?i)\\bspeed.{0,2}up\\b' },
{ key: 'slowed', expr: 'title !~= (?i)slowed' }, { key: 'slowed', expr: 'title !~= (?i)\\bslowed\\b' },
{ key: 'reverb', expr: 'title !~= (?i)reverb' }, { key: 'reverb', expr: 'title !~= (?i)\\breverb\\b' },
{ key: 'nightcore', expr: 'title !~= (?i)nightcore' }, { key: 'nightcore', expr: 'title !~= (?i)\\bnightcore\\b' },
{ key: 'karaoke', expr: 'title !~= (?i)karaoke' }, { key: 'karaoke', expr: 'title !~= (?i)\\bkaraoke\\b' },
{ key: 'parody', expr: 'title !~= (?i)parody' }, { key: 'parody', expr: 'title !~= (?i)\\bparody\\b' },
{ key: 'remix', expr: 'title !~= (?i)remix' }, { key: 'remix', expr: 'title !~= (?i)\\bremix\\b' },
{ key: 'cover', expr: 'title !~= (?i)cover' }, { key: 'cover', expr: 'title !~= (?i)\\bcover\\b' },
{ key: 'acoustic', expr: 'title !~= (?i)acoustic' }, { key: 'acoustic', expr: 'title !~= (?i)\\bacoustic\\b' },
{ key: 'instrumental', expr: 'title !~= (?i)instrumental' }, { key: 'instrumental', expr: 'title !~= (?i)\\binstrumental\\b' },
]; ];
const parts = RULES.filter(r => !t.includes(r.key)).map(r => r.expr); const parts = RULES.filter(r => !t.includes(r.key)).map(r => r.expr);
return parts.length ? parts.join(' & ') : ''; return parts.length ? parts.join(' & ') : '';