您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Creates a sidebar button to download the currently playing gif in the currently selected quality.
当前为
// ==UserScript== // @name RedGifs Downloader // @namespace burrito.scripts // @match http*://*.redgifs.com/* // @match http*://redgifs.com/* // @grant none // @version 1.1 // @author hunkyburrito // @description Creates a sidebar button to download the currently playing gif in the currently selected quality. // @homepage https://gist.github.com/hunkyburrito/f588fa77e75e29f9eeabcd24b21e35f8#file-redgif_downloader-js // @license GNU GPLv3 // ==/UserScript== // Object to store cached GIF information const gifCache = {}; async function getGif(gifId) { // Check if the GIF information exists in the cache if (gifCache[gifId]) { return gifCache[gifId]; // Return cached data if available } // If not cached, fetch GIF info from the API let gifReq = await fetch(`https://api.redgifs.com/v2/gifs/${gifId}`, { method: 'GET', headers: { Authorization: `Bearer ${localStorage.getItem('temporary_access_token')}` } }); let gifInfo = await gifReq.json(); // Cache the fetched GIF information gifCache[gifId] = gifInfo; return gifInfo; } async function download(gifInfo) { let quality = localStorage.getItem('gifQuality'); let dlLink = gifInfo.gif.urls[quality ? quality : 'sd']; // Fetch the video data let response = await fetch(dlLink); let data = await response.blob(); // Create a link element and trigger the download const link = document.createElement('a'); link.href = URL.createObjectURL(data); link.download = `${gifInfo.gif.id}.mp4`; link.setAttribute('class', "download"); document.body.appendChild(link); link.click(); // Clean up document.body.removeChild(link); URL.revokeObjectURL(link.href); } async function addButton (target, gifInfo) { // Check if the download button already exists for this GIF if (document.querySelector(`#DL_Btn_${gifInfo.gif.id}`)) { return; } // Sidebar item and button let sb_itm = document.createElement('li') sb_itm.setAttribute('class', 'SideBar-Item') let dl_btn = document.createElement('button') dl_btn.setAttribute('class', 'DL_Btn') dl_btn.setAttribute('id', `DL_Btn_${gifInfo.gif.id}`); // Unique ID for each button // Button icon let dl_icon = document.createElementNS('http://www.w3.org/2000/svg', 'svg') dl_icon.setAttribute('width', '24') dl_icon.setAttribute('height', '24') dl_icon.setAttribute('viewBox', '0 0 24 24') dl_icon.setAttribute('fill', 'white') dl_icon.innerHTML = "<path d='M11.29 15.71a1 1 0 0 0 .33.21 1 1 0 0 0 .76 0 1 1 0 0 0 .33-.21l3-3a1 1 0 0 0-1.42-1.42L13 12.59V9a1 1 0 0 0-2 0v3.59l-1.29-1.3a1 1 0 0 0-1.42 0 1 1 0 0 0 0 1.42zM12 22A10 10 0 1 0 2 12a10 10 0 0 0 10 10zm0-18a8 8 0 1 1-8 8 8 8 0 0 1 8-8z' stroke='currentColor' stroke-width='0.5' stroke-linecap='round' stroke-linejoin='round'></path>" dl_btn.appendChild(dl_icon) sb_itm.appendChild(dl_btn) let parent_node = await waitForElm('.SideBar', target) let sibling_node = await waitForElm('.FSButton', target) // Copy styles of other button const styles = window.getComputedStyle(sibling_node); let cssText = styles.cssText; if (!cssText) { cssText = Array.from(styles).reduce((str, property) => { return `${str}${property}:${styles.getPropertyValue(property)};`; }, ''); } dl_btn.style.cssText = cssText; // Insert button into sidebar sibling_node = sibling_node.parentNode parent_node.insertBefore(sb_itm, sibling_node.nextSibling) dl_btn.addEventListener('click', function(){ download(gifInfo) } ) } function waitForElm(selector, target=document) { return new Promise(resolve => { if (target.querySelector(selector)) { return resolve(target.querySelector(selector)); } const observer = new MutationObserver(mutations => { if (target.querySelector(selector)) { observer.disconnect(); resolve(target.querySelector(selector)); } }); observer.observe(target.body, { childList: true, subtree: true }); }); } async function init() { let activeGif = null; while (true) { // Wait for an active GIF element const gif = await waitForElm('.Player_isActive'); // If the new active GIF is different from the previous one, update the button if (gif !== activeGif) { activeGif = gif; const info = await getGif(gif.id.split('_')[1]); addButton(gif, info); } // Introduce a delay before the next check (e.g., 100 milliseconds) await new Promise(resolve => setTimeout(resolve, 30)); } } window.addEventListener('load', () => { init() })