Last active
March 17, 2024 16:28
-
-
Save artzub/02b1b91e5c16a76bdf6c4710dbc105f0 to your computer and use it in GitHub Desktop.
Revisions
-
artzub revised this gist
Feb 5, 2024 . 1 changed file with 23 additions and 13 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,29 +1,39 @@ const targetRootId = 'contents'; const lastVideoSelector = 'ytd-rich-grid-row:last-of-type ytd-rich-item-renderer:last-child'; const allVideosSelector = `.ytd-rich-grid-renderer#${targetRootId} ytd-rich-grid-media`; const rootNodeSelector = `ytd-rich-grid-renderer > #${targetRootId}`; const delay = (ms = 100) => new Promise((resolve) => { setTimeout(() => { resolve(true); }, ms) }); (async function() { let neededVideoId = prompt('Enter id of the last video', ''); if (!neededVideoId) { alert('The last vidoe id can not be empty'); return; } const checkWatched = async () => { await delay(3e3); console.log('find video by id:', neededVideoId); const found = document.querySelector(`a[href^="/watch?v=${neededVideoId}"]`); if (found) { console.log('found, stop observer'); observer.disconnect(); stageSecond(); return; } const lastVideo = document.querySelector(lastVideoSelector); console.log('last video:', lastVideo); if (lastVideo) { lastVideo.scrollIntoView(); } @@ -38,7 +48,7 @@ }; const stageSecond = async () => { let videos = Array.from(document.querySelectorAll(allVideosSelector)); if (neededVideoId) { const index = videos.findIndex(item => item.data.videoId === neededVideoId); @@ -58,10 +68,10 @@ `; }; const itemsContainer = document.querySelector(rootNodeSelector); const mutationListener = (mutationList, observer) => { const list = mutationList.filter(item => item.target.id === targetRootId); if (list.length > 0) { runWaiter(); @@ -72,5 +82,5 @@ observer.observe(itemsContainer, { childList: true, subtree: true }); await checkWatched(); })(); -
artzub revised this gist
Oct 20, 2022 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -15,7 +15,7 @@ const checkWatched = async () => { await delay(3e3); const found = document.querySelector(`a[href^="/watch?v=${neededVideoId}"]`); if (found) { observer.disconnect(); -
artzub revised this gist
Dec 13, 2021 . 1 changed file with 76 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,76 @@ (function addAll() { let neededVideoId = prompt('Enter id of the last video', ''); if (!neededVideoId) { alert('The last vidoe id can not be empty'); return; } const delay = (ms = 100) => new Promise((resolve) => { setTimeout(() => { resolve(true); }, ms) }); const checkWatched = async () => { await delay(3e3); const found = document.querySelector(`a[href="/watch?v=${neededVideoId}"]`); if (found) { observer.disconnect(); stageSecond(); return; } const lastVideo = document.querySelector('ytd-item-section-renderer:last-of-type ytd-grid-video-renderer:last-child'); if (lastVideo) { lastVideo.scrollIntoView(); } }; let timer; const runWaiter = () => { if (timer) { clearTimeout(timer); } timer = setTimeout(checkWatched, 2e3); }; const stageSecond = async () => { let videos = Array.from(document.querySelectorAll('#items > ytd-grid-video-renderer')); if (neededVideoId) { const index = videos.findIndex(item => item.data.videoId === neededVideoId); videos.splice(index, videos.length); } videos = videos .filter(item => !item.data.isWatched) .reverse() .map(video => `<tr><td>${video.data.videoId}</td></tr>`) ; document.body.innerHTML = ` <pre style="background: white; color: black"> ${videos.join('\n')} </pre> `; }; const itemsContainer = document.querySelector('ytd-section-list-renderer'); const mutationListener = (mutationList, observer) => { const list = mutationList.filter(item => item.target.id === 'items'); if (list.length > 0) { runWaiter(); } }; const observer = new MutationObserver(mutationListener); observer.observe(itemsContainer, { childList: true, subtree: true }); checkWatched(); })(); -
artzub created this gist
Dec 13, 2021 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,157 @@ function findPlaylist(compare) { let pageToken; while(true) { const list = YouTube.Playlists.list(['snippet'], { "maxResults": 50, "mine": true, ...(pageToken && { pageToken }) }); const item = list.items.find((row) => compare && compare(row)); if (item) { return item; } if (!list.nextPageToken) { return null; } pageToken = list.nextPageToken; } } function addPlaylist() { const title = `wl__${(new Date().getMonth()) + 1}`; const item = findPlaylist(({ snippet }) => snippet.title === title); if (item) { return item; } return YouTube.Playlists.insert( { 'snippet': { title, }, 'status': { 'privacyStatus': 'private' } }, 'snippet,status' ); } function insertVideo(playlistId, videoId) { return YouTube.PlaylistItems.insert( { "snippet": { playlistId, "resourceId": { "kind": "youtube#video", videoId } } }, 'snippet' ); } function run() { const spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); const sheet = spreadsheet.getSheets()[0]; const lastRow = sheet.getLastRow(); console.log({ lastRow }); if (lastRow < 1) { return; } // 199 because 1 request for insterting playlist const lastIndex = lastRow > 199 ? 199 : lastRow; console.log(`get range: A1:A${lastIndex}`); spreadsheet.toast(`get range: A1:A${lastIndex}`, "fill playlist"); let range = sheet.getRange(`A1:A${lastIndex}`); const rows = range.getValues().flat().filter(Boolean); console.log({ willProcessing: rows.length }); if (rows.length) { let lastAdded = 0; let error; let lastVideo; try { const pl = addPlaylist(); rows.forEach((videoId, index, arr) => { if (!videoId) { return; } try { insertVideo(pl.id, videoId, arr.length - index); lastVideo = videoId; } catch(err) { if (!err.message.includes('Video not found')) { throw err; } console.log('video not found', videoId); lastVideo = videoId; } lastAdded = index + 1; }); } catch(err) { error = err; } console.log({ lastAdded, lastVideo }); if (lastAdded > 0) { if (!lastVideo) { lastVideo = sheet.getRange('B1:B1').getValue(); } const row = sheet.getLastRow() || 1; if (lastAdded >= row) { lastAdded = row - 1; } console.log({ row, lastAdded }); if (lastAdded > 0) { sheet.deleteRows(1, lastAdded); } else { sheet.getRange('A1:A1').setValue(''); } sheet.getRange('B1:B1').setValue(lastVideo); } if (error) { throw error; } } } function init() { const spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); spreadsheet.removeMenu('YouTube'); spreadsheet.addMenu('YouTube', [ { name: 'fill playlist', functionName: 'run', } ]); } function onOpen() { init(); }