New:Socket for Asana Is Now Available.Learn more
Get Started

Yt-dl Addon for Windows

Package Overview
Versions
1
Alerts
File Explorer
Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

yt_dl_firefox_command_runner@test.com - firefox Package Compare versions

Comparing version
1.3
to
2.0
+114
-39
background.js
/*
On startup, connect to the 'firefox_command_runner' app.
Bridges the popup and the yt-dlp native host.
The popup is short-lived, so all download state lives here and is replayed to
the popup whenever it reconnects.
*/
console.log('Starting firefox command runner!')
var port = browser.runtime.connectNative('firefox_command_runner');
const HOST_NAME = "firefox_command_runner";
let hostPort = null;
let popupPort = null;
let lastDirectory = null;
let state = { phase: "idle" };
let progressCount = 0;
function log(...args) {
console.log("[yt-dlp]", new Date().toLocaleTimeString(), ...args);
}
function setState(next) {
state = next;
log("state ->", state.phase, popupPort ? "(popup open)" : "(popup closed)");
if (popupPort) {
popupPort.postMessage(state);
}
}
function notify(title, message) {
browser.notifications.create({
type: "basic",
iconUrl: browser.runtime.getURL("icons/YT_icon.png"),
title,
message,
});
}
/*
Listen for messages from the app.
Native host connection. Reconnected lazily so a host crash doesn't wedge the
add-on until the browser restarts.
*/
port.onMessage.addListener((response) => {
console.log("Received: ");
console.log(response);
if(response[0]=="END"){
browser.notifications.create({
'type': 'basic',
'iconUrl': browser.extension.getURL('icons/YT_icon.png'),
'title': 'Download Completed !',
'message': response[1],
function host() {
if (hostPort) {
return hostPort;
}
log("connecting to native host", HOST_NAME);
hostPort = browser.runtime.connectNative(HOST_NAME);
hostPort.onMessage.addListener(onHostMessage);
hostPort.onDisconnect.addListener((port) => {
hostPort = null;
log("host disconnected", port.error ? port.error.message : "(clean)");
if (port.error) {
const message = `Native host disconnected: ${port.error.message}`;
notify("Download failed", message);
setState({ phase: "error", message });
}
});
browser.runtime.sendMessage("Complete")
return hostPort;
}
else if(response[0]=="PROG" && response[1][2]=="of"){
values=["PROG",response[1][1],response[1][3],response[1][5]]
browser.runtime.sendMessage(values)
function onHostMessage(message) {
if (message.type === "progress") {
// One in 20 keeps the console readable at ~5 progress messages a second
progressCount += 1;
if (progressCount % 20 === 1 || message.status !== "downloading") {
log(`host -> progress #${progressCount}`, JSON.stringify(message));
}
} else {
progressCount = 0;
log("host ->", JSON.stringify(message));
}
else if(response[0]=="FORMAT"){
browser.runtime.sendMessage(response);
switch (message.type) {
case "formats":
setState({ phase: "formats", formats: message.formats });
break;
case "progress":
setState({ phase: "downloading", progress: message });
break;
case "done": {
lastDirectory = message.dir;
const names = message.files.slice(0, 4);
if (message.files.length > names.length) {
names.push(`… and ${message.files.length - names.length} more`);
}
notify(
"Download complete",
names.length ? names.join("\n") : "Already downloaded"
);
setState({ phase: "done", files: message.files, dir: message.dir });
break;
}
case "error":
notify("Download failed", message.message);
setState({ phase: "error", message: message.message });
break;
}
});
}
/*
Listen for messages from the content script.
Popup connection.
*/
browser.runtime.onMessage.addListener(function(message) {
if(message!="Complete"){
console.log('getting button message :' + message)
function logTabs(tabs) {
let tab = tabs[0]; // Safe to assume there will only be one result
console.log(tab.url);
port.postMessage(message+tab.url);
}
browser.tabs.query({currentWindow: true, active: true}).then(logTabs, console.error);
}
browser.runtime.onConnect.addListener((port) => {
log("popup connected, replaying state:", state.phase);
popupPort = port;
port.postMessage(state);
port.onMessage.addListener(onPopupMessage);
port.onDisconnect.addListener(() => {
log("popup closed");
popupPort = null;
});
});
async function onPopupMessage(message) {
try {
const [tab] = await browser.tabs.query({ currentWindow: true, active: true });
log("popup ->", JSON.stringify(message), "on", tab.url);
if (message.action === "formats") {
setState({ phase: "loading-formats" });
} else if (message.action === "download") {
setState({ phase: "downloading", progress: null });
}
host().postMessage({ ...message, url: tab.url });
} catch (error) {
log("relay failed:", error);
setState({ phase: "error", message: String(error) });
}
}
/*
Notification actions
*/
browser.notifications.onClicked.addListener((response) => {
console.log("Open Download folder")
port.postMessage("OpenDL");
});
browser.notifications.onClicked.addListener(() => {
log("notification clicked, opening", lastDirectory);
host().postMessage({ action: "open", path: lastDirectory });
});
+101
-21

@@ -1,29 +0,109 @@

/* Paddings */
.center-text{text-align:center!important;padding:2%}
.hidden{
display: none;
:root {
--bg: #ffffff;
--fg: #15141a;
--muted: #5b5b66;
--button-bg: #f0f0f4;
--button-hover: #e0e0e6;
--border: #cfcfd8;
--error: #c50042;
}
.full-width{width:100%}
/* Rounded progress bar */
.container:after,.container:before,.panel:after,.panel:before,.row:after,.row:before,.row-padding:after,.row-padding:before,
.round-small{border-radius:2px}.round,.round-medium{border-radius:4px}.round-large{border-radius:8px}.round-xlarge{border-radius:16px}.round-xxlarge{border-radius:32px}
@media (prefers-color-scheme: dark) {
:root {
--bg: #2b2a33;
--fg: #fbfbfe;
--muted: #b1b1bb;
--button-bg: #52525e;
--button-hover: #5b5b66;
--border: #6f6f7a;
--error: #ff9aa2;
}
}
/* Colors */
.light-grey,.hover-light-grey:hover,.light-gray,.hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important}
.blue,.hover-blue:hover{color:#fff!important;background-color:#2196F3!important}
.red,.hover-red:hover{color:#fff!important;background-color:#f44336!important;font-size: 100%;}
/* The display rules below would otherwise beat the hidden attribute's UA style */
[hidden] {
display: none !important;
}
/* Text size */
.text-80{font-size:80%}
.text-60{font-size:60%}
.text-40{font-size:40%}
.text-20{font-size:20%}
body {
width: 260px;
margin: 0;
padding: 10px;
background: var(--bg);
color: var(--fg);
font: 13px system-ui, sans-serif;
}
.buttons{
display:flex;
width:100%;
justify-content: space-between;
button, select {
font: inherit;
color: inherit;
background: var(--button-bg);
border: 1px solid var(--border);
border-radius: 4px;
padding: 6px 10px;
cursor: pointer;
}
button:hover {
background: var(--button-hover);
}
.row {
display: flex;
gap: 6px;
}
.row > * {
flex: 1;
}
.wide, #format-picker {
display: flex;
width: 100%;
box-sizing: border-box;
gap: 6px;
}
#format-picker {
margin-top: 6px;
}
#playlist-row {
display: flex;
align-items: center;
gap: 6px;
margin-top: 8px;
cursor: pointer;
}
#dropdown {
flex: 1;
min-width: 0;
}
progress {
width: 100%;
height: 8px;
}
p {
margin: 8px 0;
}
.center {
text-align: center;
}
.muted {
color: var(--muted);
font-size: 92%;
}
#error {
color: var(--error);
word-wrap: break-word;
}
#result {
word-wrap: break-word;
}
<!DOCTYPE html>
<html>

@@ -10,44 +9,33 @@ <head>

<body>
<div id="opt-in-prompt">
<p><b>This addon extracts the current URL and send it to your local yt-dl program.</b><br>
Please support the developer of this add-on by enabling this feature.
</p>
<p><a href="https://mozilla.org/privacy/websites/" target="_blank">
Privacy information</a></p>
<div id="button-container">
<button id="button-enable">Enable</button>
<button id="button-cancel" autofocus="true">Cancel</button>
<div id="picker">
<div class="row">
<button data-format="m4a">M4A</button>
<button data-format="mp3">MP3</button>
<button data-format="mp4">MP4</button>
</div>
</div>
<div id="after-opt-in" hidden="true"></div>
<div id="main" class="buttons">
<button id='audio_M4a'>M4a</button>
<button id='audio_mp3'>Mp3</button>
<button id='video'>Mp4</button>
<p class="muted center">OR</p>
<button id="list-formats" class="wide">Other video formats</button>
<div id="format-picker" hidden>
<select id="dropdown"></select>
<button id="download-selected">Download</button>
</div>
<p class="center-text text-80">OR</p>
<div id="aux">
<button id="format" class="full-width">Other formats</button>
<div id="load-format" class="hidden center-text full-width">Loading...</div>
<div id="ddMenu" class="hidden">
<div id="ddMenu" class="buttons">
<select id="dropdown" class="full-width">
</select>
<button id="DL">DL</button>
</div>
</div>
</div>
<div id="progress-bar" class="hidden full-width">
<div id="speed" class="center-text text-80"> Downloading...</div>
<div>
<progress id="prog" max="100" value="0" class="buttons"></progress>
<div id="perc" class="center-text">0%</div>
</div>
</div>
<label id="playlist-row" class="muted" hidden>
<input type="checkbox" id="playlist-toggle">
Download the whole playlist
</label>
</div>
<p id="loading" class="muted center" hidden>Loading formats...</p>
<div id="progress" hidden>
<p id="progress-status" class="muted center">Starting...</p>
<progress id="progress-bar" max="100" value="0"></progress>
<p id="progress-detail" class="center"></p>
</div>
<p id="result" class="center" hidden></p>
<p id="error" hidden></p>
<script src="script.js"></script>
</body>
</html>
{
"description": "Run yt-dl command-line program from firefox",
"description": "Download audio and video from the current tab with yt-dlp",
"manifest_version": 2,
"name": "Yt-dl Addon for Windows",
"version": "1.3",
"name": "yt-dlp Downloader",
"version": "2.0",
"icons": {
"128": "icons/YT_icon.png"
},
"browser_specific_settings": {
"gecko": {
"id": "yt_dl_firefox_command_runner@test.com",
"strict_min_version": "57.0"
"strict_min_version": "140.0",
"data_collection_permissions": {
"required": [
"none"
]
}
}
},
"background": {
"scripts": ["background.js"]
"scripts": [
"background.js"
]
},
"browser_action": {
"default_icon": "icons/YT_icon.png",
"default_title": "Youtube-dl",
"default_popup" :"index.html"
"default_title": "yt-dlp Downloader",
"default_popup": "index.html"
},
"permissions": [

@@ -31,4 +34,4 @@ "nativeMessaging",

"activeTab",
"storage"
"tabs"
]
}
}
+145
-106

@@ -1,114 +0,153 @@

// Addon Opt-in actions
window.addEventListener("load", function() {
// set up the appearance of the popup depending on the outcome of the opt-in
browser.storage.local.get("optInShown", function(result) {
console.log("Setting up UI. result.optInShown:" + result.optInShown);
document.getElementById("opt-in-prompt").hidden = result.optInShown;
document.getElementById("after-opt-in").hidden = !result.optInShown;
});
document.getElementById("button-enable").addEventListener(
"click",
function() {
browser.storage.local.set({ "optIn" : true, "optInShown" : true });
window.close();
});
document.getElementById("button-cancel").addEventListener(
"click",
function() {
browser.storage.local.set({ "optIn" : false, "optInShown" : false });
window.close();
});
/*
Popup UI. Owns no state: it renders whatever snapshot the background sends,
so closing and reopening it mid-download picks the progress bar back up.
*/
const port = browser.runtime.connect({ name: "popup" });
const sections = {
picker: document.getElementById("picker"),
loading: document.getElementById("loading"),
progress: document.getElementById("progress"),
result: document.getElementById("result"),
error: document.getElementById("error"),
};
const formatPicker = document.getElementById("format-picker");
const dropdown = document.getElementById("dropdown");
const playlistRow = document.getElementById("playlist-row");
const playlistToggle = document.getElementById("playlist-toggle");
// Offer the playlist checkbox only when the page belongs to one
browser.tabs.query({ currentWindow: true, active: true }).then(([tab]) => {
let url;
try {
url = new URL(tab.url);
} catch {
return;
}
if (url.pathname === "/playlist") {
// A playlist page has no single video to fall back to
playlistRow.hidden = false;
playlistToggle.checked = true;
playlistToggle.disabled = true;
} else if (url.searchParams.has("list")) {
playlistRow.hidden = false;
}
});
function requestDownload(format) {
port.postMessage({
action: "download",
format,
playlist: playlistToggle.checked,
});
}
////////// Plugin Event listeners //////////
// 3 Main formats
document.getElementById('audio_M4a').addEventListener('click', function(){
browser.runtime.sendMessage("m4a");
document.getElementById("aux").classList.add("hidden");
document.querySelector("p").classList.add("hidden");
document.querySelector("#progress-bar").classList.remove("hidden");
})
document.getElementById('audio_mp3').addEventListener('click', function(){
browser.runtime.sendMessage("mp3");
document.getElementById("aux").classList.add("hidden");
document.querySelector("p").classList.add("hidden");
document.querySelector("#progress-bar").classList.remove("hidden");
})
document.getElementById('video').addEventListener('click', function(){
browser.runtime.sendMessage("mp4");
document.getElementById("aux").classList.add("hidden");
document.querySelector("p").classList.add("hidden");
document.querySelector("#progress-bar").classList.remove("hidden");
})
document.querySelectorAll("[data-format]").forEach((button) => {
button.addEventListener("click", () => requestDownload(button.dataset.format));
});
// Other formats
document.getElementById('format').addEventListener('click', function(){
browser.runtime.sendMessage("format");
document.getElementById('load-format').classList.remove("hidden");
document.getElementById('format').classList.add("hidden");
})
document.getElementById('DL').addEventListener('click', function(){
var e = document.getElementById("dropdown");
var strUser = e.value;
console.log(strUser)
browser.runtime.sendMessage(strUser)
document.querySelector("#main").classList.remove("buttons");
document.querySelector("#main").classList.add("hidden");
document.querySelector("p").classList.add("hidden");
document.querySelector("#progress-bar").classList.remove("hidden");
})
document.getElementById("list-formats").addEventListener("click", () => {
port.postMessage({ action: "formats" });
});
////////// Listen for background script message //////////
browser.runtime.onMessage.addListener((response) => {
if (response=="Complete"){
document.querySelector("#progress-bar").classList.add("hidden");
}
if (response[0]=="PROG"){
console.log(response)
// Progression percent
percent = response[1];
percent2 = percent.substring(0,response[1].length-1);
percentFloat=parseFloat(percent2);
// Total DL size
sizeDL = response[2];
sizeDLFloat = parseFloat(sizeDL.substring(0,sizeDL.length-3))
partDL = (sizeDLFloat*percentFloat/100).toFixed(2)
// Real-time Speed value
speedDL=response[3]
if(speedDL!=null){
valSpeed="Downloading... "+ speedDL;
}
document.getElementById("download-selected").addEventListener("click", () => {
if (dropdown.value) {
requestDownload(dropdown.value);
}
});
// Update HTML
document.querySelector("#prog").value=percentFloat;
document.querySelector("#perc").textContent=partDL + " / "+ sizeDL;
document.querySelector("#speed").textContent=valSpeed;
// Verifier si meilleure astuce
document.querySelector("#progress-bar").classList.remove("hidden");
}
if (response[0]=="FORMAT"){
formats = response[1]
// Add dropdown options
var x = document.getElementById("dropdown");
for(a in formats){
//console.log(formats[a])
desc = formats[a][1]+" ("+formats[a][2]+")"+" - "+formats[a][3];
console.log(desc)
var option = document.createElement("option");
option.text = desc;
x.add(option, x[0]);
option.value = formats[a][0]
}
option.selected = "selected"
// Reveal Dropdown
document.getElementById('load-format').classList.add("hidden");
document.getElementById("ddMenu").classList.remove("hidden");
}
function show(...visible) {
for (const [name, element] of Object.entries(sections)) {
element.hidden = !visible.includes(name);
}
}
})
function mib(bytes) {
return `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;
}
function eta(seconds) {
const minutes = Math.floor(seconds / 60);
return `${minutes}:${String(seconds % 60).padStart(2, "0")}`;
}
function renderProgress(progress) {
const status = document.getElementById("progress-status");
const bar = document.getElementById("progress-bar");
const detail = document.getElementById("progress-detail");
if (!progress) {
status.textContent = "Starting...";
bar.removeAttribute("value");
detail.textContent = "";
return;
}
if (progress.status === "finished") {
status.textContent = "Converting...";
bar.removeAttribute("value");
detail.textContent = "";
return;
}
status.textContent = progress.speed
? `Downloading at ${mib(progress.speed)}/s`
: "Downloading...";
if (progress.total) {
bar.value = (progress.downloaded / progress.total) * 100;
detail.textContent = `${mib(progress.downloaded)} / ${mib(progress.total)}`;
} else {
bar.removeAttribute("value");
detail.textContent = mib(progress.downloaded);
}
if (progress.eta) {
detail.textContent += ` - ${eta(progress.eta)} left`;
}
}
function renderFormats(formats) {
dropdown.replaceChildren();
for (const format of formats) {
const option = document.createElement("option");
option.value = format.selection;
option.textContent = `${format.label} - ${format.size}`;
dropdown.add(option);
}
document.getElementById("list-formats").hidden = formats.length > 0;
formatPicker.hidden = formats.length === 0;
if (!formats.length) {
sections.error.hidden = false;
sections.error.textContent = "No mp4 formats found on this page";
}
}
port.onMessage.addListener((state) => {
if (state.phase !== "downloading") {
console.log("[popup] state:", JSON.stringify(state));
}
switch (state.phase) {
case "loading-formats":
show("picker", "loading");
break;
case "formats":
show("picker");
renderFormats(state.formats);
break;
case "downloading":
show("progress");
renderProgress(state.progress);
break;
case "done":
show("picker", "result");
sections.result.textContent = state.files.length
? `Saved to ${state.dir}`
: "Already downloaded";
break;
case "error":
show("picker", "error");
sections.error.textContent = state.message;
break;
default:
show("picker");
}
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet