diff --git a/api/_bootstrap.php b/api/_bootstrap.php index e197b36..7c8dac7 100644 --- a/api/_bootstrap.php +++ b/api/_bootstrap.php @@ -102,6 +102,46 @@ function request_track() { return [trim((string) $artist), trim((string) $title)]; } +/** + * Strip a featuring-artist credit ("(feat. X)", "(ft. X)", "(featuring X)", + * "(with X)", bracket variants, or an unparenthesized trailing "feat. X") + * before it goes into a Genius/dumb search query. + * + * Genius's canonical song title never includes the featuring credit (it's + * separate metadata), but translation/cover pages often spell it out + * verbatim in their title — e.g. searching "Havana (feat. Young Thug)" + * surfaces only German/French translation pages (titled "... ft. Young + * Thug ... (Deutsche Übersetzung)" etc.), while "Havana" alone correctly + * finds the original as the first hit. Leaves other qualifiers like + * "(Remix)"/"(Live)" alone — those genuinely change which page you want. + */ +function strip_feature_credit($title) { + $title = preg_replace('/[\(\[]\s*(?:feat\.?|ft\.?|featuring|with)\b[^\)\]]*[\)\]]/i', '', $title); + $title = preg_replace('/\s+(?:feat\.?|ft\.?|featuring)\b.+$/i', '', $title); + return trim(preg_replace('/\s{2,}/', ' ', $title)); +} + +/** + * Loose "is this search hit actually by the artist we want" check — + * case-insensitive, ignores punctuation/spacing and anything in brackets + * (so "Camila Cabello (Ft. Young Thug)" still matches "Camila Cabello"). + * An empty side always matches (nothing to compare against). Used to skip + * past hits attributed to someone else entirely — most notably Genius's + * "Genius Deutsche Übersetzungen" / "Genius traductions françaises" / etc. + * pseudo-artist accounts that translation pages get filed under. + */ +function artist_loosely_matches($hitArtist, $wantArtist) { + $norm = function ($s) { + $s = preg_replace('/[\(\[][^\)\]]*[\)\]]/', '', (string) $s); + $s = preg_replace('/[^\p{L}\p{N}]+/u', '', $s); + return strtolower($s); + }; + $a = $norm($hitArtist); + $b = $norm($wantArtist); + if ($a === '' || $b === '') return true; + return strpos($a, $b) !== false || strpos($b, $a) !== false; +} + /** * Return the inner HTML of a balanced