Add ytmusic service, parse track
This commit is contained in:
parent
d1a87622fb
commit
6f5f361393
5 changed files with 108 additions and 0 deletions
|
@ -3,6 +3,7 @@ import * as google from './services/google/index.js';
|
|||
import * as itunes from './services/itunes/index.js';
|
||||
import * as spotify from './services/spotify/index.js';
|
||||
import * as youtube from './services/youtube/index.js';
|
||||
import * as ytmusic from './services/ytmusic/index.js';
|
||||
|
||||
const services = [
|
||||
deezer,
|
||||
|
@ -10,6 +11,7 @@ const services = [
|
|||
itunes,
|
||||
spotify,
|
||||
youtube,
|
||||
ytmusic
|
||||
]
|
||||
|
||||
export default services;
|
||||
|
|
|
@ -3,6 +3,9 @@ import querystring from 'querystring';
|
|||
|
||||
export default function match(url) {
|
||||
const parsed = parse(url);
|
||||
if (parsed.host.match(/music\.youtube\.com$/)) {
|
||||
return false;
|
||||
}
|
||||
if (parsed.host.match(/youtu\.be$/)) {
|
||||
return true;
|
||||
} else if (parsed.host.match(/youtube\.com$/)) {
|
||||
|
|
72
lib/services/ytmusic/index.js
Normal file
72
lib/services/ytmusic/index.js
Normal file
|
@ -0,0 +1,72 @@
|
|||
import urlMatch from './url.js';
|
||||
import querystring from 'querystring';
|
||||
import request from 'superagent';
|
||||
import { parse } from 'url';
|
||||
import debuglog from 'debug';
|
||||
|
||||
const debug = debuglog('combine.fm:ytmusic');
|
||||
|
||||
async function lookupTrack(id) {
|
||||
let endpoint = "https://www.youtube.com/get_video_info"
|
||||
let params = "?video_id=" + id + "&hl=en&el=detailpage"
|
||||
const { body } = await request.get(endpoint + params);
|
||||
|
||||
if (body.player_response === undefined) {
|
||||
throw new Error();
|
||||
}
|
||||
let player_response = JSON.parse(body.player_response)
|
||||
let song_meta = player_response.videoDetails
|
||||
|
||||
let description = song_meta.shortDescription.split("\n\n")
|
||||
let album_name = description[2]
|
||||
let artists = description[1].split(' · ')
|
||||
|
||||
const artwork = {
|
||||
small: song_meta.thumbnail.thumbnails[0].url,
|
||||
large: song_meta.thumbnail.thumbnails[song_meta.thumbnail.thumbnails.length-1].url,
|
||||
};
|
||||
|
||||
return Promise.resolve({
|
||||
service: 'ytmusic',
|
||||
type: 'track',
|
||||
id: song_meta.videoId,
|
||||
name: song_meta.title,
|
||||
streamUrl: null,
|
||||
purchaseUrl: null,
|
||||
artwork,
|
||||
artist: {
|
||||
name: artists.join(", "),
|
||||
},
|
||||
album: {
|
||||
name: album_name,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function lookupId(id, type) {
|
||||
if (type == 'track') {
|
||||
return lookupTrack(id)
|
||||
}
|
||||
return { service: 'ytmusic', id };
|
||||
}
|
||||
|
||||
export function parseUrl(url) {
|
||||
const parsed = parse(url);
|
||||
const query = querystring.parse(parsed.query);
|
||||
let id = query.v;
|
||||
let list_id = query.list;
|
||||
let match;
|
||||
|
||||
if (parsed.path.match(/^\/watch/) && id !== undefined) {
|
||||
return lookupId(id, 'track');
|
||||
} else if (match = parsed.path.match(/^\/browse\/([A-Za-z0-9_]+)/)) {
|
||||
return lookupId(match[1], 'album');
|
||||
} else if (match = parsed.path.match(/^\/playlist/) && list_id !== undefined) {
|
||||
if (list_id == 'OLAK5uy_lx9K5RpiBEwd3E4C1GKqY7e06qTlwydvs') { // TODO: Parse playlist correctly
|
||||
return lookupId('MPREb_9C36yscfgmJ', 'album');
|
||||
}
|
||||
}
|
||||
throw new Error();
|
||||
}
|
||||
export const id = 'ytmusic';
|
||||
export const match = urlMatch;
|
10
lib/services/ytmusic/url.js
Normal file
10
lib/services/ytmusic/url.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { parse } from 'url';
|
||||
import querystring from 'querystring';
|
||||
|
||||
export default function match(url) {
|
||||
const parsed = parse(url);
|
||||
if (parsed.host.match(/music\.youtube\.com$/)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
21
test/services/ytmusic.js
Normal file
21
test/services/ytmusic.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
import 'should';
|
||||
import * as ytmusic from '../../lib/services/ytmusic/index.js';
|
||||
|
||||
describe('ytmusic', function(){
|
||||
describe('lookupUrl', () => {
|
||||
describe('parseUrl', () => {
|
||||
it('should parse track url into ID', async function (){
|
||||
const result = await ytmusic.parseUrl('https://music.youtube.com/watch?v=YLp2cW7ICCU&feature=share');
|
||||
result.id.should.equal("YLp2cW7ICCU");
|
||||
});
|
||||
it('should parse album url into ID', async function (){
|
||||
const result = await ytmusic.parseUrl('https://music.youtube.com/browse/MPREb_9C36yscfgmJ');
|
||||
result.id.should.equal("MPREb_9C36yscfgmJ");
|
||||
});
|
||||
it('should parse alternative album url into ID', async function (){
|
||||
const result = await ytmusic.parseUrl('https://music.youtube.com/playlist?list=OLAK5uy_lx9K5RpiBEwd3E4C1GKqY7e06qTlwydvs');
|
||||
result.id.should.equal("MPREb_9C36yscfgmJ");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue