Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add bandcamp parser, refactor naming, add type to parse answer #11

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 59 additions & 26 deletions main.js
Original file line number Diff line number Diff line change
@@ -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('/')
oskarrough marked this conversation as resolved.
Show resolved Hide resolved
let id = s[s.length - 1]
oskarrough marked this conversation as resolved.
Show resolved Hide resolved
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
}
}

Expand Down Expand Up @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion src/providers.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
const providersList = {
'youtube.com': 'youtube',
'youtu.be': 'youtube',
'discogs.com': 'discogs'
'discogs.com': 'discogs',
'bandcamp.com': 'bandcamp'
}


Expand Down
57 changes: 44 additions & 13 deletions test.js
Original file line number Diff line number Diff line change
@@ -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 => {
Expand All @@ -15,15 +21,15 @@ 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')
t.is(r.url.includes(item[0]), true)
})
})

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 => {
Expand All @@ -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 => {
Expand All @@ -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 => {
Expand All @@ -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 => {
Expand All @@ -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])
})
})
13 changes: 13 additions & 0 deletions tests/provider-dictionaries.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
]
]