From c5ac835b56123b1496da968f111e2a566351df6b Mon Sep 17 00:00:00 2001 From: Hugo Vieilledent <hugo.vieilledent@gmail.com> Date: Tue, 15 Jan 2019 19:27:16 +0100 Subject: [PATCH] add bandcamp parser, refactor naming, add type to parse answer --- main.js | 85 +++++++++++++++++++++++----------- src/providers.js | 3 +- test.js | 57 +++++++++++++++++------ tests/provider-dictionaries.js | 13 ++++++ 4 files changed, 118 insertions(+), 40 deletions(-) diff --git a/main.js b/main.js index c3aeca6..9ad0931 100644 --- a/main.js +++ b/main.js @@ -1,41 +1,77 @@ import youtubeRegex from 'youtube-regex' import providersList from './src/providers' -const youtubeUrlToId = (url) => { +/* + Media provider URL parsers +*/ + +const parseFileUrl = (url) => { + let result = new URL(url) + let s = result.pathname.split('/') + let id = s[s.length - 1] + return { + id, + type: 'audio' + } +} + +const parseYoutubeUrl = (url) => { const results = youtubeRegex().exec(url) if (!results) { return false } - return results[1] -} - -const fileUrlToId = (url) => { - let result = new URL(url) - let s = result.pathname.split('/') - return s[s.length - 1] + const id = results[1]; + return { + id, + type: 'video' + } } -const discogsUrlToId = (url) => { +const parseDiscogsUrl = (url) => { // https://regexr.com/3i5fa let discogsReleaseRegex = /([0-9]+(?:$|(?=\?)|(?=\/$)))/gm let result = discogsReleaseRegex.exec(url) if (!result) { throw new Error('Could not find id from Discogs URL') } - return result[0] + return { + id: result[0], + type: 'release' + } } -const findId = (url, provider) => { +const parseBandcampUrl = (url) => { + // https://regexr.com/46f84 + let bandcampRegex = /(album|track)(?:\/)([^\/\s\?]+)/gm + let result = bandcampRegex.exec(url) + if (!result) { + throw new Error('Could not find informations from Bandcamp URL') + } + return { + type: result[1], + id: result[2] + } +} + +const parseUrl = (url) => { + let provider = findProvider(url) let methods = { - youtube: (url) => youtubeUrlToId(url), - file: (url) => fileUrlToId(url), - discogs: (url) => discogsUrlToId(url) + youtube: (url) => parseYoutubeUrl(url), + file: (url) => parseFileUrl(url), + discogs: (url) => parseDiscogsUrl(url), + bandcamp: (url) => parseBandcampUrl(url) } - let extractId = methods[provider] - if (typeof extractId !== 'function') { - throw new Error('Could not find provider method from: ' + extractId) - } else { - return extractId(url) + let providerUrlParser = methods[provider] + + if (typeof providerUrlParser !== 'function') { + throw new Error(`Could not find a url parser for the provider: ${provider}, with url: ${url}`) + } + + const {id, type} = providerUrlParser(url) + return { + id, + type, + provider } } @@ -74,18 +110,15 @@ const mediaUrlParser = (inputUrl) => { // 0. normalize url, so it can be parsed homogenously const url = normalizeUrl(inputUrl) - // 1. detect which provider's url it is - let provider = findProvider(url) - - // 2. in this provider url, find a media `id` - let id = findId(url, provider) + // Parse the media provider url, to find: provider id, media id, media type + let {provider, id, type} = parseUrl(url) if (!id) { throw new Error('Could not detect id from: ' + url) } - // 3. return a result object - return { url, provider, id } + // 4. return a result object + return { url, provider, id, type } } export { diff --git a/src/providers.js b/src/providers.js index c5b1588..614b7ab 100644 --- a/src/providers.js +++ b/src/providers.js @@ -1,7 +1,8 @@ const providersList = { 'youtube.com': 'youtube', 'youtu.be': 'youtube', - 'discogs.com': 'discogs' + 'discogs.com': 'discogs', + 'bandcamp.com': 'bandcamp' } diff --git a/test.js b/test.js index 99eb1a3..264f743 100644 --- a/test.js +++ b/test.js @@ -1,12 +1,18 @@ import test from 'ava' import {mediaUrlParser} from './index.js' -import {youtubeDict, fileDict, discogsDict} from './tests/provider-dictionaries' +import {youtubeDict, fileDict, discogsDict, bandcampDict} from './tests/provider-dictionaries' /* Providers, check if they are correctly discovered in a url */ -test('Youtube URL correctly parse the provider', t => { +test('It throws when it cannot detect a provider', t => { + const error = t.throws(() => { + mediaUrlParser('notanurl') + }) +}) + +test('Youtube URL correctly parses the provider', t => { t.plan(youtubeDict.length) youtubeDict.forEach(item => { @@ -15,7 +21,7 @@ test('Youtube URL correctly parse the provider', t => { }) }) -test('object returned includes a normalized url property', t => { +test('Object returned includes a normalized url property', t => { youtubeDict.forEach(item => { let r = mediaUrlParser(item[0]) t.truthy(typeof r.url, 'string') @@ -23,7 +29,7 @@ test('object returned includes a normalized url property', t => { }) }) -test('File URL correctly parse the provider', async t => { +test('File URL correctly parses the provider', async t => { t.plan(fileDict.length) fileDict.forEach(item => { @@ -32,7 +38,7 @@ test('File URL correctly parse the provider', async t => { }) }) -test('Discogs URL correctly parse the provider', async t => { +test('Discogs URL correctly parses the provider', async t => { t.plan(discogsDict.length) discogsDict.forEach(item => { @@ -41,11 +47,20 @@ test('Discogs URL correctly parse the provider', async t => { }) }) +test('Bandcamp URL correctly parses the provider', async t => { + t.plan(bandcampDict.length) + + bandcampDict.forEach(item => { + let r = mediaUrlParser(item[0]) + t.is(r.provider, 'bandcamp') + }) +}) + /* ID, check if the if is found in a url of a specific provider */ -test('Youtube URL correctly parse the id correctly', t => { +test('Youtube URL correctly parses the id', t => { t.plan(youtubeDict.length) youtubeDict.forEach(item => { @@ -54,7 +69,7 @@ test('Youtube URL correctly parse the id correctly', t => { }) }) -test('File URL correctly parse the id correctly', t => { +test('File URL correctly parses the id', t => { t.plan(fileDict.length) fileDict.forEach(item => { @@ -63,17 +78,33 @@ test('File URL correctly parse the id correctly', t => { }) }) -test('It throws when it cant detect a provider', t => { - const error = t.throws(() => { - mediaUrlParser('notanurl') +test('Discogs URL correctly parses the id', t => { + t.plan(discogsDict.length) + + discogsDict.forEach(item => { + let r = mediaUrlParser(item[0]) + t.is(r.id, item[1]) }) }) -test('Discogs URL correctly parse the id correctly', t => { - t.plan(discogsDict.length) +test('Bandcamp URL correctly parses the id ', t => { + t.plan(bandcampDict.length) - discogsDict.forEach(item => { + bandcampDict.forEach(item => { let r = mediaUrlParser(item[0]) t.is(r.id, item[1]) }) }) + +/* + Type, check if the type is found in a url of a specific provider +*/ + +test('Bandcamp URL correctly parses the media type', async t => { + t.plan(bandcampDict.length) + + bandcampDict.forEach(item => { + let r = mediaUrlParser(item[0]) + t.is(r.type, item[2]) + }) +}) diff --git a/tests/provider-dictionaries.js b/tests/provider-dictionaries.js index 1af32db..53bcdfa 100644 --- a/tests/provider-dictionaries.js +++ b/tests/provider-dictionaries.js @@ -110,3 +110,16 @@ exports.discogsDict = [ '7983975' ] ] + +exports.bandcampDict = [ + [ + 'https://iliantape.bandcamp.com/album/it039-andrea-forse', + 'it039-andrea-forse', + 'album' + ], + [ + 'https://iliantape.bandcamp.com/track/future-atmo', + 'future-atmo', + 'track' + ] +]