Skip to content

Commit

Permalink
Simplify youtube searching and remove references to youtube api key
Browse files Browse the repository at this point in the history
  • Loading branch information
nukeop committed Jan 8, 2021
1 parent 443d6d4 commit 67b0607
Show file tree
Hide file tree
Showing 20 changed files with 332 additions and 402 deletions.
3 changes: 1 addition & 2 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,4 @@ INVIDIOUS_URL=https://invidious.snopyta.org
JAMENDO_CLIENT_ID=836523a7
LAST_FM_API_KEY=2b75dcb291e2b0c9a2c994aca522ac14
LAST_FM_API_SECRET=2ee49e35f08b837d43b2824198171fc8
SOUNDCLOUD_API_KEY=22e8f71d7ca75e156d6b2f0e0a5172b3
YOUTUBE_API_KEY=AIzaSyCkMLHynwJgJYQoGaIResXZxKUbC2euFfw
SOUNDCLOUD_API_KEY=22e8f71d7ca75e156d6b2f0e0a5172b3
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion packages/app/app/globals.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
module.exports = {
invidiousUrl: process.env.INVIDIOUS_URL,
ytApiKey: process.env.YOUTUBE_API_KEY,
lastfmApiKey: process.env.LAST_FM_API_KEY,
lastfmApiSecret: process.env.LAST_FM_API_SECRET,
soundcloudApiKey: process.env.SOUNDCLOUD_API_KEY,
Expand Down
35 changes: 14 additions & 21 deletions packages/app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
"semantic-ui-react": "^0.88.2",
"simple-get-lyrics": "0.0.4",
"youtube-playlist": "^1.0.2",
"ytdl-core": "^3.3.0"
"ytdl-core": "^4.4.1"
},
"devDependencies": {
"@babel/core": "^7.9.0",
Expand Down
54 changes: 27 additions & 27 deletions packages/core/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"react-dom": "^16.12.0",
"redux": "^4.0.5",
"simple-get-lyrics": "0.0.4",
"youtube-playlist": "^1.0.2"
"youtube-playlist": "^1.0.2",
"ytsr": "^3.2.1"
},
"devDependencies": {
"@types/isomorphic-fetch": "0.0.35",
Expand All @@ -43,7 +44,7 @@
"mock-require": "^3.0.3",
"ts-node": "^8.10.2",
"typescript": "^3.9.7",
"ytdl-core": "^3.3.0"
"ytdl-core": "^4.4.1"
},
"ava": {
"files": [
Expand Down
70 changes: 15 additions & 55 deletions packages/core/src/plugins/stream/YoutubePlugin.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import logger from 'electron-timber';
import _ from 'lodash';
import ytdl from 'ytdl-core';

import { StreamData, StreamQuery } from '../plugins.types';
import { StreamQuery } from '../plugins.types';
import StreamProviderPlugin from '../streamProvider';
import * as Youtube from '../../rest/Youtube';

class YoutubePlugin extends StreamProviderPlugin {
constructor() {
super();
Expand All @@ -16,61 +13,24 @@ class YoutubePlugin extends StreamProviderPlugin {
this.isDefault = true;
}

search(query: StreamQuery): Promise<StreamData | void> {
async search(query: StreamQuery) {
const terms = query.artist + ' ' + query.track;
return Youtube.trackSearch(terms)
.then(results => results.json())
.then(results => {
const song: { id: { videoId: string }} = _.head(results.items);
const id = song.id.videoId;
return ytdl.getInfo(`https://www.youtube.com/watch?v=${id}`);
})
.then(videoInfo => {
let thumbnail = _.get(videoInfo, 'player_response.videoDetails.thumbnail.thumbnails');
thumbnail = _.find(thumbnail, { width: 246 }).url;
const formatInfo = _.head(videoInfo.formats.filter(e => e.itag === 140));

return {
source: this.sourceName,
id: videoInfo.video_id,
stream: formatInfo.url,
duration: parseInt(videoInfo.length_seconds),
title: videoInfo.title,
thumbnail
};
})
.catch(error => {
logger.error(`Error while searching for ${terms} on Youtube`);
logger.error(error);
});
try {
return await Youtube.trackSearch(query, undefined, this.sourceName);
} catch (e) {
logger.error(`Error while searching for ${terms} on Youtube`);
logger.error(e);
}
}

getAlternateStream(query: StreamQuery, currentStream: { id: string }): Promise<StreamData | void> {
async getAlternateStream(query: StreamQuery, currentStream: { id: string }) {
const terms = query.artist + ' ' + query.track;
return Youtube.trackSearch(terms)
.then(results => results.json())
.then(results => {
const song = _(results.items).find(item => {
return item && item.id.videoId !== currentStream.id;
});
const id = song.id.videoId;
return ytdl.getInfo(`https://www.youtube.com/watch?v=${id}`);
})
.then(videoInfo => {
const formatInfo = _.head(videoInfo.formats.filter(e => e.itag === 140));
return {
source: this.sourceName,
id: videoInfo.video_id,
stream: formatInfo.url,
duration: parseInt(videoInfo.length_seconds),
title: videoInfo.title,
thumbnail: videoInfo.thumbnail_url
};
})
.catch(error => {
logger.error(`Error while looking up streams for ${terms} on Youtube`);
logger.error(error);
});
try {
return await Youtube.trackSearch(query, currentStream.id, this.sourceName);
} catch (e) {
logger.error(`Error while looking up streams for ${terms} on Youtube`);
logger.error(e);
}
}
}

Expand Down
50 changes: 37 additions & 13 deletions packages/core/src/rest/Youtube.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import LastFmApi from './Lastfm';
import _ from 'lodash';
import getArtistTitle from 'get-artist-title';
import ytdl from 'ytdl-core';

import ytlist from 'youtube-playlist';
import getArtistTitle from 'get-artist-title';
import ytsr from 'ytsr';

import { trackSearch } from './youtube-search';
import LastFmApi from './Lastfm';
import { StreamQuery } from '../plugins/plugins.types';

const lastfm = new LastFmApi(
process.env.LAST_FM_API_KEY,
process.env.LAST_FM_API_SECRET
);

export { trackSearch };

function isValidURL (str) {
function isValidURL(str) {
const pattern = new RegExp('^(https?:\\/\\/)' + // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name and extension
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
Expand All @@ -24,7 +23,7 @@ function isValidURL (str) {
return pattern.test(str);
}

function analyseUrlType (url) {
function analyseUrlType(url) {
const analysisResult = {
url,
isValid: false,
Expand All @@ -42,7 +41,7 @@ function analyseUrlType (url) {
return analysisResult;
}

function getTrackFromTitle (title) {
function getTrackFromTitle(title) {
const result = getArtistTitle(title);
if (result) {
return lastfm.searchTracks(result[0] + ' ' + result[1], 1)
Expand All @@ -59,7 +58,7 @@ function getTrackFromTitle (title) {
}
}

function handleYoutubePlaylist (url) {
function handleYoutubePlaylist(url) {
return ytlist(url, 'name')
.then(res => {
const allTracks = res.data.playlist.map((elt) => {
Expand All @@ -74,10 +73,10 @@ function handleYoutubePlaylist (url) {
});
}

function handleYoutubeVideo (url) {
function handleYoutubeVideo(url) {
return ytdl.getInfo(url)
.then(info => {
return getTrackFromTitle(info.title)
return getTrackFromTitle(info.videoDetails.title)
.then(track => {
return [track];
});
Expand All @@ -87,7 +86,7 @@ function handleYoutubeVideo (url) {
});
}

export function urlSearch (url) {
export function urlSearch(url) {
const urlAnalysis = analyseUrlType(url);
if (urlAnalysis.isYoutubePlaylist) {
return handleYoutubePlaylist(url);
Expand All @@ -99,3 +98,28 @@ export function urlSearch (url) {
});
}
}

export async function trackSearch(query: StreamQuery, omitStreamId?: string, sourceName?: string) {
const terms = query.artist + ' ' + query.track;
return trackSearchByString(terms, omitStreamId, sourceName);
}

export async function trackSearchByString(query: string, omitStreamId?: string, sourceName?: string) {
const results = await ytsr(query);
const topTrack: ytsr.Video = _.find(
results.items,
item => item.type === 'video' && (!omitStreamId || item.id !== omitStreamId)
) as ytsr.Video;
const topTrackInfo = await ytdl.getInfo(topTrack.url);
const formatInfo = ytdl.chooseFormat(topTrackInfo.formats, { quality: 'highestaudio' });

return {
source: sourceName,
id: topTrack.id,
stream: formatInfo.url,
duration: parseInt(topTrackInfo.videoDetails.lengthSeconds),
title: topTrackInfo.videoDetails.title,
thumbnail: topTrack.bestThumbnail.url,
format: formatInfo.container
};
}
Loading

0 comments on commit 67b0607

Please sign in to comment.