From e7f6aeb70cd4c0126e257baff3664a96fba40d9e Mon Sep 17 00:00:00 2001 From: Juan Rodriguez Date: Sun, 28 Apr 2024 11:49:27 +0200 Subject: [PATCH 01/19] fix: chromium ERROR:zygote_host_impl_linux.cc(100) --- src/utils/scraper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/scraper.ts b/src/utils/scraper.ts index e51f726..8c76e69 100644 --- a/src/utils/scraper.ts +++ b/src/utils/scraper.ts @@ -5,7 +5,7 @@ let browser: Browser | null = null; async function launchBrowser(): Promise { if (!browser) { - browser = await puppeteer.launch({ headless: true }); + browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox'] }); } return browser; } From b77120bf8b0be962f4d476ec7b26c8680cba8197 Mon Sep 17 00:00:00 2001 From: Juan Rodriguez Date: Sun, 28 Apr 2024 13:21:43 +0200 Subject: [PATCH 02/19] feat: linkToServiceType parser --- src/{utils => adapters}/spotify.ts | 2 +- src/config/enum.ts | 17 +++++++++++++++++ src/parsers/link.ts | 18 ++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) rename src/{utils => adapters}/spotify.ts (98%) create mode 100644 src/config/enum.ts create mode 100644 src/parsers/link.ts diff --git a/src/utils/spotify.ts b/src/adapters/spotify.ts similarity index 98% rename from src/utils/spotify.ts rename to src/adapters/spotify.ts index 20d9dba..00e1d86 100644 --- a/src/utils/spotify.ts +++ b/src/adapters/spotify.ts @@ -78,5 +78,5 @@ export async function fetchSpotifyMetadata(spotifyLink: string) { }); } - return { html, url }; + return html; } diff --git a/src/config/enum.ts b/src/config/enum.ts new file mode 100644 index 0000000..53d1a0f --- /dev/null +++ b/src/config/enum.ts @@ -0,0 +1,17 @@ +export enum ServiceType { + Spotify = 'spotify', + YouTube = 'youTube', + AppleMusic = 'appleMusic', + Tidal = 'tidal', + SoundCloud = 'soundCloud', + Deezer = 'deezer', +} + +export enum MetadataType { + Song = 'song', + Album = 'album', + Playlist = 'playlist', + Artist = 'artist', + Podcast = 'podcast', + Show = 'show', +} diff --git a/src/parsers/link.ts b/src/parsers/link.ts new file mode 100644 index 0000000..9848ab4 --- /dev/null +++ b/src/parsers/link.ts @@ -0,0 +1,18 @@ +import { SPOTIFY_LINK_REGEX, YOUTUBE_LINK_REGEX } from '~/config/constants'; +import { ServiceType } from '~/config/enum'; + +export const linkToServiceType = (link: string) => { + const spotifyId = link.match(SPOTIFY_LINK_REGEX)?.[3]; + + if (spotifyId) { + return { type: ServiceType.Spotify, id: spotifyId }; + } + + const youtubeId = link.match(YOUTUBE_LINK_REGEX)?.[1]; + + if (youtubeId) { + return { type: ServiceType.YouTube, id: youtubeId }; + } + + throw new Error('Link not valid or could not be parsed'); +}; From 5e6a25811e9232e50d5ef00e39db5be481981eab Mon Sep 17 00:00:00 2001 From: Juan Rodriguez Date: Sun, 28 Apr 2024 13:22:08 +0200 Subject: [PATCH 03/19] refactor: decouple service search interfaces from spotify parser --- src/adapters/apple-music.ts | 22 +++++------ src/adapters/deezer.ts | 22 +++++------ src/adapters/soundcloud.ts | 14 +++---- src/adapters/tidal.ts | 7 ++-- src/adapters/youtube.ts | 22 +++++------ src/config/constants.ts | 3 ++ src/parsers/spotify.ts | 54 ++++++++++++-------------- src/routes/api.ts | 8 ++-- src/routes/page.tsx | 8 ++-- src/services/cache.ts | 14 ++++--- src/services/search.ts | 57 +++++++++++++++++----------- src/utils/query.ts | 12 +++--- src/validations/search.ts | 4 +- src/views/components/search-card.tsx | 22 +++++------ src/views/components/search-link.tsx | 22 +++++------ 15 files changed, 152 insertions(+), 139 deletions(-) diff --git a/src/adapters/apple-music.ts b/src/adapters/apple-music.ts index 100b124..a836f6b 100644 --- a/src/adapters/apple-music.ts +++ b/src/adapters/apple-music.ts @@ -1,26 +1,26 @@ import * as config from '~/config/default'; +import { MetadataType, ServiceType } from '~/config/enum'; import { DEFAULT_TIMEOUT } from '~/config/constants'; import HttpClient from '~/utils/http-client'; import { logger } from '~/utils/logger'; import { getCheerioDoc } from '~/utils/scraper'; -import { SpotifyMetadata, SpotifyMetadataType } from '~/parsers/spotify'; -import { SpotifyContentLink, SpotifyContentLinkType } from '~/services/search'; +import { SearchMetadata, SearchResultLink } from '~/services/search'; import { getResultWithBestScore } from '~/utils/compare'; export const APPLE_MUSIC_LINK_SELECTOR = 'a[href^="https://music.apple.com/"]'; const APPLE_MUSIC_SEARCH_TYPES = { - [SpotifyMetadataType.Song]: 'Songs', - [SpotifyMetadataType.Album]: 'Albums', - [SpotifyMetadataType.Playlist]: 'Playlists', - [SpotifyMetadataType.Artist]: 'Artists', - [SpotifyMetadataType.Podcast]: undefined, - [SpotifyMetadataType.Show]: undefined, + [MetadataType.Song]: 'Songs', + [MetadataType.Album]: 'Albums', + [MetadataType.Playlist]: 'Playlists', + [MetadataType.Artist]: 'Artists', + [MetadataType.Podcast]: undefined, + [MetadataType.Show]: undefined, }; -export async function getAppleMusicLink(query: string, metadata: SpotifyMetadata) { +export async function getAppleMusicLink(query: string, metadata: SearchMetadata) { const searchType = APPLE_MUSIC_SEARCH_TYPES[metadata.type]; if (!searchType) { @@ -45,10 +45,10 @@ export async function getAppleMusicLink(query: string, metadata: SpotifyMetadata const { href } = getResultWithBestScore(doc, listElements, query); return { - type: SpotifyContentLinkType.AppleMusic, + type: ServiceType.AppleMusic, url: href, isVerified: true, - } as SpotifyContentLink; + } as SearchResultLink; } catch (err) { logger.error(`[Apple Music](${url}) ${err} `); } diff --git a/src/adapters/deezer.ts b/src/adapters/deezer.ts index fe0401c..ccc1ba8 100644 --- a/src/adapters/deezer.ts +++ b/src/adapters/deezer.ts @@ -1,12 +1,12 @@ import * as config from '~/config/default'; +import { MetadataType, ServiceType } from '~/config/enum'; import { ADAPTERS_QUERY_LIMIT } from '~/config/constants'; import HttpClient from '~/utils/http-client'; import { logger } from '~/utils/logger'; import { responseMatchesQuery } from '~/utils/compare'; -import { SpotifyMetadata, SpotifyMetadataType } from '~/parsers/spotify'; -import { SpotifyContentLink, SpotifyContentLinkType } from '~/services/search'; +import { SearchMetadata, SearchResultLink } from '~/services/search'; interface DeezerSearchResponse { total: number; @@ -20,15 +20,15 @@ interface DeezerSearchResponse { } const DEEZER_SEARCH_TYPES = { - [SpotifyMetadataType.Song]: 'track', - [SpotifyMetadataType.Album]: 'album', - [SpotifyMetadataType.Playlist]: 'playlist', - [SpotifyMetadataType.Artist]: 'artist', - [SpotifyMetadataType.Show]: 'podcast', - [SpotifyMetadataType.Podcast]: undefined, + [MetadataType.Song]: 'track', + [MetadataType.Album]: 'album', + [MetadataType.Playlist]: 'playlist', + [MetadataType.Artist]: 'artist', + [MetadataType.Show]: 'podcast', + [MetadataType.Podcast]: undefined, }; -export async function getDeezerLink(query: string, metadata: SpotifyMetadata) { +export async function getDeezerLink(query: string, metadata: SearchMetadata) { const searchType = DEEZER_SEARCH_TYPES[metadata.type]; if (!searchType) { @@ -57,10 +57,10 @@ export async function getDeezerLink(query: string, metadata: SpotifyMetadata) { } return { - type: SpotifyContentLinkType.Deezer, + type: ServiceType.Deezer, url: link, isVerified: true, - } as SpotifyContentLink; + } as SearchResultLink; } catch (error) { logger.error(`[Deezer] (${url}) ${error}`); } diff --git a/src/adapters/soundcloud.ts b/src/adapters/soundcloud.ts index 449053e..4df0b89 100644 --- a/src/adapters/soundcloud.ts +++ b/src/adapters/soundcloud.ts @@ -1,15 +1,15 @@ import * as config from '~/config/default'; +import { MetadataType, ServiceType } from '~/config/enum'; import HttpClient from '~/utils/http-client'; import { logger } from '~/utils/logger'; import { getCheerioDoc } from '~/utils/scraper'; - -import { SpotifyContentLink, SpotifyContentLinkType } from '~/services/search'; -import { SpotifyMetadata, SpotifyMetadataType } from '~/parsers/spotify'; import { getResultWithBestScore } from '~/utils/compare'; -export async function getSoundCloudLink(query: string, metadata: SpotifyMetadata) { - if (metadata.type === SpotifyMetadataType.Show) { +import { SearchMetadata, SearchResultLink } from '~/services/search'; + +export async function getSoundCloudLink(query: string, metadata: SearchMetadata) { + if (metadata.type === MetadataType.Show) { return; } @@ -33,10 +33,10 @@ export async function getSoundCloudLink(query: string, metadata: SpotifyMetadata const { href } = getResultWithBestScore(noscriptDoc, listElements, query); return { - type: SpotifyContentLinkType.SoundCloud, + type: ServiceType.SoundCloud, url: `${config.services.soundCloud.baseUrl}${href}`, isVerified: true, - } as SpotifyContentLink; + } as SearchResultLink; } catch (err) { logger.error(`[SoundCloud] (${url}) ${err}`); } diff --git a/src/adapters/tidal.ts b/src/adapters/tidal.ts index a71f658..04cb295 100644 --- a/src/adapters/tidal.ts +++ b/src/adapters/tidal.ts @@ -1,6 +1,7 @@ import * as config from '~/config/default'; +import { ServiceType } from '~/config/enum'; -import { SpotifyContentLink, SpotifyContentLinkType } from '~/services/search'; +import { SearchResultLink } from '~/services/search'; export function getTidalLink(query: string) { const params = new URLSearchParams({ @@ -11,7 +12,7 @@ export function getTidalLink(query: string) { url.search = params.toString(); return { - type: SpotifyContentLinkType.Tidal, + type: ServiceType.Tidal, url: url.toString(), - } as SpotifyContentLink; + } as SearchResultLink; } diff --git a/src/adapters/youtube.ts b/src/adapters/youtube.ts index e121868..bb337c1 100644 --- a/src/adapters/youtube.ts +++ b/src/adapters/youtube.ts @@ -1,21 +1,21 @@ import * as config from '~/config/default'; +import { MetadataType, ServiceType } from '~/config/enum'; import { logger } from '~/utils/logger'; -import { SpotifyMetadata, SpotifyMetadataType } from '~/parsers/spotify'; -import { SpotifyContentLink, SpotifyContentLinkType } from '~/services/search'; +import { SearchMetadata, SearchResultLink } from '~/services/search'; import { getLinkWithPuppeteer } from '~/utils/scraper'; const YOUTUBE_SEARCH_TYPES = { - [SpotifyMetadataType.Song]: 'song', - [SpotifyMetadataType.Album]: 'album', - [SpotifyMetadataType.Playlist]: '', - [SpotifyMetadataType.Artist]: 'channel', - [SpotifyMetadataType.Podcast]: '', - [SpotifyMetadataType.Show]: '', + [MetadataType.Song]: 'song', + [MetadataType.Album]: 'album', + [MetadataType.Playlist]: '', + [MetadataType.Artist]: 'channel', + [MetadataType.Podcast]: '', + [MetadataType.Show]: '', }; -export async function getYouTubeLink(query: string, metadata: SpotifyMetadata) { +export async function getYouTubeLink(query: string, metadata: SearchMetadata) { const params = new URLSearchParams({ q: `${query} ${YOUTUBE_SEARCH_TYPES[metadata.type]}`, }); @@ -51,10 +51,10 @@ export async function getYouTubeLink(query: string, metadata: SpotifyMetadata) { } return { - type: SpotifyContentLinkType.YouTube, + type: ServiceType.YouTube, url: link, isVerified: true, - } as SpotifyContentLink; + } as SearchResultLink; } catch (error) { logger.error(`[YouTube] (${url}) ${error}`); } diff --git a/src/config/constants.ts b/src/config/constants.ts index 967b23e..15ac937 100644 --- a/src/config/constants.ts +++ b/src/config/constants.ts @@ -5,6 +5,9 @@ export const SPOTIFY_LINK_MOBILE_REGEX = /^https:\/\/spotify\.link\/(\w+)/; export const SPOTIFY_LINK_DESKTOP_REGEX = /(https:\/\/open\.spotify\.com\/(track|album|playlist|artist|episode|show)\/(\w+))/; +export const YOUTUBE_LINK_REGEX = + /(?:https?:\/\/)?(?:www\.)?(?:youtube\.com|youtu\.be|music\.youtube\.com)\/(?:watch\?v=)?(?:embed\/)?(?:v\/)?(?:shorts\/)?(?:\S+\?v=)?(?:watch\?v=)?(?:embed\/)?(?:v\/)?(?:shorts\/)?(?:\S+\?v=)?(?:embed\/|\/)*([\w-]{11})(?:\S+)?/; + export const ADAPTERS_QUERY_LIMIT = 1; export const RESPONSE_COMPARE_MIN_SCORE = 0.4; diff --git a/src/parsers/spotify.ts b/src/parsers/spotify.ts index aa4d11d..a3e2941 100644 --- a/src/parsers/spotify.ts +++ b/src/parsers/spotify.ts @@ -1,8 +1,11 @@ -import { cacheSearchMetadata, getCachedSearchMetadata } from '~/services/cache'; +import { MetadataType } from '~/config/enum'; +import { fetchSpotifyMetadata } from '~/adapters/spotify'; + import { getCheerioDoc, metaTagContent } from '~/utils/scraper'; -import { fetchSpotifyMetadata } from '~/utils/spotify'; +import { cacheSearchMetadata, getCachedSearchMetadata } from '~/services/cache'; +import { SearchMetadata } from '~/services/search'; -export enum SpotifyMetadataType { +enum SpotifyMetadataType { Song = 'music.song', Album = 'music.album', Playlist = 'music.playlist', @@ -11,27 +14,23 @@ export enum SpotifyMetadataType { Show = 'website', } -export type SpotifyMetadata = { - title: string; - description: string; - type: SpotifyMetadataType; - image: string; - audio?: string; -}; - -export type SearchMetadata = { - url: string; - metadata: SpotifyMetadata; +const SPOTIFY_METADATA_TO_METADATA_TYPE = { + [SpotifyMetadataType.Song]: MetadataType.Song, + [SpotifyMetadataType.Album]: MetadataType.Album, + [SpotifyMetadataType.Playlist]: MetadataType.Playlist, + [SpotifyMetadataType.Artist]: MetadataType.Artist, + [SpotifyMetadataType.Podcast]: MetadataType.Podcast, + [SpotifyMetadataType.Show]: MetadataType.Show, }; -export const parseSpotifyMetadata = async (spotifyLink: string) => { - const cached = await getCachedSearchMetadata(spotifyLink); +export const getSpotifyMetadata = async (link: string) => { + const cached = await getCachedSearchMetadata(link); if (cached) { return cached; } try { - const { html, url } = await fetchSpotifyMetadata(spotifyLink); + const html = await fetchSpotifyMetadata(link); const doc = getCheerioDoc(html); @@ -40,29 +39,26 @@ export const parseSpotifyMetadata = async (spotifyLink: string) => { const image = metaTagContent(doc, 'og:image', 'property'); const audio = metaTagContent(doc, 'og:audio', 'property'); - const type = spotifyLink.includes('episode') + const type = link.includes('episode') ? SpotifyMetadataType.Podcast - : metaTagContent(doc, 'og:type', 'property'); + : (metaTagContent(doc, 'og:type', 'property') as SpotifyMetadataType); if (!title || !description || !type || !image) { throw new Error('Spotify metadata not found'); } const searchMetadata = { - metadata: { - title, - description, - type: type as SpotifyMetadataType, - image, - audio, - }, - url, + title, + description, + type: SPOTIFY_METADATA_TO_METADATA_TYPE[type], + image, + audio, } as SearchMetadata; - await cacheSearchMetadata(searchMetadata); + await cacheSearchMetadata(link, searchMetadata); return searchMetadata; } catch (err) { - throw new Error(`[${parseSpotifyMetadata.name}] (${spotifyLink}) ${err}`); + throw new Error(`[${getSpotifyMetadata.name}] (${link}) ${err}`); } }; diff --git a/src/routes/api.ts b/src/routes/api.ts index cf1c2dd..72ae533 100644 --- a/src/routes/api.ts +++ b/src/routes/api.ts @@ -4,7 +4,7 @@ import { logger } from '~/utils/logger'; import { apiVersionValidator, searchPayloadValidator } from '~/validations/search'; -import { spotifySearch } from '~/services/search'; +import { search } from '~/services/search'; export const apiRouter = new Elysia().group('/api', app => app @@ -18,10 +18,10 @@ export const apiRouter = new Elysia().group('/api', app => }) .post( '/search', - async ({ body: { spotifyLink } }) => { - const spotifyContent = await spotifySearch(spotifyLink); + async ({ body: { link } }) => { + const searchResult = await search(link); - return spotifyContent; + return searchResult; }, { body: searchPayloadValidator, diff --git a/src/routes/page.tsx b/src/routes/page.tsx index df6c54a..4ba0c67 100644 --- a/src/routes/page.tsx +++ b/src/routes/page.tsx @@ -4,7 +4,7 @@ import { logger } from '~/utils/logger'; import { searchPayloadValidator } from '~/validations/search'; -import { spotifySearch } from '~/services/search'; +import { search } from '~/services/search'; import MainLayout from '~/views/layouts/main'; import Home from '~/views/pages/home'; @@ -28,10 +28,10 @@ export const pageRouter = new Elysia() }) .post( '/search', - async ({ body: { spotifyLink } }) => { - const spotifyContent = await spotifySearch(spotifyLink); + async ({ body: { link } }) => { + const searchResult = await search(link); - return ; + return ; }, { body: searchPayloadValidator, diff --git a/src/services/cache.ts b/src/services/cache.ts index 0f8558c..7da4cdf 100644 --- a/src/services/cache.ts +++ b/src/services/cache.ts @@ -3,8 +3,7 @@ import * as config from '~/config/default'; const sqliteStore = require('cache-manager-sqlite'); const cacheManager = require('cache-manager'); -import { SearchMetadata } from '~/parsers/spotify'; -import { SearchResult } from './search'; +import { SearchMetadata, SearchResult } from './search'; export const cacheStore = cacheManager.caching({ store: sqliteStore, @@ -12,14 +11,17 @@ export const cacheStore = cacheManager.caching({ path: config.cache.databasePath, }); -export const cacheSearchMetadata = async (searchMetadata: SearchMetadata) => { - await cacheStore.set(`search:${searchMetadata.url}`, searchMetadata, { +export const cacheSearchMetadata = async ( + link: string, + searchMetadata: SearchMetadata +) => { + await cacheStore.set(`search:${link}`, searchMetadata, { ttl: config.cache.expTime, }); }; -export const getCachedSearchMetadata = async (url: SearchMetadata['url']) => { - const data = (await cacheStore.get(`search:${url}`)) as SearchMetadata; +export const getCachedSearchMetadata = async (link: string) => { + const data = (await cacheStore.get(`search:${link}`)) as SearchMetadata; return data; }; diff --git a/src/services/search.ts b/src/services/search.ts index 1b99542..c3c9ce8 100644 --- a/src/services/search.ts +++ b/src/services/search.ts @@ -1,9 +1,10 @@ -import { SPOTIFY_LINK_REGEX } from '~/config/constants'; +import { MetadataType, ServiceType } from '~/config/enum'; import { logger } from '~/utils/logger'; import { getQueryFromMetadata } from '~/utils/query'; -import { SpotifyMetadataType, parseSpotifyMetadata } from '~/parsers/spotify'; +import { linkToServiceType } from '~/parsers/link'; +import { getSpotifyMetadata } from '~/parsers/spotify'; import { cacheSearchResult, getCachedSearchResult } from './cache'; @@ -13,46 +14,58 @@ import { getDeezerLink } from '~/adapters/deezer'; import { getSoundCloudLink } from '~/adapters/soundcloud'; import { getTidalLink } from '~/adapters/tidal'; -export enum SpotifyContentLinkType { - YouTube = 'youTube', - AppleMusic = 'appleMusic', - Tidal = 'tidal', - SoundCloud = 'soundCloud', - Deezer = 'deezer', -} +export type SearchMetadata = { + title: string; + description: string; + type: MetadataType; + image: string; + audio?: string; +}; -export interface SpotifyContentLink { - type: SpotifyContentLinkType; +export interface SearchResultLink { + type: ServiceType; url: string; isVerified?: boolean; } export interface SearchResult { id: string; - type: SpotifyMetadataType; + type: MetadataType; title: string; description: string; image: string; audio?: string; source: string; - links: SpotifyContentLink[]; + links: SearchResultLink[]; } -export const spotifySearch = async (spotifyLink: string): Promise => { - const id = spotifyLink.match(SPOTIFY_LINK_REGEX)?.[3] ?? ''; +export const search = async (link: string) => { + const { type, id } = linkToServiceType(link); const cache = await getCachedSearchResult(id); if (cache) { - logger.info(`[${spotifySearch.name}] loaded from cache: ${spotifyLink}`); + logger.info(`[${search.name}] loaded from cache: ${link}`); return cache; } - logger.info(`[${spotifySearch.name}] cache miss: ${spotifyLink}`); + logger.info(`[${search.name}] cache miss: ${link}`); - const { metadata, url } = await parseSpotifyMetadata(spotifyLink); + let metadata; + + if (type === ServiceType.Spotify) { + metadata = await getSpotifyMetadata(link); + } + + if (type === ServiceType.YouTube) { + // metadata = await parseYoutubeMetadata; + } + + if (!metadata) { + throw new Error('Adapter not implemented yet'); + } const query = getQueryFromMetadata(metadata.title, metadata.description, metadata.type); - logger.info(`[${spotifySearch.name}] url: ${url}, query: ${query}`); + logger.info(`[${search.name}] link: ${link}, query: ${query}`); const [appleMusicLink, youtubeLink, deezerLink, soundCloudLink] = await Promise.all([ getAppleMusicLink(query, metadata), @@ -62,7 +75,7 @@ export const spotifySearch = async (spotifyLink: string): Promise ]); logger.info( - `[${spotifySearch.name}] results: ${JSON.stringify({ + `[${search.name}] results: ${JSON.stringify({ appleMusicLink, youtubeLink, deezerLink, @@ -86,8 +99,8 @@ export const spotifySearch = async (spotifyLink: string): Promise description: metadata.description, image: metadata.image, audio: metadata.audio, - source: url, - links: links as SpotifyContentLink[], + source: link, + links: links as SearchResultLink[], }; await cacheSearchResult(searchResult); diff --git a/src/utils/query.ts b/src/utils/query.ts index dde7d88..aa3c438 100644 --- a/src/utils/query.ts +++ b/src/utils/query.ts @@ -1,9 +1,9 @@ -import { SpotifyMetadataType } from '~/parsers/spotify'; +import { MetadataType } from '~/config/enum'; export function getQueryFromMetadata( title: string, description: string, - type: SpotifyMetadataType + type: MetadataType ) { const parsedTitle = title .replace( @@ -14,22 +14,22 @@ export function getQueryFromMetadata( let query = parsedTitle; - if (type === SpotifyMetadataType.Song) { + if (type === MetadataType.Song) { const [, artist] = description.match(/^([^·]+) · Song · \d+$/) ?? []; query = artist ? `${query} ${artist}` : query; } - if (type === SpotifyMetadataType.Album) { + if (type === MetadataType.Album) { const [, artist] = description.match(/(.+?) · Album ·/) ?? []; query = artist ? `${query} ${artist}` : query; } - if (type === SpotifyMetadataType.Playlist) { + if (type === MetadataType.Playlist) { query = `${query.replace(/This is /, '')} Playlist`; } - if (type === SpotifyMetadataType.Podcast) { + if (type === MetadataType.Podcast) { const [, artist] = description.match(/from (.+?) on Spotify\./) ?? []; query = artist ? `${query} ${artist}` : query; diff --git a/src/validations/search.ts b/src/validations/search.ts index 3bd4460..aff5e7c 100644 --- a/src/validations/search.ts +++ b/src/validations/search.ts @@ -1,9 +1,7 @@ import { t } from 'elysia'; -import { SPOTIFY_LINK_REGEX } from '~/config/constants'; - export const searchPayloadValidator = t.Object({ - spotifyLink: t.RegExp(SPOTIFY_LINK_REGEX, { error: 'Invalid spotify link' }), + link: t.String({ minLength: 1 }), }); export const apiVersionValidator = t.Object({ diff --git a/src/views/components/search-card.tsx b/src/views/components/search-card.tsx index 761b79c..a499a23 100644 --- a/src/views/components/search-card.tsx +++ b/src/views/components/search-card.tsx @@ -1,36 +1,36 @@ -import { SpotifyContent } from '~/services/search'; +import { SearchResult } from '~/services/search'; import AudioPreview from './audio-preview'; import SearchLink from './search-link'; -export default function SearchCard(props: { spotifyContent: SpotifyContent }) { +export default function SearchCard(props: { searchResult: SearchResult }) { return (
- {props.spotifyContent.title} + {props.searchResult.title}

- {props.spotifyContent.description} + {props.searchResult.description}

- {props.spotifyContent.links.length === 0 && ( + {props.searchResult.links.length === 0 && (

Not available on other platforms

)} - {props.spotifyContent.links.length > 0 && ( + {props.searchResult.links.length > 0 && (