|
| 1 | +/** |
| 2 | + * Genre mapping configuration |
| 3 | + * |
| 4 | + * This file centralizes genre name normalization across different metadata providers. |
| 5 | + * Each provider may return genre names in different formats, and this mapping ensures |
| 6 | + * consistency in the database. |
| 7 | + * |
| 8 | + * Example: |
| 9 | + * - TMDB might return "Science Fiction" |
| 10 | + * - Another provider might return "Sci-Fi" |
| 11 | + * - Both should map to "Science Fiction" in our database |
| 12 | + */ |
| 13 | + |
| 14 | +/** |
| 15 | + * Normalized genre names used in the database |
| 16 | + * These are the canonical genre names we use across the application |
| 17 | + */ |
| 18 | +export const NORMALIZED_GENRES = { |
| 19 | + // Movies & TV Shows |
| 20 | + ACTION: "Action", |
| 21 | + ADVENTURE: "Adventure", |
| 22 | + ANIMATION: "Animation", |
| 23 | + COMEDY: "Comedy", |
| 24 | + CRIME: "Crime", |
| 25 | + DOCUMENTARY: "Documentary", |
| 26 | + DRAMA: "Drama", |
| 27 | + FAMILY: "Family", |
| 28 | + FANTASY: "Fantasy", |
| 29 | + HISTORY: "History", |
| 30 | + HORROR: "Horror", |
| 31 | + MUSIC: "Music", |
| 32 | + MYSTERY: "Mystery", |
| 33 | + ROMANCE: "Romance", |
| 34 | + SCIENCE_FICTION: "Science Fiction", |
| 35 | + TV_MOVIE: "TV Movie", |
| 36 | + THRILLER: "Thriller", |
| 37 | + WAR: "War", |
| 38 | + WESTERN: "Western", |
| 39 | + |
| 40 | + // TV Specific |
| 41 | + ACTION_ADVENTURE: "Action & Adventure", |
| 42 | + KIDS: "Kids", |
| 43 | + NEWS: "News", |
| 44 | + REALITY: "Reality", |
| 45 | + SOAP: "Soap", |
| 46 | + TALK: "Talk", |
| 47 | + WAR_POLITICS: "War & Politics", |
| 48 | + |
| 49 | + // Comics |
| 50 | + SUPERHERO: "Superhero", |
| 51 | + MANGA: "Manga", |
| 52 | + GRAPHIC_NOVEL: "Graphic Novel", |
| 53 | + |
| 54 | + // Music |
| 55 | + ROCK: "Rock", |
| 56 | + POP: "Pop", |
| 57 | + JAZZ: "Jazz", |
| 58 | + CLASSICAL: "Classical", |
| 59 | + ELECTRONIC: "Electronic", |
| 60 | + HIP_HOP: "Hip Hop", |
| 61 | + METAL: "Metal", |
| 62 | + COUNTRY: "Country", |
| 63 | + BLUES: "Blues", |
| 64 | + FOLK: "Folk", |
| 65 | + REGGAE: "Reggae", |
| 66 | + RNB: "R&B", |
| 67 | + INDIE: "Indie", |
| 68 | + ALTERNATIVE: "Alternative", |
| 69 | + PUNK: "Punk", |
| 70 | +} as const; |
| 71 | + |
| 72 | +/** |
| 73 | + * Genre mapping table |
| 74 | + * Maps various genre name variations to their normalized form |
| 75 | + * |
| 76 | + * Key: lowercase version of what providers might return |
| 77 | + * Value: normalized genre name from NORMALIZED_GENRES |
| 78 | + */ |
| 79 | +export const GENRE_MAPPING: Record<string, string> = { |
| 80 | + // Action variations |
| 81 | + action: NORMALIZED_GENRES.ACTION, |
| 82 | + |
| 83 | + // Adventure variations |
| 84 | + adventure: NORMALIZED_GENRES.ADVENTURE, |
| 85 | + |
| 86 | + // Animation variations |
| 87 | + animation: NORMALIZED_GENRES.ANIMATION, |
| 88 | + animated: NORMALIZED_GENRES.ANIMATION, |
| 89 | + |
| 90 | + // Comedy variations |
| 91 | + comedy: NORMALIZED_GENRES.COMEDY, |
| 92 | + |
| 93 | + // Crime variations |
| 94 | + crime: NORMALIZED_GENRES.CRIME, |
| 95 | + |
| 96 | + // Documentary variations |
| 97 | + documentary: NORMALIZED_GENRES.DOCUMENTARY, |
| 98 | + documentaries: NORMALIZED_GENRES.DOCUMENTARY, |
| 99 | + |
| 100 | + // Drama variations |
| 101 | + drama: NORMALIZED_GENRES.DRAMA, |
| 102 | + |
| 103 | + // Family variations |
| 104 | + family: NORMALIZED_GENRES.FAMILY, |
| 105 | + |
| 106 | + // Fantasy variations |
| 107 | + fantasy: NORMALIZED_GENRES.FANTASY, |
| 108 | + |
| 109 | + // History variations |
| 110 | + history: NORMALIZED_GENRES.HISTORY, |
| 111 | + historical: NORMALIZED_GENRES.HISTORY, |
| 112 | + |
| 113 | + // Horror variations |
| 114 | + horror: NORMALIZED_GENRES.HORROR, |
| 115 | + |
| 116 | + // Music variations |
| 117 | + music: NORMALIZED_GENRES.MUSIC, |
| 118 | + musical: NORMALIZED_GENRES.MUSIC, |
| 119 | + |
| 120 | + // Mystery variations |
| 121 | + mystery: NORMALIZED_GENRES.MYSTERY, |
| 122 | + |
| 123 | + // Romance variations |
| 124 | + romance: NORMALIZED_GENRES.ROMANCE, |
| 125 | + romantic: NORMALIZED_GENRES.ROMANCE, |
| 126 | + |
| 127 | + // Science Fiction variations |
| 128 | + "science fiction": NORMALIZED_GENRES.SCIENCE_FICTION, |
| 129 | + "sci-fi": NORMALIZED_GENRES.SCIENCE_FICTION, |
| 130 | + scifi: NORMALIZED_GENRES.SCIENCE_FICTION, |
| 131 | + "science-fiction": NORMALIZED_GENRES.SCIENCE_FICTION, |
| 132 | + |
| 133 | + // TV Movie |
| 134 | + "tv movie": NORMALIZED_GENRES.TV_MOVIE, |
| 135 | + |
| 136 | + // Thriller variations |
| 137 | + thriller: NORMALIZED_GENRES.THRILLER, |
| 138 | + |
| 139 | + // War variations |
| 140 | + war: NORMALIZED_GENRES.WAR, |
| 141 | + |
| 142 | + // Western variations |
| 143 | + western: NORMALIZED_GENRES.WESTERN, |
| 144 | + |
| 145 | + // TV Specific |
| 146 | + "action & adventure": NORMALIZED_GENRES.ACTION_ADVENTURE, |
| 147 | + "action and adventure": NORMALIZED_GENRES.ACTION_ADVENTURE, |
| 148 | + kids: NORMALIZED_GENRES.KIDS, |
| 149 | + children: NORMALIZED_GENRES.KIDS, |
| 150 | + news: NORMALIZED_GENRES.NEWS, |
| 151 | + reality: NORMALIZED_GENRES.REALITY, |
| 152 | + "reality-tv": NORMALIZED_GENRES.REALITY, |
| 153 | + soap: NORMALIZED_GENRES.SOAP, |
| 154 | + talk: NORMALIZED_GENRES.TALK, |
| 155 | + "war & politics": NORMALIZED_GENRES.WAR_POLITICS, |
| 156 | + "war and politics": NORMALIZED_GENRES.WAR_POLITICS, |
| 157 | + |
| 158 | + // Comics |
| 159 | + superhero: NORMALIZED_GENRES.SUPERHERO, |
| 160 | + "super hero": NORMALIZED_GENRES.SUPERHERO, |
| 161 | + "super-hero": NORMALIZED_GENRES.SUPERHERO, |
| 162 | + manga: NORMALIZED_GENRES.MANGA, |
| 163 | + "graphic novel": NORMALIZED_GENRES.GRAPHIC_NOVEL, |
| 164 | + |
| 165 | + // Music genres |
| 166 | + rock: NORMALIZED_GENRES.ROCK, |
| 167 | + pop: NORMALIZED_GENRES.POP, |
| 168 | + jazz: NORMALIZED_GENRES.JAZZ, |
| 169 | + classical: NORMALIZED_GENRES.CLASSICAL, |
| 170 | + electronic: NORMALIZED_GENRES.ELECTRONIC, |
| 171 | + "hip hop": NORMALIZED_GENRES.HIP_HOP, |
| 172 | + "hip-hop": NORMALIZED_GENRES.HIP_HOP, |
| 173 | + hiphop: NORMALIZED_GENRES.HIP_HOP, |
| 174 | + rap: NORMALIZED_GENRES.HIP_HOP, |
| 175 | + metal: NORMALIZED_GENRES.METAL, |
| 176 | + "heavy metal": NORMALIZED_GENRES.METAL, |
| 177 | + country: NORMALIZED_GENRES.COUNTRY, |
| 178 | + blues: NORMALIZED_GENRES.BLUES, |
| 179 | + folk: NORMALIZED_GENRES.FOLK, |
| 180 | + reggae: NORMALIZED_GENRES.REGGAE, |
| 181 | + "r&b": NORMALIZED_GENRES.RNB, |
| 182 | + rnb: NORMALIZED_GENRES.RNB, |
| 183 | + "rhythm and blues": NORMALIZED_GENRES.RNB, |
| 184 | + indie: NORMALIZED_GENRES.INDIE, |
| 185 | + alternative: NORMALIZED_GENRES.ALTERNATIVE, |
| 186 | + punk: NORMALIZED_GENRES.PUNK, |
| 187 | +}; |
| 188 | + |
| 189 | +/** |
| 190 | + * Normalize a genre name to its canonical form |
| 191 | + * |
| 192 | + * @param genreName - The genre name from a metadata provider |
| 193 | + * @returns The normalized genre name, or the original if no mapping exists |
| 194 | + */ |
| 195 | +export function normalizeGenreName(genreName: string): string { |
| 196 | + const lowercased = genreName.toLowerCase().trim(); |
| 197 | + return GENRE_MAPPING[lowercased] || genreName; |
| 198 | +} |
| 199 | + |
| 200 | +/** |
| 201 | + * Create a slug from a genre name |
| 202 | + * |
| 203 | + * @param genreName - The genre name |
| 204 | + * @returns A URL-friendly slug |
| 205 | + */ |
| 206 | +export function createGenreSlug(genreName: string): string { |
| 207 | + return genreName |
| 208 | + .toLowerCase() |
| 209 | + .trim() |
| 210 | + .replace(/[^\w\s-]/g, "") // Remove special characters |
| 211 | + .replace(/\s+/g, "-") // Replace spaces with hyphens |
| 212 | + .replace(/-+/g, "-"); // Replace multiple hyphens with single hyphen |
| 213 | +} |
0 commit comments