Quick Send

Get temporary shortened links for files uploaded to Send (formerly Firefox Send) instances.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name         Quick Send
// @namespace    https://naeembolchhi.github.io/
// @version      0.5
// @description  Get temporary shortened links for files uploaded to Send (formerly Firefox Send) instances.
// @author       NaeemBolchhi
// @license      GPL-3.0-or-later
// @icon         data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 96 96"><path d="M96 51.43a25.5 25.5 0 0 1-6.61 17.14 22.297 22.297 0 0 1-15.84 6.86h-3.27V65.14h3.27c3.08-.06 6.02-1.3 8.2-3.47 2.55-2.81 3.95-6.46 3.96-10.25-.01-9.46-7.68-17.13-17.14-17.14-.57 0-3.47.37-5.23.59-.8.11-1.57-.38-1.83-1.14l-.7-2.04a21.146 21.146 0 0 0-17.57-14.45c-11.26-1.2-21.35 6.96-22.55 18.22-.25 2.32-.1 4.67.45 6.95l.73 3.13c.21.88-.31 1.77-1.17 2.03l-3.08.93a10.191 10.191 0 0 0-7.33 9.78c0 1.52.5 3 1.42 4.21a8.328 8.328 0 0 0 6.13 2.65h7.87v10.29h-7.87c-5.66.04-11.02-2.54-14.52-6.98A17.205 17.205 0 0 1 0 58.28a20.38 20.38 0 0 1 10.41-17.83c-.08-.92-.13-1.84-.13-2.75 0-17.03 13.8-30.85 30.83-30.86a30.86 30.86 0 0 1 27.65 17.14C83.83 24.1 95.97 36.34 96 51.41Zm-46.61-3.25c-.56-.77-1.63-.93-2.4-.38-.14.11-.27.23-.38.38L33.72 65.84c-.56.77-.39 1.84.38 2.4.29.21.65.33 1.01.33h7.75v18.86c0 .95.77 1.71 1.71 1.71h6.86c.95 0 1.71-.77 1.71-1.71V68.57h7.75a1.71 1.71 0 0 0 1.38-2.72L49.38 48.19h-.01Z" fill="%2345a1ff"/></svg>
// @match        https://send.vis.ee/*
// @match        https://send.mni.li/*
// @match        https://send.monks.tools/*
// @match        https://send.aurorabilisim.com/*
// @match        https://send.artemislena.eu/*
// @match        https://fileupload.ggc-project.de/*
// @match        https://drop.chapril.org/*
// @match        https://send.jeugdhulp.be/*
// @match        https://send.cyberjake.xyz/*
// @match        https://send.kokomo.cloud/*
// @match        https://send.adminforge.de/*
// @match        https://send.turingpoint.de/*
// @match        https://send.aslaets.be/*
// @match        https://send.codespace.cz/*
// @match        https://upload.nolog.cz/*
// @match        https://ch.skysend.ch/*
// @match        https://send.canine.tools/*
// @match        https://send.skylerszijjarto.com/*
// @match        https://send.richy.sh/*
// @match        https://send.majoenell.com/*
// @match        https://send.nog.community/*
// @match        https://send.hostnetwork.xyz/*
// @run-at       document-body
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// @connect      trimm.link
// ==/UserScript==

// Temporarily shortened link
async function slink(longurl) {
    const baseUrl = "https://trimm.link/";

    return new Promise((resolve, reject) => {
        GM_xmlhttpRequest({
            method: "POST",
            url: baseUrl + "shorten",
            headers: {
                "Content-Type": "application/json"
            },
            data: JSON.stringify({ link: longurl.trim() }),
            onload: function(response) {
                try {
                    // responseText is the raw string; we need to parse it manually
                    const json = JSON.parse(response.responseText);
                    const shorturl = baseUrl + (json.word || "");
                    resolve(shorturl);
                } catch (err) {
                    reject("Error parsing response: " + err);
                }
            },
            onerror: function(error) {
                reject("Request failed: " + error);
            }
        });
    });
}

// Style Additions
const newCSS = `
    .temp-link-shortener {
        background-color: #f38416;
        margin-bottom: 1rem;
    }
    .temp-link-shortener:hover, .temp-link-shortener:focus {
        background-color: #a16908;
    }
    .temp-link-shortener.hide {
        display: none;
    }

    .loader-circle-8 {
        position: relative;
        margin: 0 auto;
        height: 18.4px;
        stroke: white;
    }
    .loader-circle-8:before {
        content: "";
        display: block;
        padding-top: 100%;
    }
    .circular {
        animation: rotate 2s linear infinite;
        height: 100%;
        transform-origin: center center;
        width: 100%;
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        margin: auto;
    }
    .path {
        stroke-dasharray: 1, 200;
        stroke-dashoffset: 0;
        animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite;
        stroke-linecap: round;
    }
    @keyframes rotate {
        100% {
            transform: rotate(360deg);
        }
    }
    @keyframes dash {
        0% {
            stroke-dasharray: 1, 200;
            stroke-dashoffset: 0;
        }
        50% {
            stroke-dasharray: 89, 200;
            stroke-dashoffset: -35px;
        }
        100% {
            stroke-dasharray: 89, 200;
            stroke-dashoffset: -124px;
        }
    }
`;
GM_addStyle(newCSS);

// Add new button
function createShortenButton() {
    if (document.querySelector('.temp-link-shortener')) {return;}

    let sourcebtn = document.querySelectorAll('send-copy-dialog button[title*="opy link"], send-share-dialog button[title*="hare link"]')[0];

    if (!sourcebtn) {return;}

    let copybtn = sourcebtn.cloneNode(true);

    copybtn.classList.add('temp-link-shortener');
    copybtn.textContent = 'Shorten link';
    copybtn.setAttribute('title', 'Shorten link');

    sourcebtn.parentNode.insertBefore(copybtn, sourcebtn);

    copybtn.addEventListener('click', clickShortenButton);
}

// Process shortening
function clickShortenButton() {
    let shareURL = document.querySelector('#share-url');
    let shortenbtn = document.querySelector('.temp-link-shortener');

    shortenbtn.innerHTML = `
        <div class="loader-circle-8">
            <svg class="circular" viewbox="25 25 50 50">
            <circle class="path" cx="50" cy="50" r="20" fill="none" stroke-width="5" stroke-miterlimit="10"/>
            </svg>
        </div>
    `;

    slink(shareURL.value).then(key => {
        shareURL.value = key;
        document.querySelector('.temp-link-shortener').classList.add('hide');
    }).catch(() => {
        console.log('error');
    });

    let sourcebtn = document.querySelectorAll('send-copy-dialog button[title*="opy link"], send-share-dialog button[title*="hare link"]')[0];
    sourcebtn.outerHTML = sourcebtn.outerHTML;
    sourcebtn = document.querySelectorAll('send-copy-dialog button[title*="opy link"], send-share-dialog button[title*="hare link"]')[0];
    sourcebtn.addEventListener('click', clickCopyButton);
}

// Copy button new function
function clickCopyButton() {
    let shareURL = document.querySelector('#share-url');
    let sourcebtn = document.querySelectorAll('send-copy-dialog button[title*="opy link"]')[0];
    let sharebtn = document.querySelectorAll('send-share-dialog button[title*="hare link"]')[0];

    if (sourcebtn) {
        navigator.clipboard.writeText(shareURL.value).then(() => {
            // Success
            sourcebtn.textContent = 'Copied!';
        }).catch(err => {
            // Failure
            sourcebtn.textContent = 'Failure!';
        });

        window.location.reload();
    } else if (sharebtn) {
        navigator.share({url: shareURL.value});
    }
}

// Mutation observer to track file uploads
let observer = new MutationObserver(function() {
    createShortenButton();
});
observer.observe(document.documentElement, {childList: true, subtree: true});