您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Bulk download all Payhip course assignment files with formatted names
当前为
// ==UserScript== // @name Payhip Course Assignment Bulk Downloader // @namespace https://tampermonkey.net/ // @version 1.0.1 // @description Bulk download all Payhip course assignment files with formatted names // @author ymhc // @match https://payhip.com/course-assignments* // @grant GM_download // @license MIT // ==/UserScript== (function() { 'use strict'; // Create floating download button function createFloatingButton() { const button = document.createElement('button'); button.innerHTML = '📥 Bulk Download'; button.style.cssText = ` position: fixed; top: 20px; right: 20px; z-index: 9999; background: #007bff; color: white; border: none; padding: 12px 20px; border-radius: 5px; cursor: pointer; font-size: 14px; font-weight: bold; box-shadow: 0 2px 10px rgba(0,0,0,0.2); transition: background 0.3s ease; `; button.addEventListener('mouseenter', () => { button.style.background = '#0056b3'; }); button.addEventListener('mouseleave', () => { button.style.background = '#007bff'; }); button.addEventListener('click', bulkDownload); document.body.appendChild(button); return button; } // Extract assignment data from the page function getAssignmentData() { const assignments = []; const rows = document.querySelectorAll('.general-row.js-general-row'); rows.forEach(row => { try { // Extract student name const studentLink = row.querySelector('a[href*="/student-details/"]'); let studentName = ''; if (studentLink) { studentName = studentLink.textContent.trim(); } // Extract assignment title const assignmentElement = row.querySelector('.lesson-type-icon-and-lesson-name-wrapper'); let assignmentTitle = ''; if (assignmentElement) { assignmentTitle = assignmentElement.textContent.trim(); } // Extract download URL const downloadLink = row.querySelector('a[href*="/course-assignments/download"]'); let downloadUrl = ''; if (downloadLink) { downloadUrl = downloadLink.href; } // Extract original filename for extension const fileNameElement = row.querySelector('.file-name'); let originalFileName = ''; let fileExtension = ''; if (fileNameElement) { originalFileName = fileNameElement.textContent.trim(); const lastDotIndex = originalFileName.lastIndexOf('.'); if (lastDotIndex > -1) { fileExtension = originalFileName.substring(lastDotIndex); } } if (studentName && assignmentTitle && downloadUrl) { assignments.push({ studentName, assignmentTitle, downloadUrl, originalFileName, fileExtension, newFileName: `${studentName} - ${assignmentTitle}${fileExtension}` }); } } catch (error) { console.error('Error processing assignment row:', error); } }); return assignments; } // Download a single file with custom name function downloadFile(url, fileName) { return new Promise((resolve, reject) => { // Try using GM_download if available (Tampermonkey) if (typeof GM_download !== 'undefined') { GM_download(url, fileName, url) .then(() => { setTimeout(resolve, 500); }) .catch(error => { console.error(`GM_download failed for ${fileName}:`, error); // Fallback to fetch method fallbackDownload(url, fileName).then(resolve).catch(reject); }); } else { // Use fetch method as fallback fallbackDownload(url, fileName).then(resolve).catch(reject); } }); } // Fallback download method using fetch and blob function fallbackDownload(url, fileName) { return new Promise((resolve, reject) => { fetch(url) .then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.blob(); }) .then(blob => { const blobUrl = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = blobUrl; link.download = fileName; link.style.display = 'none'; document.body.appendChild(link); link.click(); document.body.removeChild(link); // Clean up the blob URL window.URL.revokeObjectURL(blobUrl); // Small delay to prevent overwhelming the browser setTimeout(resolve, 500); }) .catch(error => { console.error(`Failed to download ${fileName}:`, error); reject(error); }); }); } // Show progress indicator function showProgress(current, total) { let progressDiv = document.getElementById('bulk-download-progress'); if (!progressDiv) { progressDiv = document.createElement('div'); progressDiv.id = 'bulk-download-progress'; progressDiv.style.cssText = ` position: fixed; top: 70px; right: 20px; z-index: 9999; background: #28a745; color: white; padding: 10px 15px; border-radius: 5px; font-size: 12px; box-shadow: 0 2px 10px rgba(0,0,0,0.2); `; document.body.appendChild(progressDiv); } progressDiv.textContent = `Downloading: ${current}/${total}`; if (current === total) { setTimeout(() => { if (progressDiv.parentNode) { progressDiv.parentNode.removeChild(progressDiv); } }, 2000); } } // Main bulk download function async function bulkDownload() { const assignments = getAssignmentData(); if (assignments.length === 0) { alert('No assignments found on this page.'); return; } const confirmMessage = `Found ${assignments.length} assignments. Download all?`; if (!confirm(confirmMessage)) { return; } console.log('Starting bulk download of assignments:', assignments); for (let i = 0; i < assignments.length; i++) { const assignment = assignments[i]; showProgress(i + 1, assignments.length); try { console.log(`Downloading: ${assignment.newFileName}`); await downloadFile(assignment.downloadUrl, assignment.newFileName); } catch (error) { console.error(`Failed to download ${assignment.newFileName}:`, error); } } console.log('Bulk download completed!'); } // Initialize the script when page loads function init() { // Check if we're on the assignments page if (window.location.pathname.includes('course-assignments')) { // Wait a bit for the page to fully load setTimeout(() => { createFloatingButton(); console.log('Payhip Assignment Bulk Downloader loaded'); }, 1000); } } // Run initialization if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();