TikTok HD Download (uses ssstik.io)

This adds the Download button on TikToks (near the follow or following button where it shows comments etc), clicking it opens the ssstik.io website and submits the copied link and downloads the TikTok in HD!

// ==UserScript==
// @name         TikTok HD Download (uses ssstik.io)
// @namespace    http://tampermonkey.net/
// @version      1.4
// @description  This adds the Download button on TikToks (near the follow or following button where it shows comments etc), clicking it opens the ssstik.io website and submits the copied link and downloads the TikTok in HD!
// @author       CJStylesOrg
// @match        https://www.tiktok.com/*
// @match        https://ssstik.io*
// @icon         https://static.vecteezy.com/system/resources/previews/016/716/450/non_2x/tiktok-icon-free-png.png
// @grant        none
// ==/UserScript==

(function () {
  let isButtonAdded = false;

  function addssstikButton(targetElement) {
    if (targetElement.querySelector('.ssstik-btn')) return;

    let ssstikBtn = document.createElement('button');
    ssstikBtn.className = 'ssstik-btn';
    ssstikBtn.innerHTML = 'Download';
    ssstikBtn.style.cssText = `
      box-sizing: border-box;
      appearance: none;
      min-width: 96px;
      display: inline-flex;
      justify-content: center;
      align-items: center;
      position: relative;
      border-style: solid;
      border-width: 1px;
      border-radius: 2px;
      font-family: var(--tux-fontFamilyParagraph);
      font-weight: var(--tux-fontWeightSemibold);
      text-decoration: none;
      cursor: pointer;
      background-clip: padding-box;
      font-size: 15px;
      height: 36px;
      padding-inline: 15px;
      color: var(--tux-colorConstTextInverse);
      background-color: var(--tux-colorPrimary);
      border-color: var(--tux-colorPrimary);
      margin-left: 10px;
    `;

    ssstikBtn.addEventListener('click', () => {
      let currentLink = window.location.href;
      navigator.clipboard
        .writeText(currentLink)
        .then(() => {
          window.open('https://ssstik.io/', '_blank');
        })
        .catch((err) => {
          console.error('Could not copy text: ', err);
        });
    });

    targetElement.appendChild(ssstikBtn);
  }

  function observeChanges() {
    const targetWrapper = document.querySelector('.css-r4iroe-DivBtnWrapper.evv7pft7, .css-31630c-DivInfoContainer.e17fzhrb0');
    if (targetWrapper) {
      addssstikButton(targetWrapper);
    }
  }

  const observer = new MutationObserver(() => {
    observeChanges();
  });

  observer.observe(document.body, { childList: true, subtree: true });

  window.addEventListener('beforeunload', () => {
    observer.disconnect();
  });
})();

(function() {
  'use strict';

  if (!document.referrer.includes("tiktok.com")) {
    console.log("Not referred from TikTok, aborting script execution.");
    return;
  }

  function clickButton(selector) {
    const button = document.querySelector(selector);
    if (button) {
      button.click();
    }
  }

  clickButton('#paste');

  const pollInterval = 1000; // Check every second

  const interval = setInterval(async () => {
    const inputField = document.querySelector('#main_page_text');

    // If pasted content detected, submit and stop checking
    if (inputField && inputField.value.trim() !== "") {
      console.log("Pasted content detected, submitting...");
      clickButton('#submit');
      clearInterval(interval);
      return;
    }

    // Check clipboard permission
    if (navigator.permissions) {
      try {
        const permissionStatus = await navigator.permissions.query({ name: "clipboard-read" });
        if (permissionStatus.state === "denied") {
          console.warn("Clipboard access denied. Cannot proceed.");
          clearInterval(interval);
          return;
        }
        if (permissionStatus.state === "granted") {
          console.log("Clipboard access granted, retrying paste if necessary...");
          clickButton('#paste');
        }
        // If still "prompt", keep waiting
      } catch (err) {
        console.error("Could not check clipboard permission: ", err);
      }
    }
  }, pollInterval);

  const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
      if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
        clickButton('#hd_download');
      }
    });
  });

  observer.observe(document.body, { childList: true, subtree: true });
})();