// ==UserScript==
// @name Telegram Media Downloader (Batch Support)
// @name:en Telegram Media Downloader (Batch Support)
// @name:zh-CN Telegram 受限图片视频下载器 (批量支持)
// @name:zh-TW Telegram 受限圖片影片下載器 (批次支援)
// @name:ru Telegram: загрузчик медиафайлов (пакетная загрузка)
// @version 1.207
// @namespace https://github.com/Neet-Nestor/Telegram-Media-Downloader
// @description Enhanced version with batch download support for restricted Telegram content
// @description:en Download multiple images/videos at once from restricted Telegram channels
// @description:ru Пакетная загрузка медиафайлов из закрытых Telegram-каналов
// @description:zh-CN 批量下载禁止保存的Telegram频道内容
// @description:zh-TW 批次下載禁止儲存的 Telegram 頻道內容
// @author Nestor Qin + Modifications
// @license GNU GPLv3
// @website https://github.com/Neet-Nestor/Telegram-Media-Downloader
// @match https://web.telegram.org/*
// @match https://webk.telegram.org/*
// @match https://webz.telegram.org/*
// @icon https://img.icons8.com/color/452/telegram-app--v5.png
// @grant GM_download
// @grant GM_xmlhttpRequest
// ==/UserScript==
(function() {
'use strict';
// Existing logger and constants remain unchanged
const logger = { /* ... original logger code ... */ };
const contentRangeRegex = /^bytes (\d+)-(\d+)\/(\d+)$/;
const REFRESH_DELAY = 500;
const hashCode = s => { /* ... original hash code ... */ };
// Batch Download System
const batchManager = {
queue: new Map(),
isProcessing: false,
addToQueue: function(url, type, element) {
this.queue.set(url, { type, element });
element.classList.add('tel-batch-selected');
},
removeFromQueue: function(url) {
this.queue.delete(url);
},
processQueue: async function() {
this.isProcessing = true;
const batchSize = this.queue.size;
for (const [url, {type, element}] of this.queue) {
try {
await new Promise((resolve, reject) => {
setTimeout(() => {
try {
switch(type) {
case 'video': tel_download_video(url); break;
case 'audio': tel_download_audio(url); break;
case 'image': tel_download_image(url); break;
}
resolve();
} catch(e) {
reject(e);
}
}, 1000);
});
element.classList.remove('tel-batch-selected');
} catch(e) {
logger.error(`Batch failed for ${url}: ${e.message}`);
}
}
this.queue.clear();
this.isProcessing = false;
}
};
// Batch UI Elements
const createBatchUI = () => {
const existingButton = document.getElementById('tel-batch-download');
if (!existingButton) {
const batchButton = document.createElement('button');
batchButton.id = 'tel-batch-download';
batchButton.textContent = `Batch Download (${batchManager.queue.size})`;
Object.assign(batchButton.style, {
position: 'fixed',
bottom: '20px',
right: '20px',
zIndex: '99999',
padding: '10px 20px',
backgroundColor: '#0088cc',
color: 'white',
border: 'none',
borderRadius: '5px',
cursor: 'pointer'
});
batchButton.addEventListener('click', () => {
if (!batchManager.isProcessing && batchManager.queue.size > 0) {
batchButton.textContent = 'Processing...';
batchManager.processQueue().finally(() => {
batchButton.textContent = 'Batch Download (0)';
});
}
});
document.body.appendChild(batchButton);
}
};
// Modified media injection with checkboxes
const injectMediaElements = (mediaElements, mediaType) => {
mediaElements.forEach(element => {
if (element.querySelector('.tel-batch-checkbox')) return;
const url = element.querySelector('video,img,audio')?.src;
if (!url) return;
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.className = 'tel-batch-checkbox';
Object.assign(checkbox.style, {
position: 'absolute',
top: '5px',
left: '5px',
zIndex: '1000',
width: '18px',
height: '18px'
});
checkbox.addEventListener('change', (e) => {
if (e.target.checked) {
batchManager.addToQueue(url, mediaType, element);
} else {
batchManager.removeFromQueue(url);
}
document.getElementById('tel-batch-download').textContent =
`Batch Download (${batchManager.queue.size})`;
});
element.style.position = 'relative';
element.appendChild(checkbox);
});
};
// Modified interval handlers
const createMediaHandlers = () => {
// Original media detection code modified to include batch checkboxes
setInterval(() => {
// Video elements
const videoElements = document.querySelectorAll('.VideoPlayer, video');
injectMediaElements(videoElements, 'video');
// Image elements
const imageElements = document.querySelectorAll('img.PVZ8TOWS, img.media-photo');
injectMediaElements(imageElements, 'image');
// Audio elements
const audioElements = document.querySelectorAll('audio-element, audio');
injectMediaElements(audioElements, 'audio');
createBatchUI();
}, REFRESH_DELAY);
};
// Existing progress bar setup remains unchanged
const setupProgressBar = () => { /* ... original progress bar code ... */ };
// Original download functions remain unchanged
const tel_download_video = url => { /* ... original video download ... */ };
const tel_download_audio = url => { /* ... original audio download ... */ };
const tel_download_image = url => { /* ... original image download ... */ };
// Initialization
(function init() {
setupProgressBar();
createMediaHandlers();
logger.info('Batch download system initialized');
})();
})();