UNPKG

social-link-parser

Version:

Extract usernames, IDs, and metadata from social media URLs across 100+ platforms

138 lines 5.86 kB
import { Platforms } from '../../core/types.js'; import { normalize, getUrlSafe } from '../../utils/url.js'; import { QUERY_HASH } from '../../utils/constants.js'; function getAppleMusicEmbedUrl(hostname, link) { const url = new URL(link); url.hostname = hostname; url.searchParams.set('theme', 'auto'); return url.toString(); } const domains = [ 'music.apple.com', 'embed.music.apple.com', 'podcasts.apple.com', 'embed.podcasts.apple.com', ]; const MUSIC_DOMAIN_PATTERN = '^https?://(?:www\\.)?(?:embed\\.)?music\\.apple\\.com'; const PODCASTS_DOMAIN_PATTERN = '^https?://(?:www\\.)?(?:embed\\.)?podcasts\\.apple\\.com'; const LOCALE_GROUP = '(?:(?<locale>[a-z]{2}(?:-[a-z]{2})?)\/)?'; const NAME_GROUP = '(?<name>[^\/]+)'; export const applemusic = { id: Platforms.AppleMusic, name: 'Apple Music', color: '#fa243c', domains: domains, domainsRegexp: new RegExp(`^(?:https?://)?(?:www\\.)?(?:(?:music|podcasts)\\.apple\\.com|embed\\.(?:music\\.|podcasts\\.)?apple\\.com)`, 'i'), patterns: { profile: new RegExp(`^https?://(music|podcasts)\\.apple\\.com/(?:(\w{2})/)?(album|artist|playlist|song|station|podcast)/[^/]+/([a-zA-Z0-9.-]+)/?${QUERY_HASH}$`, 'i'), handle: /^\d+$/, content: { playlist: new RegExp(`${MUSIC_DOMAIN_PATTERN}\\/${LOCALE_GROUP}playlist\\/${NAME_GROUP}\\/(?<playlistId>[a-zA-Z0-9.-]+)(?:\\?.*)?$`, 'i'), artist: new RegExp(`${MUSIC_DOMAIN_PATTERN}\\/${LOCALE_GROUP}artist\\/${NAME_GROUP}\\/(?<artistId>\\d+)(?:\\?.*)?$`, 'i'), station: new RegExp(`${MUSIC_DOMAIN_PATTERN}\\/${LOCALE_GROUP}station\\/${NAME_GROUP}\\/(?<stationId>[a-zA-Z0-9.-]+)(?:\\?.*)?$`, 'i'), podcastEpisode: new RegExp(`${PODCASTS_DOMAIN_PATTERN}\\/${LOCALE_GROUP}podcast\\/${NAME_GROUP}\\/id(?<podcastId>\\d+)\\?.*i=(?<episodeId>\\d+).*$`, 'i'), podcast: new RegExp(`${PODCASTS_DOMAIN_PATTERN}\\/${LOCALE_GROUP}podcast\\/${NAME_GROUP}\\/id(?<podcastId>\\d+)(?:\\?.*)?$`, 'i'), song: new RegExp(`${MUSIC_DOMAIN_PATTERN}\\/${LOCALE_GROUP}song\\/${NAME_GROUP}\\/(?<songId>\\d+)(?:\\?.*)?$`, 'i'), track: new RegExp(`${MUSIC_DOMAIN_PATTERN}\\/${LOCALE_GROUP}album\\/${NAME_GROUP}\\/(?<albumId>\\d+)\\?.*i=(?<trackId>\\d+).*$`, 'i'), album: new RegExp(`${MUSIC_DOMAIN_PATTERN}\\/${LOCALE_GROUP}album\\/${NAME_GROUP}\\/(?<albumId>\\d+)(?:\\?.*)?$`, 'i') } }, detect(url) { return this.domainsRegexp.test(url); }, extract(url, res) { const urlObj = getUrlSafe(url); if (!urlObj) return; const contentPatterns = this.patterns.content; if (!contentPatterns) return; let matchResult = null; for (const [contentType, pattern] of Object.entries(contentPatterns)) { if (!pattern) continue; const match = urlObj.href.match(pattern); if (match && match.groups) { matchResult = { contentType, match }; break; } } if (!matchResult) return; const { contentType, match } = matchResult; const groups = match.groups; res.metadata.contentType = contentType; if (groups.locale) { res.metadata.locale = groups.locale; } switch (contentType) { case 'artist': res.ids.artistId = groups.artistId; res.metadata.isProfile = true; break; case 'album': res.ids.albumId = groups.albumId; res.metadata.isAlbum = true; break; case 'playlist': res.ids.playlistId = groups.playlistId; res.metadata.isPlaylist = true; break; case 'song': res.ids.songId = groups.songId; res.metadata.isSong = true; break; case 'track': res.ids.albumId = groups.albumId; res.ids.trackId = groups.trackId; res.metadata.isTrack = true; break; case 'station': res.ids.stationId = groups.stationId; res.metadata.isStation = true; break; case 'podcast': res.ids.podcastId = groups.podcastId; res.metadata.isPodcast = true; break; case 'podcastEpisode': res.ids.podcastId = groups.podcastId; res.ids.episodeId = groups.episodeId; res.metadata.isPodcastEpisode = true; break; } res.metadata.domain = urlObj.hostname; }, validateHandle(handle) { return this.patterns.handle.test(handle); }, buildProfileUrl(artistId) { return `https://music.apple.com/us/artist/id${artistId}`; }, normalizeUrl(url) { return normalize(url); }, getEmbedInfo(url) { if (url.includes('embed.music.apple.com') || url.includes('embed.podcasts.apple.com')) { return { embedUrl: url, isEmbedAlready: true }; } const result = { isValid: false, originalUrl: url, normalizedUrl: url, platform: null, ids: {}, metadata: {} }; this.extract(url, result); if (!result.metadata.contentType) { return null; } const targetDomain = (result.metadata.contentType === 'podcast' || result.metadata.contentType === 'podcastEpisode') ? 'embed.podcasts.apple.com' : 'embed.music.apple.com'; const embedUrl = getAppleMusicEmbedUrl(targetDomain, url); return { embedUrl, type: 'iframe' }; } }; //# sourceMappingURL=index.js.map