digger for TPB description

The script to display images and URLs in descriptions for thepiratebay.com

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        digger for TPB description
// @namespace   https://github.com/sbugzu/digger_for_TPB_description
// @require     https://code.jquery.com/jquery-3.6.0.min.js
// @match       https://thepiratebay.org/description.php*
// @grant       none
// @version     0.1.0
// @author      sbugzu
// @description The script to display images and URLs in descriptions for thepiratebay.com
// @license     Unlicense
// ==/UserScript==

'use strict';

/*
const isYouTubeUrl = function(url) {
  try {
    const parsedUrl = new URL(url);
    return (
      parsedUrl.hostname === "www.youtube.com" ||
      parsedUrl.hostname === "youtube.com" ||
      parsedUrl.hostname === "m.youtube.com" ||
      parsedUrl.hostname === "youtu.be"
    );
  } catch (e) {
    return false; // Invalid URL
  }
}
*/

const buildUrl = function(url) {
  /*
  if(isYouTubeUrl(url)) {
    const { id, service} = getVideoId(url);
    if(id !== undefined) {
      return "https://www.youtube.com/embed/${id}";
    }
  }
  */

  const { id, service} = getVideoId(url);
  if( service !== undefined && id !== undefined) {
    if( service === "youtube" ) {
      return "https://www.youtube.com/embed/" + id;
    }
  }
  return url;
}


const text = $("#descr").text();

//const images = text.match(/https?:\/\/\S+\.(?:jpg|jpeg|png|gif|webp|bmp|svg)/gi) || [];
//const pages = text.match(/https?:\/\/[^\s]+?(?<!\.(jpg|jpeg|png|gif|webp|bmp|svg))(?=\s|$)/gi) || [];
//console.log(images)

const urlRegex = /https?:\/\/[^\s\[\]\)\}<>"']+/gi;
const urls = text.match(urlRegex) || [];
const imageRegex = /\.(jpg|jpeg|png|gif|webp|bmp|svg)(?=[?&#\[]|$)/i;
const images = urls.filter(url => imageRegex.test(url));
const pages = urls.filter(url => !imageRegex.test(url));

const $metadata = $("#metadata").first();
const $preview = $('<div id="preview"></div>').css({"text-align": "center"});

images.forEach(url => {
  const $img = $("<img>").attr("src", url);
  $img.css({
    "max-width": "95%",
    "height": "auto",
    "margin": "10px 0",
    "display": "inline-block"
  });
  $preview.append($img);
  const $link = $("<p>").append($("<a>")
                                .attr("href", url)
                                .attr("target", "_blank")
                                .attr("rel", "noopener noreferrer")
                                .text("☝️ " + url)
  );
  $preview.append($link);
});


pages.forEach(url => {
  const dstUrl = buildUrl(url);
  const $iframe = $("<iframe>").attr("src", dstUrl).css({
    "width": "95%",
    "height": "512px",
    "border": "0"
  });

  $preview.append($iframe);
  const $link = $("<p>").append($("<a>")
                                .attr("href", url)
                                .attr("target", "_blank")
                                .attr("rel", "noopener noreferrer")
                                .text("☝️ " + url)
  );
  $preview.append($link);
});

$metadata.after($preview);

/* =========== embedded get-video-id ============ */

/*! get-video-id v4.1.7 | @license MIT © Michael Wuergler | https://github.com/radiovisual/get-video-id */

/**
 * Strip away any remaining parameters following `?` or `/` or '&' for YouTube shortcode strings.
 *
 * @note this function is not meant to work with url strings containing a protocol like https://
 * @param {String} shortcodeString - the parameter string
 * @returns {String}
 */
function stripParameters(shortcodeString) {
  // Split parameters or split folder separator
  if (shortcodeString.includes('?')) {
    shortcodeString = shortcodeString.split('?')[0];
  }
  if (shortcodeString.includes('/')) {
    shortcodeString = shortcodeString.split('/')[0];
  }
  if (shortcodeString.includes('&')) {
    shortcodeString = shortcodeString.split('&')[0];
  }
  return shortcodeString;
}

/**
 * Get the Youtube Video id.
 * @param {string} youtubeStr - the url from which you want to extract the id
 * @returns {string|undefined}
 */
function youtube(youtubeString) {
  let string_ = youtubeString;

  // Remove the '-nocookie' flag from youtube urls
  string_ = string_.replace('-nocookie', '');

  // Remove time hash at the end of the string
  string_ = string_.replace(/#t=.*$/, '');

  // Strip the leading protocol
  string_ = string_.replace(/^https?:\/\//, '');

  // Shortcode
  const shortcode = /youtube:\/\/|youtu\.be\/|y2u\.be\//g;
  if (shortcode.test(string_)) {
    const shortcodeid = string_.split(shortcode)[1];
    return stripParameters(shortcodeid);
  }

  // Shorts
  const shortsUrl = /\/shorts\//g;
  if (shortsUrl.test(string_)) {
    return stripParameters(string_.split(shortsUrl)[1]);
  }

  // V= or vi=
  const parameterv = /v=|vi=/g;
  if (parameterv.test(string_)) {
    const array = string_.split(parameterv);
    return stripParameters(array[1].split('&')[0]);
  }

  // /v/ or /vi/ or /watch/
  const inlinev = /\/v\/|\/vi\/|\/watch\//g;
  if (inlinev.test(string_)) {
    const inlineid = string_.split(inlinev)[1];
    return stripParameters(inlineid);
  }

  // Format an_webp
  const parameterwebp = /\/an_webp\//g;
  if (parameterwebp.test(string_)) {
    const webp = string_.split(parameterwebp)[1];
    return stripParameters(webp);
  }

  // /e/
  const eformat = /\/e\//g;
  if (eformat.test(string_)) {
    const estring = string_.split(eformat)[1];
    return stripParameters(estring);
  }

  // Embed
  const embedreg = /\/embed\//g;
  if (embedreg.test(string_)) {
    const embedid = string_.split(embedreg)[1];
    return stripParameters(embedid);
  }

  // ignore /user/username pattern
  const usernamereg = /\/user\/([a-zA-Z\d]*)$/g;
  if (usernamereg.test(string_)) {
    return undefined;
  }

  // User
  const userreg = /\/user\/(?!.*videos)/g;
  if (userreg.test(string_)) {
    const elements = string_.split('/');
    return stripParameters(elements.pop());
  }

  // Attribution_link
  const attrreg = /\/attribution_link\?.*v%3D([^%&]*)(%26|&|$)/;
  if (attrreg.test(string_)) {
    return stripParameters(string_.match(attrreg)[1]);
  }

  // Live
  const livereg = /\/live\//g;
  if (livereg.test(string_)) {
    const liveid = string_.split(livereg)[1];
    return stripParameters(liveid);
  }
  return undefined;
}

/**
 * Get the vimeo id.
 *
 * @param {String} vimeoString the url from which you want to extract the id
 * @returns {String|undefined}
 */
function vimeo(vimeoString) {
  let string_ = vimeoString;
  if (string_.includes('#')) {
    [string_] = string_.split('#');
  }
  if (string_.includes('?') && !string_.includes('clip_id=')) {
    [string_] = string_.split('?');
  }
  let id;
  let array;
  const event = /https?:\/\/vimeo\.com\/event\/(\d+)$/;
  const eventMatches = event.exec(string_);
  if (eventMatches && eventMatches[1]) {
    return eventMatches[1];
  }
  const primary = /https?:\/\/vimeo\.com\/(\d+)/;
  const matches = primary.exec(string_);
  if (matches && matches[1]) {
    return matches[1];
  }
  const vimeoPipe = ['https?://player.vimeo.com/video/[0-9]+$', 'https?://vimeo.com/channels', 'groups', 'album'].join('|');
  const vimeoRegex = new RegExp(vimeoPipe, 'gim');
  if (vimeoRegex.test(string_)) {
    array = string_.split('/');
    if (array && array.length > 0) {
      id = array.pop();
    }
  } else if (/clip_id=/gim.test(string_)) {
    array = string_.split('clip_id=');
    if (array && array.length > 0) {
      [id] = array[1].split('&');
    }
  }
  return id;
}

/**
 * Get the vine id.
 * @param {string} string_ - the url from which you want to extract the id
 * @returns {string|undefined}
 */
function vine(string_) {
  const regex = /https:\/\/vine\.co\/v\/([a-zA-Z\d]*)\/?/;
  const matches = regex.exec(string_);
  if (matches && matches.length > 1) {
    return matches[1];
  }
  return undefined;
}

/**
 * Get the VideoPress id.
 * @param {string} urlString - the url from which you want to extract the id
 * @returns {string|undefined}
 */
function videopress(urlString) {
  let idRegex;
  if (urlString.includes('embed')) {
    idRegex = /embed\/(\w{8})/;
    return urlString.match(idRegex)[1];
  }
  idRegex = /\/v\/(\w{8})/;
  const matches = urlString.match(idRegex);
  if (matches && matches.length > 0) {
    return matches[1];
  }
  return undefined;
}

/**
 * Get the Microsoft Stream id.
 * @param {string} urlString - the url from which you want to extract the id
 * @returns {string|undefined}
 */
function microsoftStream(urlString) {
  const regex = urlString.includes('embed') ? /https:\/\/web\.microsoftstream\.com\/embed\/video\/([a-zA-Z\d-]*)\/?/ : /https:\/\/web\.microsoftstream\.com\/video\/([a-zA-Z\d-]*)\/?/;
  const matches = regex.exec(urlString);
  if (matches && matches.length > 1) {
    return matches[1];
  }
  return undefined;
}

/**
 * Get the tiktok id.
 * @param {string} urlString - the url from which you want to extract the id
 * @returns {string|undefined}
 */
function tiktok(urlString) {
  // Parse basic url and embeds
  const basicReg = /tiktok\.com(.*)\/video\/(\d+)/gm;
  const basicParsed = basicReg.exec(urlString);
  if (basicParsed && basicParsed.length > 2) {
    return basicParsed[2];
  }
  return undefined;
}

/**
 * Get the dailymotion id.
 * @param {string} urlString - the url from which you want to extract the id
 * @returns {string|undefined}
 */
function dailymotion(urlString) {
  // Parse basic url and embeds
  const basicReg = /dailymotion\.com(.*)(video)\/([a-zA-Z\d]+)/gm;
  const basicParsed = basicReg.exec(urlString);
  if (basicParsed) {
    return basicParsed[3];
  }

  // Parse shortlink
  const shortRegex = /dai\.ly\/([a-zA-Z\d]+)/gm;
  const shortParsed = shortRegex.exec(urlString);
  if (shortParsed && shortParsed.length > 1) {
    return shortParsed[1];
  }

  // Dynamic link
  const dynamicRegex = /dailymotion\.com(.*)video=([a-zA-Z\d]+)/gm;
  const dynamicParsed = dynamicRegex.exec(urlString);
  if (dynamicParsed && dynamicParsed.length > 2) {
    return dynamicParsed[2];
  }
  return undefined;
}

/**
 * Get the loom id.
 * @param {string} urlString - the url from which you want to extract the id
 * @returns {string|undefined}
 */
function loom(urlString) {
  const regex = /^https?:\/\/(?:www\.)?loom\.com\/(?:share|embed)\/([\da-zA-Z]+)\/?/;
  const matches = regex.exec(urlString);
  if (matches && matches.length > 1) {
    return matches[1];
  }
  return undefined;
}

/**
 * Get the value assigned to a "src" attribute in a string, or undefined.
 * @param {String} input
 * @returns {String|undefined}
 */
function getSrc(input) {
  if (typeof input !== 'string') {
    throw new TypeError('getSrc expected a string');
  }
  const srcRegEx = /src="(.*?)"/gm;
  const matches = srcRegEx.exec(input);
  if (matches && matches.length >= 2) {
    return matches[1];
  }
  return undefined;
}

/**
 * Prepare the URL by doing common cleanup operations common for all URL types.
 * @param {String} input
 * @returns {String}
 */
function sanitizeUrl(input) {
  if (typeof input !== 'string') {
    throw new TypeError(`sanitizeUrl expected a string, got ${typeof input}`);
  }
  let string_ = input;
  if (/<iframe/gi.test(string_)) {
    string_ = getSrc(string_) || '';
  }

  // Remove surrounding whitespaces or linefeeds
  string_ = string_.trim();

  // Remove any leading `www.`
  string_ = string_.replace('/www.', '/');
  return string_;
}

/**
 * Extract the url query parameter from a Google redirect url.
 *
 * @example
 * ```javascript
 * const url = extractGoogleRedirectionUrl('https://www.google.cz/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwj30L2MvpDVAhUFZVAKHb8CBaYQuAIIIjAA&url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DdQw4w9WgXcQ')
 * // => 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'
 * ```
 * @param {String} input
 * @returns {String}
 */
function extractGoogleRedirectionUrl(input) {
  if (typeof input !== 'string') {
    throw new TypeError(`extractGoogleRedirectionUrl expected a string, got ${typeof input}`);
  }
  const string_ = input.trim();

  // Try to handle google redirection uri
  if (/\/\/google|www\.google/.test(string_)) {
    try {
      const urlObject = new URL(input);
      const parameters = new URLSearchParams(urlObject.search);
      const extractedUrl = parameters.get('url');
      if (extractedUrl) {
        return decodeURIComponent(extractedUrl);
      }
    } catch {
      // If there's an error (e.g., input is not a valid URL), return the trimmed input
      return string_;
    }
  }
  return string_;
}

/**
 * Get the id and service from a video url.
 * @param {String} urlString - the url from which you want to extract the id
 * @returns {Object}
 */
function getVideoId(urlString) {
  if (typeof urlString !== 'string') {
    throw new TypeError('get-video-id expects a string');
  }
  const string_ = sanitizeUrl(urlString);
  const url = extractGoogleRedirectionUrl(string_);
  let metadata = {
    id: undefined,
    service: undefined
  };
  if (/youtube|youtu\.be|y2u\.be|i.ytimg\./.test(url)) {
    metadata = {
      id: youtube(url),
      service: 'youtube'
    };
  } else if (/vimeo/.test(url)) {
    metadata = {
      id: vimeo(url),
      service: 'vimeo'
    };
  } else if (/vine/.test(url)) {
    metadata = {
      id: vine(url),
      service: 'vine'
    };
  } else if (/videopress/.test(url)) {
    metadata = {
      id: videopress(url),
      service: 'videopress'
    };
  } else if (/microsoftstream/.test(url)) {
    metadata = {
      id: microsoftStream(url),
      service: 'microsoftstream'
    };
  } else if (/tiktok\.com/.test(url)) {
    metadata = {
      id: tiktok(url),
      service: 'tiktok'
    };
  } else if (/(dailymotion\.com|dai\.ly)/.test(url)) {
    metadata = {
      id: dailymotion(url),
      service: 'dailymotion'
    };
  } else if (/loom\.com/.test(url)) {
    metadata = {
      id: loom(url),
      service: 'loom'
    };
  }
  return metadata;
}