Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
SiddhantAttavar authored Aug 2, 2021
1 parent ffde035 commit 5175e99
Show file tree
Hide file tree
Showing 4 changed files with 276 additions and 0 deletions.
211 changes: 211 additions & 0 deletions autoconfirm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
const ynsTag = `[Youtube NonStop v${chrome.runtime.getManifest().version}]`;
const isYoutubeMusic = window.location.hostname === 'music.youtube.com';
const checkIfPausedTimeout = 2000; //timeout time to check if the video is paused after interaction
const idleTimeout = 3000; //time to pass without interaction to consider the page idle
const resetActedTime = 1000; //to avoid spamming clicks on the dialog
let lastInteractionTime = new Date().getTime();
let hasActedOnDialog = false;
let videoElement = null;
let isPausedByUser = false;
let documentObserver = null;
let isHoldingMouseDown = false; //to avoid taking action when mouse is being held down
let confirmDialogElement = isYoutubeMusic
? 'ytmusic-you-there-renderer'
: 'yt-confirm-dialog-renderer'; //the element that contains the confirm dialog
let isObservingDialog = false;
let dialogObserver = null;

const MutationObserver =
window.MutationObserver || window.WebKitMutationObserver;

function getTimestamp() {
let dt = new Date();
let time = dt.getHours() + ':' + dt.getMinutes() + ':' + dt.getSeconds();
return time;
}

function log(message) {
console.log(`${ynsTag}[${getTimestamp()}] ${message}`);
}

function debug(message) {
console.debug(`${ynsTag}[${getTimestamp()}] ${message}`);
}

/* INTERACTION LISTENERS */

function listenForMediaKeys() {
if (navigator.mediaSession === undefined) {
log("Your browser doesn't seem to support navigator.mediaSession yet :/");
return;
}
log('Listening for media keys...');
navigator.mediaSession.setActionHandler('pause', () => {
lastInteractionTime = new Date().getTime();
isPausedByUser = true;
if (videoElement !== null) {
videoElement.pause();
}
});

navigator.mediaSession.setActionHandler('play', () => {
lastInteractionTime = new Date().getTime();
if (videoElement !== null) {
videoElement.play();
}
});
}

function listenForMouse() {
document.addEventListener('click', (e) => {
if (e.isTrusted) {
lastInteractionTime = new Date().getTime();
isPausedByUser = true;
setTimeout(resetInteractionIfNotPaused, checkIfPausedTimeout);
}
});

document.addEventListener('mousedown', (e) => {
if (e.isTrusted) {
isHoldingMouseDown = true;
setTimeout(() => (isHoldingMouseDown = false), 10000); //as a last resort because depending on the action of the user the mouseup might not get fired
}
});

document.addEventListener('mouseup', (e) => {
if (e.isTrusted) {
isHoldingMouseDown = false;
}
});
}

function listenForKeyboard() {
document.addEventListener('keydown', (e) => {
if (e.isTrusted) {
lastInteractionTime = new Date().getTime();
isPausedByUser = true;
setTimeout(resetInteractionIfNotPaused, checkIfPausedTimeout);
}
});
}

function isIdle() {
let currTime = new Date().getTime();
debug(
`\ntime passed: ${
currTime - lastInteractionTime
}\nisPausedByUser: ${isPausedByUser}\nisHoldingMouseDown: ${isHoldingMouseDown}`
);
if (
currTime - lastInteractionTime <= idleTimeout ||
isPausedByUser ||
isHoldingMouseDown
) {
lastInteractionTime = new Date().getTime();
return false;
}
return true;
}

function resetInteractionIfNotPaused() {
if (videoElement == null) return;
if (!videoElement.paused) {
isPausedByUser = false;
}
}

/* ACTIONS */

function clickDialog() {
if (
document.querySelector(confirmDialogElement).parentElement.style.display !==
'none' &&
!hasActedOnDialog
) {
debug('Detected confirm dialog');
if (!isIdle()) return;

document
.querySelector(confirmDialogElement)
.querySelector('yt-button-renderer[dialog-confirm]')
.click();
hasActedOnDialog = true;
setTimeout(() => (hasActedOnDialog = false), resetActedTime);
debug('Clicked dialog!');
}
}

function unpauseVideo() {
if (!isIdle()) return;

videoElement.play();
debug('Unpaused video!');
}

/* OBSERVERS */

function observeElements() {
documentObserver = new MutationObserver((mutations, observer) => {
observeVideoElement();
observeDialog();
if (videoElement !== null && isObservingDialog) {
documentObserver.disconnect();
}
});

documentObserver.observe(document, {
childList: true,
subtree: true,
});
}

function observeDialog() {
if (dialogObserver == null) {
dialogObserver = new MutationObserver((mutations, observer) => {
clickDialog();
});
}

if (!isObservingDialog) {
const el = document.querySelectorAll(confirmDialogElement);
if (el.length === 1) {
dialogObserver.observe(el[0].parentElement, {
attributeFilter: ['style'],
}); //we want to observe the paper-dialog
debug('Monitoring confirmation dialog...');
isObservingDialog = true;
} else if (el.length > 1) {
log(
'YouTube changed something in the dialogs...!\nIf you see this message, contact the developer at ioannounikosdev@gmail.com'
);
}
}
}

function observeVideoElement() {
if (videoElement !== null) return;
if (document.querySelector('video') !== null) {
videoElement = document.querySelector('video');
listenForMediaKeys();
log('Monitoring video for pauses...');
videoElement.onpause = () => {
if (videoElement.ended) return;
debug('Detected paused video');
unpauseVideo();
};
videoElement.onplay = () => {
isPausedByUser = false;
};
}
}

log(
`Monitoring YouTube ${
isYoutubeMusic ? 'Music ' : ''
}for 'Confirm watching?' action...`
);

listenForMouse();
listenForKeyboard();

observeElements();
34 changes: 34 additions & 0 deletions background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
chrome.commands.onCommand.addListener(function (command) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
if (tabs[0]) {
var createOpts = {};
createOpts.index = tabs[0].index + 1;
createOpts.openerTabId = tabs[0].id;
chrome.tabs.create(createOpts, (createdTab) => {
if (tabs[0].groupId >= 0) {
var groupOpts = {};
groupOpts.groupId = tabs[0].groupId;
groupOpts.tabIds = createdTab.id;
chrome.tabs.group(groupOpts);
}
});
}
});
});

chrome.runtime.onInstalled.addListener(() => {
chrome.declarativeContent.onPageChanged.removeRules(undefined, () => {
chrome.declarativeContent.onPageChanged.addRules([{
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { hostEquals: 'www.youtube.com' }
}),
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { hostEquals: 'music.youtube.com' }
})
],
actions: [new chrome.declarativeContent.ShowPageAction()]
}
]);
});
});
Binary file added icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"manifest_version": 2,
"name": "Edge Customizer",
"description": "Provides various browser scripts",
"version": "1",
"permissions": ["tabs", "declarativeContent"],
"background": {
"scripts": ["background.js"]
},
"content_scripts": [
{
"matches": ["https://www.youtube.com/*", "https://music.youtube.com/*"],
"js": ["autoconfirm.js"],
"run_at": "document_end"
}
],
"incognito": "split",
"browser_action": {
"default_title": "Edge Customizer"
},
"icons": {"128": "icon.png"},
"commands": {
"new-tab-here": {
"suggested_key": {
"default": "Ctrl+T",
"mac": "MacCtrl+T"
},
"description": "Open a new tab next to the current one"
}
}
}

0 comments on commit 5175e99

Please sign in to comment.