From 68f5cf5430c4f7e43fbfb51177eb903b121911be Mon Sep 17 00:00:00 2001 From: piotrruss Date: Sun, 30 May 2021 21:31:39 +0200 Subject: added related videos search --- README.md | 4 +++- yta | 51 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 7737cd5..46ae690 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,9 @@ Command line player to listen to YT videos written in node Saves bandwidth and streams only the audio part of the videos # Requirements -Node.js and npm installed +1. Node.js and npm +2. mpv +3. youtube_dl # Before use 1. Install node packages with `npm i` diff --git a/yta b/yta index 851e849..bdee11e 100755 --- a/yta +++ b/yta @@ -20,20 +20,26 @@ const showOsd = () => { console.log(''); }; -const showPlaying = (n) => console.log(`${colors.green('Currently playing:\n------------------')}\n${colors.yellow('Title:')} ${colors.cyan(data.titles[n])}\n${colors.yellow('Description:')} ${colors.cyan(data.descriptions[n])}\n${colors.yellow('Channel:')} ${colors.cyan(data.channels[n])}\n${colors.yellow('Length:')} ${colors.cyan(data.durations[n])}\n`); +const showPlaying = n => console.log(`${colors.green('Currently playing:\n------------------')}\n${colors.yellow('Title:')} ${colors.cyan(data.titles[n])}\n${colors.yellow('Description:')} ${colors.cyan(data.descriptions[n])}\n${colors.yellow('Channel:')} ${colors.cyan(data.channels[n])}\n${colors.yellow('Length:')} ${colors.cyan(data.durations[n])}\n`); const showPlaylist = (r,n) => console.log(r.map(x=>x===n?(colors.yellow(x+'. '+data.titles[x-1])):(colors.cyan(x+'. '+data.titles[x-1]))).join('\n'),'\n'); -const showHelp = () => console.log(colors.green('YT audio player\n---------------\n1. Type song name and press [ENTER] to search it in YT\n2. Type result number and press [ENTER] to play the song\n3. Type a range of songs (ex. [2-5]) to play them in a row\n4. Type "h" and press [ENTER] to see this help page\n5. Type "q" and press [ENTER] to quit YT audio player\n')); +const showHelp = () => console.log(colors.green('YT audio player\n---------------\n1. Type song name and press [ENTER] to search it in YT\n2. Type result number and press [ENTER] to play the song\n3. Type a range of songs (ex. [2-5]) to play them in a row\n4. Type [r(nr)] (ex. [r2]) to find songs related to chosen result\n5. Type [h] and press [ENTER] to see this help page\n6. Type [q] and press [ENTER] to quit YT audio player\n')); -const searchUrl = (q) => `https://www.googleapis.com/youtube/v3/search?part=snippet&partcontentDetails&maxResults=20&q=${q}&type=video&key=${YTKEY}`; +const apiUrl = 'https://www.googleapis.com/youtube/v3'; -const detailsUrl = (a) => `https://www.googleapis.com/youtube/v3/videos?part=contentDetails&id=${a.join(',')}&key=${YTKEY}`; +const searchUrl = q => `${apiUrl}/search?part=snippet&maxResults=20&q=${q}&type=video&key=${YTKEY}`; + +const detailsUrl = a => `${apiUrl}/videos?part=contentDetails&id=${a.join(',')}&key=${YTKEY}`; + +const relatedUrl = i => `${apiUrl}/search?part=snippet&maxResults=20&relatedToVideoId=${i}&type=video&key=${YTKEY}`; const isSongRange = q => q.match(/^[0-9]+-[0-9]+$/); const isSongName = q => q.match(/.{3,}/); +const isRelated = q => q.match(/^r[0-9]+$/) && parseInt(q.replace('r','')) <= data.ids.length; + const isSongNumber = q => q.match(/^[0-9]+$/) && parseInt(q) <= data.ids.length; const playNr = (n) => spawn('mpv', ['--no-video', '--msg-level=all=no,statusline=status', `https://www.youtube.com/watch?v=${data.ids[parseInt(n)]}`], { stdio: 'inherit' }); @@ -76,12 +82,11 @@ const handleSongRange = (q) => { } }; -const handleSongName = (q) => ( - fetch(searchUrl(q)) - .then(res => res.json()) - .then(json => presentResults(json)) - .catch(e => console.log(e)) -); +const handleSongName = q => getSongs(q); + +const handleRelated = q => { + return getRelated(parseInt(q.replace('r','')) - 1); +} const handleSongNumber = (q) => { const nr = parseInt(q) - 1; @@ -114,18 +119,22 @@ const handleWrongInput = () => { showPrompt(); }; -const getDurations = (ids) => ( - fetch(detailsUrl(ids)) - .then(res => res.json()) - .then(json => json.items.map(i => i.contentDetails.duration.replace(/(PT|S)/g,'').split(/[A-Z]/g).map(d => d.padStart(2, '0')).join(':'))) - .catch(e => console.log(e)) -); +const formatTime = i => i.contentDetails.duration.replace(/(PT|S)/g,'').split(/[A-Z]/g).map(d => d.padStart(2, '0')).join(':'); + +const getJson = (url) => fetch(url).then(res => res.json()).catch(e => console.log(e)); + +const getSongs = (q) => getJson(searchUrl(q)).then(json => presentResults(json)); + +const getRelated = (n) => getJson(relatedUrl(data.ids[n])).then(json => presentResults(json)); + +const getDurations = (ids) => getJson(detailsUrl(ids)).then(json => json.items.map(formatTime)); const presentResults = (results) => { - data.titles = results.items.map(result => result.snippet.title); - data.descriptions = results.items.map(result => result.snippet.description); - data.channels = results.items.map(result => result.snippet.channelTitle); - data.ids = results.items.map(result => result.id.videoId); + const items = results.items.filter(i => i.snippet); + data.titles = items.map(i => i.snippet.title); + data.descriptions = items.map(i => i.snippet.description); + data.channels = items.map(i => i.snippet.channelTitle); + data.ids = items.map(i => i.id.videoId); getDurations(data.ids).then(durations => { data.durations = durations; clearOutput(); @@ -142,6 +151,8 @@ const handlePrompt = (err, { query }) => { if (isSongRange(query)) { handleSongRange(query); + } else if (isRelated(query)) { + handleRelated(query); } else if (isSongName(query)) { handleSongName(query); } else if (isSongNumber(query)) { -- cgit v1.2.3