Greasy Fork

Greasy Fork is available in English.

FR:Reborn

Show all QCs in TaoBao/Yupoo/etc

目前为 2021-06-04 提交的版本。查看 最新版本

// ==UserScript==
// @name         FR:Reborn
// @namespace    https://www.reddit.com/user/RobotOilInc
// @version      0.5.1
// @description  Show all QCs in TaoBao/Yupoo/etc
// @author       RobotOilInc
// @match        http://*/*
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @license      MIT
// @homepageURL  https://www.qc-server.cf/
// @supportURL   http://greasyfork.icu/en/scripts/426976-fr-es-viewer
// @include      /^https?://((?:item|2)\.taobao|detail\.tmall)\.com/(item|meal_detail)\.(htm|html)\?/
// @include      /^https?://world.(?:taobao|tmall).com/item/\d+.htm/
// @include      /^https?://world.(?:taobao|tmall).com/item/\d+.html/
// @include      /^https?://.*\.x\.yupoo\.com/albums/\d+/
// @require      https://unpkg.com/sweetalert2@11/dist/sweetalert2.min.js
// @require      https://unpkg.com/[email protected]/src/logger.min.js
// @require      https://unpkg.com/[email protected]/dist/jquery.min.js
// @require      https://unpkg.com/[email protected]/dist/swagger-client.browser.min.js
// @require      https://unpkg.com/[email protected]/js/iframeResizer.min.js
// @require      http://greasyfork.icu/scripts/11562-gm-config-8/code/GM_config%208+.js?version=66657
// @resource     sweetalert2 https://unpkg.com/[email protected]/dist/sweetalert2.min.css
// @run-at       document-end
// ==/UserScript==

/**
 * @param text {string}
 * @param type {null|('success'|'error'|'warning'|'info')}
 */
const Snackbar = function (text, type = null) {
  if (typeof type !== 'undefined' && type != null) {
    Swal.fire({
      title: text,
      icon: type,
      position: 'bottom-end',
      showConfirmButton: false,
      allowOutsideClick: false,
      backdrop: false,
      timer: 1500,
    });

    return;
  }

  Swal.fire({
    title: text,
    position: 'bottom-end',
    showConfirmButton: false,
    allowOutsideClick: false,
    backdrop: false,
    timer: 1500,
  });
};

class Taobao {
  /**
   * @param client {SwaggerClient}
   */
  constructor(client) {
    this.client = client;
  }

  loadIframe($iframe) {
    const searchParams = new URLSearchParams(window.location.search);
    const id = searchParams.get('id');

    // Build URL
    const request = SwaggerClient.buildRequest({
      spec: this.client.spec,
      operationId: 'viewTaobao',
      parameters: { id },
      responseContentType: 'application/json',
    });

    // Hide, to later show and add the src
    $iframe.hide()
      .css('width', '770px')
      .attr('src', request.url);

    // Finally prepend
    $('.attributes#attributes')
      .after($iframe);
  }

  /**
   * @param hostname {string}
   * @returns {boolean}
   */
  supports(hostname) {
    return hostname.includes('taobao')
      || hostname.includes('tmall');
  }
}

class Yupoo {
  /**
   * @param client {SwaggerClient}
   */
  constructor(client) {
    this.client = client;
  }

  loadIframe($iframe) {
    const id = window.location.href.match(/^https?:\/\/.*\.x\.yupoo\.com\/albums\/(\d+)/)[1];
    const author = window.location.hostname.replace('.x.yupoo.com', '');

    // Build URL
    const request = SwaggerClient.buildRequest({
      spec: this.client.spec,
      operationId: 'viewYupoo',
      parameters: { id, author },
      responseContentType: 'application/json',
    });

    // Hide, to later show and add the src
    $iframe.hide()
      .attr('src', request.url);

    // Finally append
    $('.showalbum__imagecardwrap')
      .append($iframe);
  }

  /**
   * @param hostname {string}
   * @returns {boolean}
   */
  supports(hostname) {
    return hostname.includes('yupoo.com');
  }
}

/**
 * @param client {SwaggerClient}
 * @param hostname {string}
 */
function getSource(client, hostname) {
  const sources = [new Taobao(client), new Yupoo(client)];

  let source;
  Object.values(sources).forEach((value) => {
    if (value.supports(hostname)) {
      source = value;
    }
  });

  return source;
}

// Inject snackbar css style
GM_addStyle(GM_getResourceText('sweetalert2'));

// Setup proper settings menu
GM_config.init('Settings', {
  serverSection: {
    label: 'QC Server settings',
    type: 'section',
  },
  swaggerDocUrl: {
    label: 'Swagger documentation URL',
    type: 'text',
    default: 'https://www.qc-server.cf/api/doc.json',
  },
});

// Reload page if config changed
GM_config.onclose = (saveFlag) => {
  if (saveFlag) {
    window.location.reload();
  }
};

// Register menu within GM
GM_registerMenuCommand('Settings', GM_config.open);

// eslint-disable-next-line func-names
(async function () {
  // Setup the logger.
  Logger.useDefaults();

  // Log the start of the script.
  Logger.info(`Starting extension, version ${GM_info.script.version}`);

  /** @type {SwaggerClient} */
  let client;

  // Try to create Swagger client from our own documentation
  try {
    client = await new SwaggerClient({ url: GM_config.get('swaggerDocUrl') });
  } catch (error) {
    Snackbar('We are unable to connect to FR:Reborn, features will be disabled.');
    Logger.error(`We are unable to connect to FR:Reborn: ${GM_config.get('swaggerDocUrl')}`, error);

    return;
  }

  // Create iFrame we will pass to all loaders, will show content once something has been loaded
  const $iframe = $('<iframe id="qciframe" style="border:0" />');
  $iframe.on('load', () => {
    $iframe.iFrameResize({ checkOrigin: ['https://localhost:8000', 'https://www.qc-server.cf'], bodyMargin: 10, bodyPadding: 10 });
    $iframe.show();
  });

  // Get the proper source view, if any
  const source = getSource(client, window.location.hostname);
  if (null !== source) {
    source.loadIframe($iframe);

    return;
  }

  Logger.error('Unsupported website');
}());