Enhancements for Le Show
// ==UserScript== // @name Le Show Enhancements // @author Than // @version 0.03 // @description Enhancements for Le Show // @match https://harryshearer.com* // @include https://harryshearer.com* // @connect harryshearer.com // @grant GM.xmlHttpRequest // @grant unsafeWindow // @grant GM_addStyle // @grant GM_setClipboard // @run-at document-end // @namespace https://greasyfork.org/users/288098 // ==/UserScript== //0.3 - Added skip forward and skip back. And hopefully fixed a bug where my phone keeps the volume too quiet after skipping a song. //0.2 - published script (function() { 'use strict'; /*-------------------------------------------------------------------------------------------------------------------- ------------------------------------------- General functions -------------------------------------------------- --------------------------------------------------------------------------------------------------------------------*/ // not currently using anything here /*-------------------------------------------------------------------------------------------------------------------- ------------------------------------------- Init functions -------------------------------------------------- --------------------------------------------------------------------------------------------------------------------*/ init(); // kick things off function init(){ enhanceIndividualShowPage(); // fixes audio stuff on individual le show pages. Skips songs, prevents looping. } function enhanceIndividualShowPage(){ if (!document.URL.includes("/le-shows/")){return} // if it's not an individual show page, return var audio = document.querySelector("audio"); // grab the audio tag from the page var goodTimestampArray = getTimestampArr(); // make an array of "good" timestamps - a list full of seconds where harry is talking and not playing music // console.log(goodTimestampArray); audio.addEventListener("timeupdate",progressUpdated); // as the progress bar var currentTime; // global variable to store the current progress of the episode var gracePeriod = false; // if set to true, the script won't skip the song (assuming it's the grace period, last 30 seconds of the song. addSkipButtons(); function addSkipButtons(){ // adds buttons to skip forward & back ten seconds var skipDiv = document.createElement("div"); skipDiv.innerHTML = `<button id="rewind">⏪</button><button id="fast_forward">⏩</button>`; // creating our skip buttons var container = document.querySelector(".jp-type-playlist"); // choosing which container they'll go in var insertBeforeThis = container.querySelector("h3"); // we'll put our buttons above the "Music & Segments" H3 element container.insertBefore(skipDiv, insertBeforeThis); // insert the buttons skipDiv.addEventListener("click",skipClickHandler); // add their click logic function skipClickHandler(e){ if (e.target == e.currentTarget){return} // ignores any clicks on the skipDiv itself var clicked = e.target; // what did the user click? // console.log(clicked); if (clicked.id === "rewind" || clicked.parentNode.id === "rewind"){ // user clicked the rewind button audio.currentTime = audio.currentTime - 10; // skip back 10 seconds } else if (clicked.id === "fast_forward" || clicked.parentNode.id === "fast_forward"){ // user clicked the fast forward button audio.currentTime = audio.currentTime + 20; // skip forward 20 seconds } } } async function fadeAudioOut(skipTo) { gracePeriod = true; var audio = document.querySelector("audio"); var fadeOut = setInterval(volDown, 200); function volDown() { if (audio.volume <= 0.1) { console.log("cancelling fade out") clearInterval(fadeOut); audio.currentTime = skipTo; fadeAudioIn(); } else { console.log("ducking audio") audio.volume = audio.volume - 0.03; } } } async function fadeAudioIn() { var audio = document.querySelector("audio"); var fadeIn = setInterval(volUp, 400); function volUp() { if (audio.volume >= 0.8) { console.log("finished fading in"); audio.volume = 1; // set volume to max clearInterval(fadeIn); // gracePeriod = false; } else { console.log("upping audio") audio.volume = audio.volume + 0.1; } } } async function progressUpdated(){ var timestamp = Math.floor(audio.currentTime); // grab the current progress of the episode if (currentTime > 3300 && timestamp == 0){audio.pause()} // If the previous second was at the end of the episode, and the current second is at the beginning, pause so it doesn't loop if (currentTime == timestamp){return} // this whole function runs every time the event handler updates, which is 4 times per second. We don't want to iterate through the goodTimestampArray 4 times per second, so we do it once per second currentTime = timestamp; // now it's ok to update the time // console.log(timestamp); if (goodTimestampArray.includes(timestamp)){ gracePeriod = false; return} // if the current second is in the "good" timestamp array, never mind we're all good if (gracePeriod){return} // we're in the grace period part of the song. Return. for (var i=0,j = goodTimestampArray.length;i<j;i++){ // otherwise, loop through the array if (goodTimestampArray[i] > timestamp){ // look for the first array value which is bigger than the current time fadeAudioOut(goodTimestampArray[i] - 30); // audio.currentTime = goodTimestampArray[i]-30; // skip to that value break; // no need to loop any more } } } function getTimestampArr(){ // make an array of "good" timestamps, where harry is talking and not playing music var timestampDomElements = document.querySelector(".jp-playlist").querySelectorAll(".time"); // all timestamps for the episode var musicTimestampDomElements = document.querySelector(".other-list").querySelectorAll(".time"); // just the music timestamps var musicStartTimeArray = []; // this will be populated with the timestamps of the music we want to skip for (var i=0,j = musicTimestampDomElements.length-1;i<j;i++){ // -1 so as to allow the instrumental at the end of the broadcast to play. For each music timestamp if (musicTimestampDomElements[i].nextElementSibling.textContent.includes("Harry Shearer")){continue} // if it's Harry's own song, don't skip it var musicStartTime = convertTimeToSeconds(musicTimestampDomElements[i].textContent); // convert the time to seconds musicStartTimeArray.push(musicStartTime); // push the timestamp into our array of music to skip } // console.log(musicStartTimeArray); var goodTimeArray = []; // this will be populated with a list of seconds which don't contain music for (var k=0,l = timestampDomElements.length;k<l;k++){ // for each timestamp dom element var startTime = convertTimeToSeconds(timestampDomElements[k].textContent); // convert the timestamp to seconds var endTime; // populate this with the end time, which depends on a couple of factors if (timestampDomElements[k+1]){ // if there's a next timestamp in the dom endTime = convertTimeToSeconds(timestampDomElements[k+1].textContent); // make that the end time } else { // otherwise endTime = 3900; // no more timestamps, it's the end of the podcast. Hard coded 3900 cos that's the absolute max duration of the show } if (musicStartTimeArray.includes(startTime)){ // if the start time of this element is the same as a music start time continue; // don't add this chunk of seconds to the array } addGoodTimestampsToArr(goodTimeArray,startTime,endTime); // add this timestamp & all the seconds up to & including its endtime to the goodTimeArray //addGoodTimestampsToArray(array,startTime,endTime); } return goodTimeArray; // send this array back } function convertTimeToSeconds(timestamp){ // simple function to convert a timestamp to seconds (taken from the website's own code!) var timeSplit = timestamp.split(":"); var timeInSeconds = (parseFloat(timeSplit[0]) * 60) + parseFloat(timeSplit[1]); return timeInSeconds; } function addGoodTimestampsToArr(array,startTime,endTime){ // feed this function the array you wan to update, the start time & the end time for (var i = parseInt(startTime); i <= parseInt(endTime); i++) { // for every number from start time to end time array.push(i); // push those numbers to the array } } } // not currently setting styles, but we might! var globalStyle = ` #rewind,#fast_forward{ width: 60px; height: 50px; padding: 5px; margin: 5px; font-size: 30px; background-color: #fda732; } ` GM_addStyle(globalStyle) // Your code here... })();