RedGifs Downloader

Creates a sidebar button to download the currently playing gif in the currently selected quality.

Verzia zo dňa 15.12.2023. Pozri najnovšiu verziu.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name        RedGifs Downloader
// @namespace   burrito.scripts
// @match       http*://*.redgifs.com/*
// @match       http*://redgifs.com/*
// @grant       none
// @version     1.0
// @author      hunkyburrito
// @description Creates a sidebar button to download the currently playing gif in the currently selected quality.
// @homepage    https://gist.githubusercontent.com/hunkyburrito/f588fa77e75e29f9eeabcd24b21e35f8/raw/e89c52ab8b00721273499c8ad9139a95102f2a0f/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;
}

function download (gifInfo) {
  let quality = localStorage.getItem('gifQuality')
  let dlLink = gifInfo.gif.urls[quality ? quality : 'sd']

  const link = document.createElement('a');
  link.href = dlLink;
  link.download = `${gifInfo.gif.id}.mp4`
  link.setAttribute('class', "download");

  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

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()
})