Weidian to Basetao

Add a Weidian order straight into BaseTao

目前為 2021-06-11 提交的版本,檢視 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Weidian to Basetao
// @namespace    https://www.reddit.com/user/RobotOilInc
// @version      1.0.5
// @description  Add a Weidian order straight into BaseTao
// @author       RobotOilInc
// @match        https://weidian.com/item.html*
// @match        https://*.weidian.com/item.html*
// @grant        GM_xmlhttpRequest
// @license      MIT
// @homepageURL  https://greasyfork.org/en/scripts/427774-weidian-to-basetao
// @supportURL   https://greasyfork.org/en/scripts/427774-weidian-to-basetao
// @require      https://unpkg.com/[email protected]/src/logger.min.js
// @require      https://unpkg.com/[email protected]/dist/jquery.min.js
// @require      https://greasyfork.org/scripts/401399-gm-xhr/code/GM%20XHR.js?version=938754
// @connect      basetao.com
// @run-at       document-end
// @icon         https://assets.geilicdn.com/fxxxx/favicon.ico
// ==/UserScript==

/**
 * Creates a SKU toast, which is shown because of Weidians CSS
 *
 * @param toast {string}
 */
const Snackbar = function (toast) {
  const $toast = $(`<div class="sku-toast">${toast}</div>`).css('font-size', '20px');

  // Append the toast to the body
  $('.sku-body').append($toast);

  // Set a timeout to remove it
  setTimeout(() => $toast.fadeOut('slow', () => { $toast.remove(); }), 2000);
};

// Chinese SKU names for colors
const chineseForColors = ['颜色'];

// Chinese SKU names for sizing
const chineseForSizing = ['尺寸', '尺码', '型号尺寸'];

/**
 * Waits for an element satisfying selector to exist, then resolves promise with the element.
 * Useful for resolving race conditions.
 *
 * @param selector {string}
 * @returns {Promise}
 */
const elementReady = function (selector) {
  return new Promise((resolve) => {
    const el = document.querySelector(selector);
    if (el) {
      resolve(el);
    }

    new MutationObserver((mutationRecords, observer) => {
      // Query for elements matching the specified selector
      Array.from(document.querySelectorAll(selector)).forEach((element) => {
        resolve(element);
        // Once we have resolved we don't need the observer anymore.
        observer.disconnect();
      });
    }).observe(document.documentElement, {
      childList: true,
      subtree: true,
    });
  });
};

/**
 * Trims the input text and removes all inbetween spaces as well.
 *
 * @param string {string}
 */
const removeWhitespaces = (string) => string.trim().replace(/\s(?=\s)/g, '');

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

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

  // Setup GM_XHR
  $.ajaxSetup({ xhr() { return new GM_XHR(); } });

  // Build the basic buttons
  const $button = $('<button>Add to BaseTao</button>').css('background', '#f29800').css('font-size', '15px').css('color', '#FFFFFF')
    .css('text-align', 'center')
    .css('padding', '15px 0')
    .css('width', '100%')
    .css('height', '100%');

  // Attach click handler
  $button.on('click', async () => {
    // Disable button to prevent double clicks and show clear message
    $button.attr('disabled', true).text('Processing...');

    // Grab data required to add the order
    const data = await $.get('https://www.basetao.com/index/selfhelporder.html');

    // Check if user is actually logged in
    if (data.indexOf('long time no operation ,please sign in again') !== -1) {
      Snackbar('You need to be logged in on BaseTao to use this extension (CSRF).');
      $button.attr('disabled', false).text('Add to BaseTao');

      return;
    }

    // Convert into jQuery object
    const $data = $(data);

    // Get the username
    const username = $data.find('#dropdownMenu1').text();
    if (typeof username === 'undefined' || username == null || username === '') {
      Snackbar('You need to be logged in on BaseTao to use this extension (CSRF).');
      $button.attr('disabled', false).text('Add to BaseTao');

      return;
    }

    // Build items from Basetao
    const csrf = $data.find('input[name=csrf_test_name]').first().val();

    // Items from Weidian
    const price = Number(removeWhitespaces($('.sku-cur-price').text()).replace(/(\D+)/, ''));
    const shopName = removeWhitespaces($('.shop-toggle-header-name').text());
    const itemName = removeWhitespaces($('.item-title').text());
    const imageUrl = $('img#skuPic').attr('src');

    // Create dynamic items
    let selectedColor = null;
    let selectedSize = null;
    let canContinue = true;

    // Try and find the proper SKU rows
    $('.sku-content .sku-row').each((key, value) => {
      const rowTitle = $(value).find('.row-title').text();

      // Check if this is color
      if (chineseForColors.includes(rowTitle)) {
        const selectedItem = $(value).find('.sku-item.selected');
        if (selectedItem.length === 0) {
          canContinue = false;

          return;
        }

        selectedColor = removeWhitespaces(selectedItem.text());
      }

      // Check if this is size
      if (chineseForSizing.includes(rowTitle)) {
        const selectedItem = $(value).find('.sku-item.selected');
        if (selectedItem.length === 0) {
          canContinue = false;

          return;
        }

        selectedSize = removeWhitespaces(selectedItem.text());
      }
    });

    // Check if anything was missed
    if (canContinue === false) {
      Snackbar('You are missing a required option (color/size)');
      $button.attr('disabled', false).text('Add to BaseTao');

      return;
    }

    // Build the data we will send
    const baseTaoData = {
      csrf_test_name: csrf,
      color: selectedColor,
      size: selectedSize,
      number: 1,
      pric: price,
      shipping: 10,
      totalpric: price + 10,
      t_title: itemName,
      t_seller: shopName,
      t_img: imageUrl,
      t_href: window.location.href,
      s_url: window.location.href,
      buyyourself: 1,
      site: null,
      note: null,
    };

    Logger.info('Sending order to BaseTao...', baseTaoData);

    $.ajax({
      url: 'https://www.basetao.com/index/Ajax_data/buyonecart',
      type: 'POST',
      headers: {
        origin: 'https://www.basetao.com',
        referer: 'https://www.basetao.com/index/selfhelporder.html',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36',
        'x-requested-with': 'XMLHttpRequest',
      },
      data: baseTaoData,
    }).then((response) => {
      if (removeWhitespaces(response) !== '1') {
        Logger.error('Item could not be added', response);
        Snackbar('Item could not be added, make sure you are logged in');

        return;
      }

      Snackbar('Item has been added, be sure to double check it');

      // Remove button once done
      $button.fadeOut('slow', () => { $button.remove(); });
    }).catch((err) => {
      Logger.error('An error happened when uploading the image', err);
      Snackbar('An error happened when adding the order');
    });
  });

  // Setup for when someone presses the buy button
  elementReady('.sku-footer').then((element) => {
    $(element).before($button);
  });
}());