Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
9 changes: 9 additions & 0 deletions desktopFiles/ytdlp-downloader.desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[Desktop Entry]
Type=Application
Name=Video Downloader
Exec=bash -c 'arg=$0; arg=${arg/"https//"/"https://"}; clean_url=${arg:19}; echo "Download URL: $clean_url"; yt-dlp -f "best[height<=1080]/best" --output "$HOME/Downloads/%(title)s.%(ext)s" "$clean_url" || (echo "ERROR: Download failed for URL: $clean_url" && echo "Raw arg: $arg"; echo "Raw link:" $0 && sleep 5)' "%u"
StartupNotify=true
MimeType=x-scheme-handler/ytdlp-downloader
Terminal=true # Change to false after testing for background runs
Hidden=false
Icon=download
90 changes: 90 additions & 0 deletions userscript/mpvOdysee.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// ==UserScript==
// @name Odysee MPV Player
// @version 0.2
// @description This little script opens any Odysee video in MPV with a simple button click
// @author TibixDev
// @match https://odysee.com/*
// @icon https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Odysee_Logo.svg/1200px-Odysee_Logo.svg.png
// @grant GM_addStyle
// ==/UserScript==

(async function () {
'use strict';
console.log("[YTMPV] Odysee MPV player script loaded");
let urlRegex = /^https:\/\/(www\.)?odysee\.com\/@[^:]+:[^\/]+\/[^:]+:[^\/]*$/

function setButtonInterval() {
return setInterval(() => {
//console.log("pooling menu container");
if (document.querySelector(".card__body>.media__subtitle--between>.media__actions")) {
console.log("[YTMPV] Menu container found, executing...");
addMpvButton()
}
}, 2000);
}

let waitForButtons = null;

let location = window.location.href;;
if (location.match(urlRegex)) {
waitForButtons = setButtonInterval();
console.log("[YTMPV] Starting video link correct: " + location);
}

function handleVideoUrlChange(newUrl) {
if (location !== newUrl && window.location.href.match(urlRegex) && !waitForButtons) {
console.log("[YTMPV] Video URL detected, toggling waitForButtons...");
waitForButtons = setButtonInterval();
location = newUrl;
}
}

document.addEventListener('click', (e) => {
//console.log("click");
// Optional: Skip if clicking your button or specific elements

if (e.target.id === "mpv-button") {
return; // Don't refresh on MPV button clicks
}
setTimeout(() => {
handleVideoUrlChange(window.location.href);
}, 100);
}, true);

function addMpvButton() {
clearInterval(waitForButtons);
waitForButtons = null;
const ytButtons = document.querySelector(".card__body>.media__subtitle--between>.media__actions");
const ytButton = document.createElement("button");
ytButton.id = "mpv-button";
ytButton.classList.add("button", "button--no-style", "button--file-action");
const mpvBtnStyle = `
#mpv-button {
margin-right: 10px;
}`

const styleElem = document.createElement("style");
if (styleElem.styleSheet) {
styleElem.styleSheet.cssText = mpvBtnStyle;
} else {
styleElem.appendChild(document.createTextNode(mpvBtnStyle));
}
document.getElementsByTagName('head')[0].appendChild(styleElem);
//ytButton.style.cssText = "margin-right: 10px;";
ytButton.textContent = "▶ MPV";
ytButton.addEventListener("click", () => {
document.querySelector("video").pause();
document.location = "mpv://" + document.location.href;
ytButton.textContent = "⌛ Opening...";
ytButton.style.cssText = "background-color: #0a6dab;";
setTimeout(() => {
ytButton.textContent = "▶ MPV";
ytButton.style.cssText = "";
}, 3000);
});

ytButtons.appendChild(ytButton);
console.log("[YTMPV] MPV button added");
console.log(ytButton, ytButtons);
}
})();
49 changes: 21 additions & 28 deletions userscript/mpv.js → userscript/mpvYouTube.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,64 +14,57 @@

function setButtonInterval() {
return setInterval(() => {
if (document.querySelector("#info>#menu-container>#menu>ytd-menu-renderer>#top-level-buttons-computed>ytd-toggle-button-renderer")) {
if (document.querySelector("#actions>#actions-inner>#menu>ytd-menu-renderer>#top-level-buttons-computed>yt-button-view-model")) {
console.log("[YTMPV] Menu container found, executing...");
addMpvButton()
}
}, 1000);
}, 2000);
}

// let waitForButtons = setButtonInterval();
let waitForButtons = null;

let location = window.location.href;;
let location = window.location.href;
if (location.match(/^https:\/\/www\.youtube\.com\/watch\?v=([^&]*)/)) {
waitForButtons = setButtonInterval();
console.log("[YTMPV] Video link correct: " + location);
}

let waitForUrlChange = setInterval(() => {
if (location !== window.location.href && window.location.href.includes("watch?v=") && !waitForButtons) {
function handleVideoUrlChange(newUrl) {
if (location !== newUrl && newUrl.includes("watch?v=") && !waitForButtons) {
console.log("[YTMPV] Video URL detected, toggling waitForButtons...");
waitForButtons = setButtonInterval();
location = window.location.href;
location = newUrl;
}
}, 1000);
}

// Listen for YouTube's navigation finish event
window.addEventListener('yt-navigate-finish', () => {
// Small delay to ensure URL and content are settled
setTimeout(() => {
handleVideoUrlChange(window.location.href);
}, 100);
});

function addMpvButton() {
clearInterval(waitForButtons);
waitForButtons = null;
const ytButtons = document.querySelector("#info>#menu-container>#menu>ytd-menu-renderer>#top-level-buttons-computed");
const ytButtons = document.querySelector("#actions>#actions-inner>#menu>ytd-menu-renderer>#top-level-buttons-computed");
const ytButton = document.createElement("button");
ytButton.id = "mpv-button";
ytButton.classList.add("ytSpecButtonViewModelHost", "style-scope", "ytd-menu-renderer", "yt-spec-button-shape-next", "yt-spec-button-shape-next--tonal", "yt-spec-button-shape-next--mono", "yt-spec-button-shape-next--size-m", "yt-spec-button-shape-next--icon-leading", "yt-spec-button-shape-next--enable-backdrop-filter-experiment");
const mpvBtnStyle = `
#mpv-button {
color: white;
cursor: pointer;
background-color: #043565;
border-radius: 10px;
margin-left: 10px;
margin-right: 10px;
padding-left: 10px;
padding-right: 10px;
font-size: var(--ytd-tab-system-font-size);
font-weight: var(--ytd-tab-system-font-weight);
font-family: Roboto, Arial, sans-serif;
border: 0;
transition: all 0.2s ease-in-out;
}

#mpv-button:hover {
background-color: #0a6dab;
}`

const styleElem = document.createElement("style");
if (styleElem.styleSheet) {
styleElem.styleSheet.cssText = mpvBtnStyle;
} else {
styleElem.appendChild(document.createTextNode(mpvBtnStyle));
}
document.getElementsByTagName('head')[0].appendChild(styleElem);
// ytButton.style.cssText = mpvBtnStyle;
//ytButton.style.cssText = "margin-left: 10px;";
ytButton.textContent = "▶ MPV";
ytButton.addEventListener("click", () => {
document.querySelector("video").pause();
Expand All @@ -83,7 +76,7 @@
ytButton.style.cssText = "";
}, 3000);
});

ytButtons.appendChild(ytButton);
console.log("[YTMPV] MPV button added");
console.log(ytButton, ytButtons);
Expand Down
84 changes: 84 additions & 0 deletions userscript/youtubeDownloader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// ==UserScript==
// @name YouTube Downloader
// @version 0.3
// @description This little script downloads any YouTube video
// @author TibixDev
// @match https://www.youtube.com/*
// @grant GM_addStyle
// ==/UserScript==

(async function () {
'use strict';
console.log("[YTDL] YouTube downloader script loaded");

function setButtonInterval() {
return setInterval(() => {
if (document.querySelector("#actions>#actions-inner>#menu>ytd-menu-renderer>#top-level-buttons-computed>yt-button-view-model")) {
console.log("[YTDL] Menu container found, executing...");
addDlButton()
}
}, 2000);
}

let waitForButtons = null;

let location = window.location.href;
if (location.match(/^https:\/\/www\.youtube\.com\/watch\?v=([^&]*)/)) {
waitForButtons = setButtonInterval();
console.log("[YTDL] Video link correct: " + location);
}

function handleVideoUrlChange(newUrl) {
if (location !== newUrl && newUrl.includes("watch?v=") && !waitForButtons) {
console.log("[YTDL] Video URL detected, toggling waitForButtons...");
waitForButtons = setButtonInterval();
location = newUrl;
}
}

// Listen for YouTube's navigation finish event
window.addEventListener('yt-navigate-finish', () => {
// Small delay to ensure URL and content are settled
setTimeout(() => {
handleVideoUrlChange(window.location.href);
}, 100);
});

function addDlButton() {
clearInterval(waitForButtons);
waitForButtons = null;
const ytButtons = document.querySelector("#actions>#actions-inner>#menu>ytd-menu-renderer>#top-level-buttons-computed");
const ytButton = document.createElement("button");
ytButton.id = "ytdlp-button";
ytButton.classList.add("ytSpecButtonViewModelHost", "style-scope", "ytd-menu-renderer", "yt-spec-button-shape-next", "yt-spec-button-shape-next--tonal", "yt-spec-button-shape-next--mono", "yt-spec-button-shape-next--size-m", "yt-spec-button-shape-next--icon-leading", "yt-spec-button-shape-next--enable-backdrop-filter-experiment");
const mpvBtnStyle = `
#ytdlp-button {
margin-left: 10px;
padding: 0px 40px;
}`

const styleElem = document.createElement("style");
if (styleElem.styleSheet) {
styleElem.styleSheet.cssText = mpvBtnStyle;
} else {
styleElem.appendChild(document.createTextNode(mpvBtnStyle));
}
document.getElementsByTagName('head')[0].appendChild(styleElem);
//ytButton.style.cssText = "margin-left: 10px;";
ytButton.textContent = "📥 DOWNLOAD";
ytButton.addEventListener("click", () => {
document.querySelector("video").pause();
document.location = "ytdlp-downloader://" + document.location.href;
ytButton.textContent = "📥 DOWNLOAD";
//ytButton.style.cssText = "background-color: #0a6dab;";
setTimeout(() => {
ytButton.textContent = "Downloading...";
ytButton.style.cssText = "";
}, 3000);
});

ytButtons.appendChild(ytButton);
console.log("[YTDL] DOWNLOAD button added");
console.log(ytButton, ytButtons);
}
})();