Greasy Fork

Greasy Fork is available in English.

Stores to Agent

Adds an order directly from stores to your agent

当前为 2022-12-13 提交的版本,查看 最新版本

// ==UserScript==
// @name          Stores to Agent
// @namespace     https://www.reddit.com/user/RobotOilInc
// @version       4.0.6
// @author        RobotOilInc
// @source        https://gitlab.com/robotoilinc/stores-to-agents/
// @license       MIT
// @require       https://unpkg.com/[email protected]/dist/axios.min.js#sha384-vmbbJNC6Li6w5GzrydJ5cd4ttMcLJ/Nl5xgp5saZ5QV8fp7zdsrFDcCasGqOFlaC
// @require       https://unpkg.com/[email protected]/dist/axiosGmxhrAdapter.min.js#sha384-zLl38UTizqOVmTBf0gUo342oP5vEKIj6j4Ap0ldlotJFjDWTXIeHDm2Lk5DeB5wL
// @require       https://unpkg.com/[email protected]/dist/index.umd.min.js#sha384-IforrfCAVNj1KYlzIXNAyX2RADvDkkufuRfcM0qT57QMNdEonuvBRK2WfL8Co3JV
// @require       https://unpkg.com/[email protected]/gm4-polyfill.js#sha384-nDSbBzN1Jn1VgjQjt5u2BxaPO1pbMS9Gxyi5+yIsKYWzqkYOEh11iQdomqywYPaN
// @require       https://unpkg.com/[email protected]/dist/jquery.min.js#sha384-vtXRMe3mGCbOeY7l30aIg8H9p3GdeSe4IFlP6G8JMa7o7lXvnz3GFKzPxzJdPfGK
// @require       https://unpkg.com/[email protected]/src/logger.min.js#sha384-CGmI56C3Kvs2e+Ftr3UpFkkMgOAXBUkLKS/KVkxDEuGSUYF8qki7CzwWWBz4QM60
// @require       http://greasyfork.icu/scripts/11562-gm-config-8/code/GM_config%208+.js?version=66657#sha256-229668ef83cd26ac207e9d780e2bba6658e1506ac0b23fb29dc94ae531dd31fb
// @description   Adds an order directly from stores to your agent
// @homepageURL   http://greasyfork.icu/en/scripts/427774-stores-to-agent
// @supportURL    http://greasyfork.icu/en/scripts/427774-stores-to-agent
// @match         https://detail.1688.com/offer/*
// @match         https://*.taobao.com/item.htm*
// @match         https://*.v.weidian.com/?userid=*
// @match         https://*.weidian.com/item.html*
// @match         https://*.yupoo.com/albums/*
// @match         https://detail.tmall.com/item.htm*
// @match         https://weidian.com/*itemID=*
// @match         https://weidian.com/?userid=*
// @match         https://weidian.com/item.html*
// @match         https://*.pandabuy.com/*
// @match         https://www.pandabuy.com/*
// @grant         GM_addStyle
// @grant         GM_getResourceText
// @grant         GM_getValue
// @grant         GM_setValue
// @grant         GM_registerMenuCommand
// @grant         GM_webRequest
// @grant         GM_xmlhttpRequest
// @grant         GM_deleteValue
// @grant         GM_listValues
// @connect       basetao.com
// @connect       cssbuy.com
// @connect       superbuy.com
// @connect       ytaopal.com
// @connect       wegobuy.com
// @connect       pandabuy.com
// @webRequest    [{ "selector": "*thor.weidian.com/stardust/*", "action": "cancel" }]
// @icon          https://i.imgur.com/2lQXuqv.png
// @run-at        document-end
// ==/UserScript==


/*! @robotoilinc/stores-to-agents v4.0.6 has been created by RobotOilInc. All rights reserved. */
/******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ "./node_modules/object-to-formdata/src/index.js":
/***/ ((module) => {

function isUndefined(value) {
  return value === undefined;
}

function isNull(value) {
  return value === null;
}

function isBoolean(value) {
  return typeof value === 'boolean';
}

function isObject(value) {
  return value === Object(value);
}

function isArray(value) {
  return Array.isArray(value);
}

function isDate(value) {
  return value instanceof Date;
}

function isBlob(value, isReactNative) {
  return isReactNative ? isObject(value) && !isUndefined(value.uri) : isObject(value) && typeof value.size === 'number' && typeof value.type === 'string' && typeof value.slice === 'function';
}

function isFile(value, isReactNative) {
  return isBlob(value, isReactNative) && typeof value.name === 'string' && (isObject(value.lastModifiedDate) || typeof value.lastModified === 'number');
}

function initCfg(value) {
  return isUndefined(value) ? false : value;
}

function serialize(obj, cfg, fd, pre) {
  cfg = cfg || {};
  fd = fd || new FormData();
  cfg.indices = initCfg(cfg.indices);
  cfg.nullsAsUndefineds = initCfg(cfg.nullsAsUndefineds);
  cfg.booleansAsIntegers = initCfg(cfg.booleansAsIntegers);
  cfg.allowEmptyArrays = initCfg(cfg.allowEmptyArrays);
  cfg.noFilesWithArrayNotation = initCfg(cfg.noFilesWithArrayNotation);
  cfg.dotsForObjectNotation = initCfg(cfg.dotsForObjectNotation);
  const isReactNative = typeof fd.getParts === 'function';

  if (isUndefined(obj)) {
    return fd;
  } else if (isNull(obj)) {
    if (!cfg.nullsAsUndefineds) {
      fd.append(pre, '');
    }
  } else if (isBoolean(obj)) {
    if (cfg.booleansAsIntegers) {
      fd.append(pre, obj ? 1 : 0);
    } else {
      fd.append(pre, obj);
    }
  } else if (isArray(obj)) {
    if (obj.length) {
      obj.forEach((value, index) => {
        let key = pre + '[' + (cfg.indices ? index : '') + ']';

        if (cfg.noFilesWithArrayNotation && isFile(value, isReactNative)) {
          key = pre;
        }

        serialize(value, cfg, fd, key);
      });
    } else if (cfg.allowEmptyArrays) {
      fd.append(pre + '[]', '');
    }
  } else if (isDate(obj)) {
    fd.append(pre, obj.toISOString());
  } else if (isObject(obj) && !isBlob(obj, isReactNative)) {
    Object.keys(obj).forEach(prop => {
      const value = obj[prop];

      if (isArray(value)) {
        while (prop.length > 2 && prop.lastIndexOf('[]') === prop.length - 2) {
          prop = prop.substring(0, prop.length - 2);
        }
      }

      const key = pre ? cfg.dotsForObjectNotation ? pre + '.' + prop : pre + '[' + prop + ']' : prop;
      serialize(value, cfg, fd, key);
    });
  } else {
    fd.append(pre, obj);
  }

  return fd;
}

module.exports = {
  serialize
};

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	(() => {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = (module) => {
/******/ 			var getter = module && module.__esModule ?
/******/ 				() => (module['default']) :
/******/ 				() => (module);
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be in strict mode.
(() => {
"use strict";

;// CONCATENATED MODULE: external "Logger"
const external_Logger_namespaceObject = Logger;
var external_Logger_default = /*#__PURE__*/__webpack_require__.n(external_Logger_namespaceObject);
;// CONCATENATED MODULE: external "GMStorage"
const external_GMStorage_namespaceObject = GMStorage;
var external_GMStorage_default = /*#__PURE__*/__webpack_require__.n(external_GMStorage_namespaceObject);
;// CONCATENATED MODULE: ./src/Constants.ts
const PandaBuyToken = "PANDABUY_TOKEN";
const PandaBuyUserInfo = "PANDABUY_USERINFO";
;// CONCATENATED MODULE: ./src/exceptions/PandaBuyError.ts
class PandaBuyError extends Error {
  constructor(message) {
    super(message);
    this.name = "PandaBuyError";
  }

}
;// CONCATENATED MODULE: ./src/helpers/StorageHelper.ts
class LocalStorage {
  constructor() {
    this.localStorageSupported = typeof window["localStorage"] != "undefined" && window["localStorage"] != null;
  } // add value to storage


  add(key, item) {
    if (this.localStorageSupported) {
      localStorage.setItem(key, item);
    }
  } // get one item by key from storage


  get(key) {
    if (this.localStorageSupported) {
      return localStorage.getItem(key);
    }

    return null;
  } // remove value from storage


  remove(key) {
    if (this.localStorageSupported) {
      localStorage.removeItem(key);
    }
  } // clear storage (remove all items from it)


  clear() {
    if (this.localStorageSupported) {
      localStorage.clear();
    }
  }

}
;// CONCATENATED MODULE: ./src/agents/login/Pandabuy.ts





class PandaBuyLogin {
  constructor() {
    this.store = new (external_GMStorage_default())();
    this.localStorage = new LocalStorage();
  }

  supports(hostname) {
    return hostname.includes("pandabuy.com");
  }

  process() {
    // If we already have a token, don't bother
    const currentToken = this.store.get(PandaBuyToken, null);

    if (currentToken !== null && currentToken.length !== 0) {
      return;
    } // Don't bother with getting the token, if we aren't loggeed in yet


    const userInfo = this.localStorage.get(PandaBuyUserInfo);

    if (userInfo === null || userInfo.length === 0) {
      return;
    } // The token should now exist


    const updatedToken = this.localStorage.get(PandaBuyToken);

    if (updatedToken === null || updatedToken.length === 0) {
      throw new PandaBuyError("Could not retrieve token");
    } // Store it internally


    this.store.set(PandaBuyToken, updatedToken);
    external_Logger_default().info("Updated the PandaBuy Authorization Token");
  }

}
;// CONCATENATED MODULE: ./src/agents/login/Logins.ts

function getLogin(hostname) {
  const agents = [new PandaBuyLogin()];
  let agent = null;
  Object.values(agents).forEach(value => {
    if (value.supports(hostname)) {
      agent = value;
    }
  });
  return agent;
}
// EXTERNAL MODULE: ./node_modules/object-to-formdata/src/index.js
var src = __webpack_require__("./node_modules/object-to-formdata/src/index.js");
;// CONCATENATED MODULE: ./src/exceptions/BaseTaoError.ts
class BaseTaoError extends Error {
  constructor(message) {
    super(message);
    this.name = "BaseTaoError";
  }

}
;// CONCATENATED MODULE: external "axios"
const external_axios_namespaceObject = axios;
var external_axios_default = /*#__PURE__*/__webpack_require__.n(external_axios_namespaceObject);
;// CONCATENATED MODULE: external "axiosGmxhrAdapter"
const external_axiosGmxhrAdapter_namespaceObject = axiosGmxhrAdapter;
var external_axiosGmxhrAdapter_default = /*#__PURE__*/__webpack_require__.n(external_axiosGmxhrAdapter_namespaceObject);
;// CONCATENATED MODULE: ./src/helpers/Axios.ts


function get(url, config) {
  return external_axios_default().get(url, {
    adapter: (external_axiosGmxhrAdapter_default()),
    ...config
  });
}
function post(url, data, config) {
  return external_axios_default().post(url, data, {
    adapter: (external_axiosGmxhrAdapter_default()),
    ...config
  });
}
;// CONCATENATED MODULE: ./src/helpers/RemoveEmoji.ts
/**
 * Removes all emojis from the input text.
 *
 * @param string {string}
 */
const removeEmoji = string => string.replace(/[^\p{L}\p{N}\p{P}\p{Z}^$\n]/gu, "");
;// CONCATENATED MODULE: ./src/helpers/RemoveWhitespaces.ts
/**
 * Trims the input text and removes all in between spaces as well.
 *
 * @param string {string}
 */
const removeWhitespaces = string => $.trim(string).replace(/\s(?=\s)/g, "");
;// CONCATENATED MODULE: ./src/agents/BaseTao.ts






const CSRF_REQUIRED_ERROR = "You need to be logged in on BaseTao to use this extension (CSRF required).";
class BaseTao {
  constructor() {
    this.parser = new DOMParser();
  }

  get name() {
    return "BaseTao";
  }

  async send(order) {
    // Get proper domain to use
    const properDomain = await this._getDomain(); // Build the purchase data

    const purchaseData = await this._buildPurchaseData(properDomain, order);
    external_Logger_default().info("Sending order to BaseTao...", properDomain, purchaseData); // Do the actual call

    const response = await post(`${properDomain}/index/Ajax_data/buyonecart`, (0,src.serialize)(purchaseData), {
      headers: {
        origin: `${properDomain}`,
        referer: `${properDomain}/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"
      }
    });

    if (removeWhitespaces(response.data) === "1") {
      return;
    }

    external_Logger_default().error("Item could not be added", response.data);
    throw new BaseTaoError("Item could not be added, make sure you are logged in");
  }

  async _getDomain() {
    // Try HTTPS (with WWW) first
    let response = await get("https://www.basetao.com/index/selfhelporder.html");
    let doc = this.parser.parseFromString(response.data, "text/html");
    let csrfToken = doc.querySelector("input[name=csrf_test_name]");

    if (csrfToken && csrfToken.value.length !== 0) {
      return "https://www.basetao.com";
    } // Try HTTPS (without WWW) after


    response = await get("https://basetao.com/index/selfhelporder.html");
    doc = this.parser.parseFromString(response.data, "text/html");
    csrfToken = doc.querySelector("input[name=csrf_test_name]");

    if (csrfToken && csrfToken.value.length !== 0) {
      return "https://basetao.com";
    } // User is not logged in/there is an issue


    throw new Error(CSRF_REQUIRED_ERROR);
  }

  async _buildPurchaseData(properDomain, order) {
    // Get the CSRF token
    const csrf = await this._getCSRF(properDomain); // Build the data we will send

    return {
      csrf_test_name: csrf,
      color: order.item.color,
      size: order.item.size,
      number: 1,
      pric: order.price,
      shipping: order.shipping,
      totalpric: order.price + order.shipping,
      t_title: encodeURIComponent(removeEmoji(order.item.name)),
      t_seller: encodeURIComponent(removeEmoji(order.shop.name ?? "")),
      t_img: encodeURIComponent(order.item.imageUrl),
      t_href: encodeURIComponent(window.location.href),
      s_url: encodeURIComponent(order.shop.url ?? ""),
      buyyourself: 1,
      note: this._buildRemark(order),
      item_id: order.item.id,
      sku_id: 0
    };
  }

  async _getCSRF(properDomain) {
    // Grab data from BaseTao
    const response = await get(`${properDomain}/index/selfhelporder.html`); // Check if user is actually logged in

    if (response.data.includes("please sign in again")) {
      throw new Error(CSRF_REQUIRED_ERROR);
    }

    const doc = this.parser.parseFromString(response.data, "text/html");
    const csrfToken = doc.querySelector("input[name=csrf_test_name]");

    if (csrfToken && csrfToken.value.length !== 0) {
      return csrfToken.value;
    } // Return CSRF


    throw new Error(CSRF_REQUIRED_ERROR);
  }

  _buildRemark(order) {
    const descriptionParts = [];
    if (order.item.model !== null) descriptionParts.push(`Model: ${order.item.model}`);
    if (order.item.other.length !== 0) descriptionParts.push(order.item.other);
    let description = null;

    if (descriptionParts.length !== 0) {
      description = descriptionParts.join(" / ");
    }

    return description;
  }

}
;// CONCATENATED MODULE: ./src/exceptions/CSSBuyError.ts
class CSSBuyError extends Error {
  constructor(message) {
    super(message);
    this.name = "CSSBuyError";
  }

}
;// CONCATENATED MODULE: ./src/agents/CSSBuy.ts




class CSSBuy {
  get name() {
    return "CSSBuy";
  }

  async send(order) {
    // Build the purchase data
    const purchaseData = this._buildPurchaseData(order);

    external_Logger_default().info("Sending order to CSSBuy...", purchaseData); // Do the actual call

    const response = await post("https://www.cssbuy.com/ajax/fast_ajax.php?action=buyone", (0,src.serialize)(purchaseData), {
      headers: {
        "accept": "application/json, text/javascript, */*; q=0.01",
        "accept-language": "nl,en-US;q=0.9,en;q=0.8,de;q=0.7,und;q=0.6",
        "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
        "referrer": `https://www.cssbuy.com/?go=item&url=${encodeURIComponent(purchaseData.data.href)}`,
        "referrerPolicy": "strict-origin-when-cross-origin",
        "x-requested-with": "XMLHttpRequest"
      }
    });

    if (response.data.ret === 0) {
      return;
    }

    external_Logger_default().error("Item could not be added", response);
    throw new CSSBuyError("Item could not be added");
  }

  _buildPurchaseData(order) {
    // Build the description
    const description = this._buildRemark(order); // Create the purchasing data


    return {
      data: {
        buynum: 1,
        shopid: order.shop.id,
        picture: order.item.imageUrl,
        defaultimg: order.item.imageUrl,
        freight: order.shipping,
        price: order.price,
        color: order.item.color,
        size: order.item.size,
        total: order.price + order.shipping,
        buyyourself: 0,
        seller: order.shop.name,
        href: window.location.href,
        title: order.item.name,
        note: description,
        option: description
      }
    };
  }

  _buildRemark(order) {
    const descriptionParts = [];
    if (order.item.model !== null) descriptionParts.push(`Model: ${order.item.model}`);
    if (order.item.color !== null) descriptionParts.push(`Color: ${order.item.color}`);
    if (order.item.size !== null) descriptionParts.push(`Size: ${order.item.size}`);
    if (order.item.other.length !== 0) descriptionParts.push(`${order.item.other}`);
    let description = null;

    if (descriptionParts.length !== 0) {
      description = descriptionParts.join(" / ");
    }

    return description;
  }

}
;// CONCATENATED MODULE: ./src/agents/PandaBuy.ts





class PandaBuy {
  constructor() {
    this.store = new (external_GMStorage_default())();
  }

  get name() {
    return "PandaBuy";
  }

  async send(order) {
    const token = this.store.get(PandaBuyToken, null);

    if (token === null || token.length === 0) {
      throw new PandaBuyError("We do not have your PandaBuy authorization token yet. Please visit PandaBuy (and login if needed)");
    } // Build the purchase data


    const purchaseData = this._buildPurchaseData(order);

    external_Logger_default().info("Sending order to PandaBuy...", purchaseData); // Do the actual call

    await post("https://www.pandabuy.com/gateway/user/cart/add", JSON.stringify(purchaseData), {
      responseType: "json",
      withCredentials: true,
      headers: {
        accept: "application/json, text/plain, */*",
        authorization: `Bearer ${token}`,
        "content-type": "application/json;charset=UTF-8",
        currency: "CNY",
        lang: "en",
        referrer: `https://www.pandabuy.com/uniorder?text=${encodeURIComponent(window.location.href)}`,
        referrerPolicy: "strict-origin-when-cross-origin"
      }
    }).then(response => {
      if (response.data.code === 200 && response.data.msg === null) {
        return;
      }

      external_Logger_default().error("Item could not be added", response.data.msg);
      throw new PandaBuyError("Item could not be added");
    }).catch(err => {
      // If the error is our own, just rethrow it
      if (err instanceof PandaBuyError) {
        throw err;
      } // Our token has expired


      if (err.response.status === 401) {
        // Reset the current token
        GM_setValue(PandaBuyToken, null);
        external_Logger_default().error("PandaBuy authorization token has expired");
        throw new PandaBuyError("Your PandaBuy authorization token has expired. Please visit PandaBuy (or login at PandaBuy) again");
      }

      external_Logger_default().error("An error happened when uploading the order", err);
      throw new Error("An error happened when adding the order");
    });
  }

  _buildPurchaseData(order) {
    // Build the description
    const description = this._buildRemark(order); // Create the purchasing data


    return {
      storeName: order.shop.name,
      storeId: order.shop.id,
      goodsUrl: window.location.href,
      goodsName: order.item.name,
      goodsAttr: description,
      storageNo: 1,
      goodsPrice: order.price,
      goodsNum: 1,
      fare: order.shipping,
      remark: "|",
      selected: 1,
      purchaseType: 1,
      goodsImg: order.item.imageUrl,
      servicePrice: "0.00",
      writePrice: order.price,
      actPrice: order.price,
      storeSource: this._buildStoreSource(),
      goodsId: order.item.id
    };
  }

  _buildRemark(order) {
    const descriptionParts = [];
    if (order.item.model !== null && order.item.model.length !== 0) descriptionParts.push(`Model: ${order.item.model}`);
    if (order.item.color !== null && order.item.color.length !== 0) descriptionParts.push(`Color: ${order.item.color}`);
    if (order.item.size !== null && order.item.size.length !== 0) descriptionParts.push(`Size: ${order.item.size}`);
    if (order.item.other.length !== 0) descriptionParts.push(`${order.item.other}`);
    let description = null;

    if (descriptionParts.length !== 0) {
      description = descriptionParts.join(" / ");
    }

    return description;
  }

  _buildStoreSource() {
    if (window.location.hostname.includes("1688.com")) {
      return "1688";
    }

    if (window.location.hostname.includes("taobao.com")) {
      return "taobao";
    }

    if (window.location.hostname.includes("weidian.com")) {
      return "weidian";
    }

    if (window.location.hostname.includes("yupoo.com")) {
      return "yupoo";
    }

    if (window.location.hostname === "detail.tmall.com") {
      return "tmall";
    }

    throw new PandaBuyError(`Could not determine store source ${window.location.hostname}`);
  }

}
;// CONCATENATED MODULE: ./src/exceptions/SuperBuyError.ts
class SuperBuyError extends Error {
  constructor(message) {
    super(message);
    this.name = "SuperBuyError";
  }

}
;// CONCATENATED MODULE: ./src/helpers/BuildTaoCarts.ts
class BuildTaoCarts {
  purchaseData(order) {
    // Build the description
    const description = this._buildRemark(order); // Generate an SKU based on the description


    let sku = null;

    if (description !== null && description.length !== 0) {
      sku = description.split("").reduce((a, b) => (a << 5) - a + b.charCodeAt(0) | 0, 0);
    } // Create the purchasing data


    return {
      type: 1,
      shopItems: [{
        shopLink: "",
        shopSource: "NOCRAWLER",
        shopNick: "",
        shopId: "",
        goodsItems: [{
          beginCount: 0,
          count: 1,
          desc: description,
          freight: order.shipping,
          freightServiceCharge: 0,
          goodsAddTime: Math.floor(Date.now() / 1000),
          goodsCode: `NOCRAWLER-${sku}`,
          goodsId: window.location.href,
          goodsLink: window.location.href,
          goodsName: order.item.name,
          goodsPrifex: "NOCRAWLER",
          goodsRemark: description,
          guideGoodsId: "",
          is1111Yushou: "no",
          picture: order.item.imageUrl,
          platForm: "pc",
          price: order.price,
          priceNote: "",
          serviceCharge: 0,
          sku: order.item.imageUrl,
          spm: "",
          warehouseId: "1"
        }]
      }]
    };
  }

  _buildRemark(order) {
    const descriptionParts = [];
    if (order.item.model !== null) descriptionParts.push(`Model: ${order.item.model}`);
    if (order.item.color !== null) descriptionParts.push(`Color: ${order.item.color}`);
    if (order.item.size !== null) descriptionParts.push(`Size: ${order.item.size}`);
    if (order.item.other.length !== 0) descriptionParts.push(`${order.item.other}`);
    let description = null;

    if (descriptionParts.length !== 0) {
      description = descriptionParts.join(" / ");
    }

    return description;
  }

}
;// CONCATENATED MODULE: ./src/agents/SuperBuy.ts




class SuperBuy {
  constructor() {
    this._builder = new BuildTaoCarts();
  }

  get name() {
    return "SuperBuy";
  }

  async send(order) {
    // Build the purchase data
    const purchaseData = this._builder.purchaseData(order);

    external_Logger_default().info("Sending order to SuperBuy...", purchaseData); // Do the actual call

    const response = await post("https://front.superbuy.com/cart/add-cart", JSON.stringify(purchaseData), {
      responseType: "json",
      headers: {
        origin: "https://www.superbuy.com",
        referer: "https://www.superbuy.com/",
        "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"
      }
    });

    if (response.data.state === 0 && response.data.msg === "Success") {
      return;
    }

    external_Logger_default().error("Item could not be added", response.data.msg);
    throw new SuperBuyError("Item could not be added");
  }

}
;// CONCATENATED MODULE: ./src/exceptions/WeGoBuyError.ts
class WeGoBuyError extends Error {
  constructor(message) {
    super(message);
    this.name = "WeGoBuyError";
  }

}
;// CONCATENATED MODULE: ./src/agents/WeGoBuy.ts




class WeGoBuy {
  constructor() {
    this._builder = new BuildTaoCarts();
  }

  get name() {
    return "WeGoBuy";
  }

  async send(order) {
    // Build the purchase data
    const purchaseData = this._builder.purchaseData(order);

    external_Logger_default().info("Sending order to WeGoBuy...", purchaseData); // Do the actual call

    const response = await post("https://front.wegobuy.com/cart/add-cart", JSON.stringify(purchaseData), {
      responseType: "json",
      headers: {
        origin: "https://www.superbuy.com",
        referer: "https://www.superbuy.com/",
        "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"
      }
    });

    if (response.data.state === 0 && response.data.msg === "Success") {
      return;
    }

    external_Logger_default().error("Item could not be added", response.data.msg);
    throw new WeGoBuyError("Item could not be added");
  }

}
;// CONCATENATED MODULE: ./src/agents/Agents.ts





const getAgent = selection => {
  switch (selection) {
    case "basetao":
      return new BaseTao();

    case "cssbuy":
      return new CSSBuy();

    case "pandabuy":
      return new PandaBuy();

    case "superbuy":
      return new SuperBuy();

    case "wegobuy":
      return new WeGoBuy();

    default:
      throw new Error(`Agent '${selection}' is not implemented`);
  }
};
;// CONCATENATED MODULE: ./src/classes/Item.ts
class Item {
  constructor(id, name, imageUrl, model, color, size, others) {
    this.id = id;
    this.name = name;
    this.imageUrl = imageUrl;
    this.model = model;
    this.color = color;
    this.size = size;
    this.others = others;
  }

  get other() {
    return this.others.join("\n");
  }

}
;// CONCATENATED MODULE: ./src/classes/Order.ts
class Order {
  constructor(shop, item, price, shipping) {
    this.shop = shop;
    this.item = item;
    this.price = price;
    this.shipping = shipping;
  }

}
;// CONCATENATED MODULE: ./src/classes/Shop.ts
class Shop {
  constructor(id, name, url) {
    this.id = id;
    this.name = name;
    this.url = url;
  }

}
;// CONCATENATED MODULE: ./src/helpers/ElementReady.ts
/**
 * Waits for an element satisfying selector to exist, then resolves promise with the element.
 * Useful for resolving race conditions.
 */
const elementReady = function (selector) {
  return new Promise(resolve => {
    // Check if the element already exists
    const element = document.querySelector(selector);

    if (element) {
      resolve(element);
    } // It doesn't so, so let's make a mutation observer and wait


    new MutationObserver((mutationRecords, observer) => {
      // Query for elements matching the specified selector
      Array.from(document.querySelectorAll(selector)).forEach(foundElement => {
        // Resolve the element that we found
        resolve(foundElement); // Once we have resolved we don't need the observer anymore.

        observer.disconnect();
      });
    }).observe(document.documentElement, {
      childList: true,
      subtree: true
    });
  });
};
;// CONCATENATED MODULE: ./src/helpers/Snackbar.ts

const Snackbar = function (toast) {
  // Log the snackbar, for ease of debugging
  external_Logger_default().info(toast); // Setup toast element

  const $toast = $(`<div style="background-color:#333;border-radius:2px;bottom:50%;color:#fff;display:block;font-size:16px;left:50%;margin-left:-150px;min-width:250px;opacity:1;padding:16px;position:fixed;right:50%;text-align:center;transition:background .2s;width:300px;z-index:2147483647">${toast}</div>`); // Append to the body

  $("body").append($toast); // Set a timeout to remove the toast

  setTimeout(() => $toast.fadeOut("slow", () => $toast.remove()), 5000);
};
;// CONCATENATED MODULE: ./src/stores/1688.ts








class Store1688 {
  constructor() {
    this.store = new (external_GMStorage_default())();
  }

  attach($document, localWindow) {
    elementReady(".order-button-wrapper > .order-button-children > .order-button-children-list").then(element => {
      const button = this._buildButton($document, localWindow);

      if (button === null) {
        return;
      }

      $(element).prepend(button);
    });
  }

  supports(hostname) {
    return hostname.includes("1688.com");
  }

  _buildButton($document, window) {
    // Force someone to select an agent
    if (this.store.get("agentSelection") === "empty") {
      GM_config.open();
      Snackbar("Please select what agent you use");
      return null;
    } // Get the agent related to our config


    const agent = getAgent(this.store.get("agentSelection", "")); // Create button

    const $button = $(`<button id="agent-button" class="order-normal-button order-button">Add to ${agent.name}</button>`);
    $button.on("click", async () => {
      // Disable button to prevent double clicks and show clear message
      $button.attr("disabled", "disabled").text("Processing..."); // Try to build and send the order

      try {
        await agent.send(this._buildOrder($document, window));
      } catch (err) {
        $button.attr("disabled", null).text(`Add to ${agent.name}`);
        return Snackbar(err);
      }

      $button.attr("disabled", null).text(`Add to ${agent.name}`); // Success, tell the user

      return Snackbar("Item has been added, be sure to double check it");
    });
    return $('<div class="order-button-tip-wrapper"></div>').append($button);
  }

  _buildShop(window) {
    const id = window.__GLOBAL_DATA.offerBaseInfo.sellerUserId;
    const name = window.__GLOBAL_DATA.offerBaseInfo.sellerLoginId;
    const url = new URL(window.__GLOBAL_DATA.offerBaseInfo.sellerWinportUrl, window.location).toString();
    return new Shop(id, name, url);
  }

  _buildItem($document, window) {
    // Build item information
    const id = window.__GLOBAL_DATA.tempModel.offerId;
    const name = removeWhitespaces(window.__GLOBAL_DATA.tempModel.offerTitle); // Build image information

    const imageUrl = new URL(window.__GLOBAL_DATA.images[0].size310x310ImageURI, window.location).toString(); // Retrieve the dynamic selected item

    const skus = this._processSku($document);

    return new Item(id, name, imageUrl, null, null, null, skus);
  }

  _buildPrice($document) {
    return Number(removeWhitespaces($document.find(".order-price-wrapper .total-price .value").text()));
  }

  _buildShipping($document) {
    return Number(removeWhitespaces($document.find(".logistics-express .logistics-express-price").text()));
  }

  _buildOrder($document, window) {
    return new Order(this._buildShop(window), this._buildItem($document, window), this._buildPrice($document), this._buildShipping($document));
  }

  _processSku($document) {
    const selectedItems = []; // Grab the module that holds the selected data

    const skuData = this._findModule($document.find(".pc-sku-wrapper")[0]).getSkuData(); // Grab the map we can use to find names


    const skuMap = skuData.skuState.skuSpecIdMap; // Parse all the selected items

    const selectedData = skuData.skuPannelInfo.getSubmitData().submitData; // Ensure at least one item is selected

    if (typeof selectedData.find(item => item.specId !== null) === "undefined") {
      throw new Error("Make sure to select at least one item");
    } // Process all selections


    selectedData.forEach(item => {
      const sku = skuMap[item.specId]; // Build the proper name

      let name = removeWhitespaces(sku.firstProp);

      if (sku.secondProp != null && sku.secondProp.length !== 0) {
        name = `${name} - ${removeWhitespaces(sku.secondProp)}`;
      } // Add it to the list with quantity


      selectedItems.push(`${name}: ${item.quantity}x`);
    });
    return selectedItems;
  }

  _findModule($element) {
    const instanceKey = Object.keys($element).find(key => key.startsWith("__reactInternalInstance$"));
    const internalInstance = $element[instanceKey];
    if (internalInstance == null) return null;
    return internalInstance.return.ref.current;
  }

}
;// CONCATENATED MODULE: ./src/Enums.ts
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

class Enum {
  constructor() {
    _defineProperty(this, "_model", ["型号", "模型", "模型", "model", "type"]);

    _defineProperty(this, "_colors", ["颜色", "彩色", "色", "色彩", "配色", "配色方案", "color", "colour", "color scheme"]);

    _defineProperty(this, "_sizing", ["尺寸", "尺码", "型号尺寸", "大小", "浆液", "码数", "码", "size", "sizing"]);
  }

  isModel(item) {
    return this._arrayContains(this._model, item);
  }

  isColor(item) {
    return this._arrayContains(this._colors, item);
  }

  isSize(item) {
    return this._arrayContains(this._sizing, item);
  }

  _arrayContains(array, query) {
    return array.filter(item => query.toLowerCase().indexOf(item.toLowerCase()) !== -1).length !== 0;
  }

}
;// CONCATENATED MODULE: ./src/helpers/Capitalize.ts
/**
 * @param s {string|undefined}
 * @returns {string}
 */
const capitalize = s => s && s[0].toUpperCase() + s.slice(1) || "";
;// CONCATENATED MODULE: ./src/helpers/RetrieveDynamicInformation.ts



const retrieveDynamicInformation = ($document, rowCss, rowTitleCss, selectedItemCss) => {
  // Create dynamic items
  let model = null;
  let color = null;
  let size = null;
  const others = []; // Load dynamic items

  $document.find(rowCss).each((key, value) => {
    const _enum = new Enum();

    const rowTitle = $(value).find(rowTitleCss).text();
    const selectedItem = $(value).find(selectedItemCss); // Check if this is model

    if (_enum.isModel(rowTitle)) {
      if (selectedItem.length === 0) {
        throw new Error("Model is missing");
      }

      model = removeWhitespaces(selectedItem.text());
      return;
    } // Check if this is color


    if (_enum.isColor(rowTitle)) {
      if (selectedItem.length === 0) {
        throw new Error("Color is missing");
      }

      color = removeWhitespaces(selectedItem.text());
      return;
    } // Check if this is size


    if (_enum.isSize(rowTitle)) {
      if (selectedItem.length === 0) {
        throw new Error("Sizing is missing");
      }

      size = removeWhitespaces(selectedItem.text());
      return;
    }

    others.push(`${capitalize(rowTitle)}: ${removeWhitespaces(selectedItem.text())}`);
  });
  return {
    model,
    color,
    size,
    others
  };
};
;// CONCATENATED MODULE: ./src/stores/TaoBao.ts







class TaoBao {
  attach($document, localWindow) {
    const button = this._buildButton($document, localWindow);

    if (button === null) {
      return;
    }

    $document.find("#detail .tb-property-x .tb-key .tb-action").after(button);
  }

  supports(hostname) {
    return hostname.includes("taobao.com");
  }

  _buildButton($document, window) {
    // Force someone to select an agent
    if (GM_config.get("agentSelection") === "empty") {
      GM_config.open();
      Snackbar("Please select what agent you use");
      return null;
    } // Get the agent related to our config


    const agent = getAgent(GM_config.get("agentSelection"));
    const $button = $(`<button id="agent-button">Add to ${agent.name}</button>`).css("width", "180px").css("color", "#FFF").css("border-color", "#F40").css("background", "#F40").css("cursor", "pointer").css("text-align", "center").css("font-family", '"Hiragino Sans GB","microsoft yahei",sans-serif').css("font-size", "16px").css("line-height", "38px").css("border-width", "1px").css("border-style", "solid").css("border-radius", "2px");
    $button.on("click", async () => {
      // Disable button to prevent double clicks and show clear message
      $button.attr("disabled", "disabled").text("Processing..."); // Try to build and send the order

      try {
        await agent.send(this._buildOrder($document, window));
      } catch (err) {
        $button.attr("disabled", null).text(`Add to ${agent.name}`);
        return Snackbar(err);
      }

      $button.attr("disabled", null).text(`Add to ${agent.name}`); // Success, tell the user

      return Snackbar("Item has been added, be sure to double check it");
    });
    return $('<div class="tb-btn-add-agent" style="margin-top: 20px"></div>').append($button);
  }

  _buildShop(window) {
    const id = window.g_config.idata.shop.id;
    const name = window.g_config.shopName;
    const url = new URL(window.g_config.idata.shop.url, window.location).toString();
    return new Shop(id, name, url);
  }

  _buildItem($document, window) {
    // Build item information
    const id = window.g_config.idata.item.id;
    const name = window.g_config.idata.item.title; // Build image information

    const imageUrl = new URL(window.g_config.idata.item.pic, window.location).toString(); // Retrieve the dynamic selected item

    const {
      model,
      color,
      size,
      others
    } = retrieveDynamicInformation($document, ".tb-skin > .tb-prop", ".tb-property-type", ".tb-selected");
    return new Item(id, name, imageUrl, model, color, size, others);
  }

  _buildPrice($document) {
    const promoPrice = this._buildPromoPrice($document);

    if (promoPrice !== null) {
      return promoPrice;
    }

    return Number(removeWhitespaces($document.find("#J_StrPrice > .tb-rmb-num").text()));
  }

  _buildPromoPrice($document) {
    const promoPrice = $document.find("#J_PromoPriceNum.tb-rmb-num").text();

    if (promoPrice.length === 0) {
      return null;
    }

    const promoPrices = promoPrice.split(" ");

    if (promoPrices.length !== 0) {
      return Number(promoPrices.shift());
    }

    return Number(promoPrice);
  }

  _buildShipping($document) {
    const postageText = removeWhitespaces($document.find("#J_WlServiceInfo").first().text()); // Check for free shipping

    if (postageText.includes("快递 免运费")) {
      return 0;
    } // Try and get postage from text


    const postageMatches = postageText.match(/([\d.]+)/); // If we can't find any numbers, assume free as well, agents will fix it

    return postageMatches !== null ? Number(postageMatches[0]) : 0;
  }

  _buildOrder($document, window) {
    return new Order(this._buildShop(window), this._buildItem($document, window), this._buildPrice($document), this._buildShipping($document));
  }

}
;// CONCATENATED MODULE: ./src/stores/Tmall.ts







class Tmall {
  attach($document, localWindow) {
    const button = this._buildButton($document, localWindow);

    if (button === null) {
      return;
    }

    $document.find(".tb-btn-basket.tb-btn-sku").before(button);
  }

  supports(hostname) {
    return hostname === "detail.tmall.com";
  }

  _buildButton($document, window) {
    // Force someone to select an agent
    if (GM_config.get("agentSelection") === "empty") {
      GM_config.open();
      Snackbar("Please select what agent you use");
      return null;
    } // Get the agent related to our config


    const agent = getAgent(GM_config.get("agentSelection"));
    const $button = $(`<button id="agent-button">Add to ${agent.name}</button>`).css("width", "180px").css("color", "#FFF").css("border-color", "#F40").css("background", "#F40").css("cursor", "pointer").css("text-align", "center").css("font-family", '"Hiragino Sans GB","microsoft yahei",sans-serif').css("font-size", "16px").css("line-height", "38px").css("border-width", "1px").css("border-style", "solid").css("border-radius", "2px");
    $button.on("click", async () => {
      // Disable button to prevent double clicks and show clear message
      $button.attr("disabled", "disabled").text("Processing..."); // Try to build and send the order

      try {
        await agent.send(this._buildOrder($document, window));
      } catch (err) {
        $button.attr("disabled", null).text(`Add to ${agent.name}`);
        return Snackbar(err);
      }

      $button.attr("disabled", null).text(`Add to ${agent.name}`); // Success, tell the user

      return Snackbar("Item has been added, be sure to double check it");
    });
    return $('<div class="tb-btn-add-agent"></div>').append($button);
  }

  _buildShop(window) {
    const id = window.g_config.shopId;
    const name = window.g_config.sellerNickName;
    const url = new URL(window.g_config.shopUrl, window.location).toString();
    return new Shop(id, name, url);
  }

  _buildItem($document, window) {
    // Build item information
    const id = window.g_config.itemId;
    const name = removeWhitespaces($document.find("#J_DetailMeta > div.tm-clear > div.tb-property > div > div.tb-detail-hd > h1").text()); // Build image information

    const imageUrl = $document.find("#J_ImgBooth").first().attr("src"); // Retrieve the dynamic selected item

    const {
      model,
      color,
      size,
      others
    } = retrieveDynamicInformation($document, ".tb-skin > .tb-sku > .tb-prop", ".tb-metatit", ".tb-selected");
    return new Item(id, name, imageUrl, model, color, size, others);
  }

  _buildPrice($document) {
    let price = Number(removeWhitespaces($document.find(".tm-price").first().text()));
    $document.find(".tm-price").each((key, element) => {
      const currentPrice = Number(removeWhitespaces(element.textContent));
      if (price > currentPrice) price = currentPrice;
    });
    return price;
  }

  _buildShipping($document) {
    const postageText = removeWhitespaces($document.find("#J_PostageToggleCont > p > .tm-yen").first().text()); // Check for free shipping

    if (postageText.includes("快递 免运费")) {
      return 0;
    } // Try and get postage from text


    const postageMatches = postageText.match(/([\d.]+)/); // If we can't find any numbers, assume free as well, agents will fix it

    return postageMatches !== null ? Number(postageMatches[0]) : 0;
  }

  _buildOrder($document, window) {
    return new Order(this._buildShop(window), this._buildItem($document, window), this._buildPrice($document), this._buildShipping($document));
  }

}
;// CONCATENATED MODULE: ./src/stores/Weidian.ts








class Weidian {
  attach($document, localWindow) {
    $document.find(".footer-btn-container > span").add(".item-container > .sku-button").on("click", () => {
      // Force someone to select an agent
      if (GM_config.get("agentSelection") === "empty") {
        alert("Please select what agent you use");
        GM_config.open();
        return;
      }

      this._attachFooter($document, localWindow);

      this._attachFooterBuyNow($document, localWindow);
    }); // Setup for storefront

    $document.on("mousedown", "div.base-ct.img-wrapper", () => {
      // Force new tab for shopping cart (must be done using actual window and by overwriting window.API.Bus)
      localWindow.API.Bus.on("onActiveSku", t => localWindow.open(`https://weidian.com/item.html?itemID=${t}&frb=open`).focus());
    }); // Check if we are a focused screen (because of storefront handler) and open the cart right away

    if (new URLSearchParams(localWindow.location.search).get("frb") === "open") {
      $document.find("[data-spider-action-name='add_Cart']").trigger("click");
    }
  }

  supports(hostname) {
    return hostname.includes("weidian.com");
  }

  _attachFooter($document, window) {
    // Attach button the footer (buy with options or cart)
    elementReady(".sku-footer").then(element => {
      // Only add the button if it doesn't exist
      if ($("#agent-button").length !== 0) {
        return;
      } // Add the agent button, if we have one


      const button = this._attachButton($document, window);

      if (button === null) {
        return;
      }

      $(element).before(button);
    });
  }

  _attachFooterBuyNow($document, window) {
    // Attach button the footer (buy now)
    elementReady(".login_plugin_wrapper").then(element => {
      // Only add the button if it doesn't exist
      if ($("#agent-button").length !== 0) {
        return;
      } // Add the agent button, if we have one


      const button = this._attachButton($document, window);

      if (button === null) {
        return;
      }

      $(element).parent().after(button);
    });
  }

  _attachButton($document, window) {
    // Force someone to select an agent
    if (GM_config.get("agentSelection") === "empty") {
      GM_config.open();
      Snackbar("Please select what agent you use");
      return null;
    } // Get the agent related to our config


    const agent = getAgent(GM_config.get("agentSelection"));
    const $button = $(`<button id="agent-button">Add to ${agent.name}</button>`).css("background", "#f29800").css("color", "#FFFFFF").css("font-size", "15px").css("text-align", "center").css("padding", "15px 0").css("width", "100%").css("height", "100%").css("cursor", "pointer");
    $button.on("click", async () => {
      // Disable button to prevent double clicks and show clear message
      $button.attr("disabled", "disabled").text("Processing..."); // Try to build and send the order

      try {
        await agent.send(this._buildOrder($document, window));
      } catch (err) {
        $button.attr("disabled", null).text(`Add to ${agent.name}`);
        Snackbar(err);
        return;
      }

      $button.attr("disabled", null).text(`Add to ${agent.name}`); // Success, tell the user

      Snackbar("Item has been added, be sure to double check it");
      return;
    });
    return $button;
  }

  _buildShop($document, window) {
    // Setup default values for variables
    let id = null;
    let name = null;
    let url = null; // Try and fill the variables

    let $shop = $document.find(".shop-toggle-header-name").first();

    if ($shop.length !== 0) {
      name = removeWhitespaces($shop.text());
    }

    $shop = $document.find(".item-header-logo").first();

    if ($shop.length !== 0) {
      url = new URL($shop.attr("href"), window.location.href).toString();
      id = url.replace(/^\D+/g, "");
      name = removeWhitespaces($shop.text());
    }

    $shop = $document.find(".shop-name-str").first();

    if ($shop.length !== 0) {
      url = new URL($shop.parents("a").first().attr("href"), window.location.href).toString();
      id = url.replace(/^\D+/g, "");
      name = removeWhitespaces($shop.text());
    } // If no shop name is defined, just set shop ID


    if ((name === null || name.length === 0) && id !== null) {
      name = id;
    }

    return new Shop(id, name, url);
  }

  _buildItem($document, window) {
    // Build item information
    const id = window.location.href.match(/[?&]itemId=(\d+)/i)[1];
    const name = removeWhitespaces($document.find(".item-title").first().text()); // Build image information

    let $itemImage = $document.find("img#skuPic");
    if ($itemImage.length === 0) $itemImage = $document.find("img.item-img");
    const imageUrl = $itemImage.first().attr("src");
    const {
      model,
      color,
      size,
      others
    } = retrieveDynamicInformation($document, ".sku-content .sku-row", ".row-title", ".sku-item.selected");
    return new Item(id, name, imageUrl, model, color, size, others);
  }

  _buildPrice($document) {
    let $currentPrice = $document.find(".sku-cur-price");
    if ($currentPrice.length === 0) $currentPrice = $document.find(".cur-price");
    return Number(removeWhitespaces($currentPrice.first().text()).replace(/(\D+)/, ""));
  }

  _buildShipping($document) {
    const $postageBlock = $document.find(".postage-block").first();
    const postageMatches = removeWhitespaces($postageBlock.text()).match(/([\d.]+)/); // If we can't find any numbers, assume free, agents will fix it

    return postageMatches !== null ? Number(postageMatches[0]) : 0;
  }

  _buildOrder($document, window) {
    return new Order(this._buildShop($document, window), this._buildItem($document, window), this._buildPrice($document), this._buildShipping($document));
  }

}
;// CONCATENATED MODULE: ./src/stores/Yupoo.ts






class Yupoo {
  attach($document, localWindow) {
    // Setup for item page
    const button = this._buildButton($document, localWindow);

    if (button === null) {
      return;
    }

    $document.find(".showalbumheader__tabgroup").prepend(button);
  }

  supports(hostname) {
    return hostname.includes("yupoo.com");
  }

  _buildButton($document, window) {
    // Force someone to select an agent
    if (GM_config.get("agentSelection") === "empty") {
      GM_config.open();
      Snackbar("Please select what agent you use");
      return null;
    } // Get the agent related to our config


    const agent = getAgent(GM_config.get("agentSelection"));
    const $button = $(`<button id="agent-button" class="button showalbumheader__copy">Add to ${agent.name}</button>`);
    $button.on("click", async () => {
      // Disable button to prevent double clicks and show clear message
      $button.attr("disabled", "disabled").text("Processing..."); // Try to build and send the order

      try {
        await agent.send(this._buildOrder($document, window));
      } catch (err) {
        $button.attr("disabled", null).text(`Add to ${agent.name}`);
        return Snackbar(err);
      }

      $button.attr("disabled", null).text(`Add to ${agent.name}`); // Success, tell the user

      return Snackbar("Item has been added, be sure to double check it");
    });
    return $button;
  }

  _buildShop($document, window) {
    // Setup default values for variables
    const author = window.location.hostname.replace(".x.yupoo.com", "");
    const name = $document.find(".showheader__headerTop > h1").first().text();
    const url = `https://${author}.x.yupoo.com/albums`;
    return new Shop(author, name, url);
  }

  _buildItem($document, window) {
    // Build item information
    const id = window.location.href.match(/albums\/(\d+)/i)[1];
    const name = removeWhitespaces($document.find("h2 > .showalbumheader__gallerytitle").first().text()); // Build image information

    const $itemImage = $document.find(".showalbumheader__gallerycover > img").first();
    const imageUrl = new URL($itemImage.attr("src").replace("photo.yupoo.com/", "cdn.fashionreps.page/yupoo/"), window.location.href).toString(); // Ask for dynamic information

    let color = prompt("What color (leave blank if not needed)?");

    if (color !== null && removeWhitespaces(color).length === 0) {
      color = null;
    }

    let size = prompt("What size (leave blank if not needed)?");

    if (size !== null && removeWhitespaces(size).length === 0) {
      size = null;
    }

    return new Item(id, name, imageUrl, null, color, size, []);
  }

  _buildPrice($document) {
    const priceHolder = $document.find("h2 > .showalbumheader__gallerytitle");
    let currentPrice = "0"; // Try and find the price of the item

    const priceMatcher = priceHolder.text().match(/¥?(\d+)¥?/i);

    if (priceHolder && priceMatcher && priceMatcher.length !== 0) {
      currentPrice = priceMatcher[1];
    }

    return Number(removeWhitespaces(currentPrice).replace(/(\D+)/, ""));
  }

  _buildOrder($document, window) {
    return new Order(this._buildShop($document, window), this._buildItem($document, window), this._buildPrice($document), 10);
  }

}
;// CONCATENATED MODULE: ./src/stores/Stores.ts





function getStore(hostname) {
  const agents = [new Store1688(), new TaoBao(), new Tmall(), new Yupoo(), new Weidian()];
  let agent = null;
  Object.values(agents).forEach(value => {
    if (value.supports(hostname)) {
      agent = value;
    }
  });
  return agent;
}
;// CONCATENATED MODULE: ./src/index.ts


 // Inject config styling

GM_addStyle("div.config-dialog.config-dialog-ani { z-index: 2147483647; }"); // Setup proper settings menu

GM_config.init("Settings", {
  agentSection: {
    label: "Select your agent",
    type: "section"
  },
  agentSelection: {
    label: "Your agent",
    type: "select",
    default: "empty",
    options: {
      empty: "Select your agent...",
      basetao: "BaseTao",
      cssbuy: "CSSBuy",
      pandabuy: "PandaBuy",
      superbuy: "SuperBuy",
      wegobuy: "WeGoBuy"
    }
  }
}); // 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.
  external_Logger_default().useDefaults(); // Log the start of the script.

  external_Logger_default().info(`Starting extension '${GM_info.script.name}', version ${GM_info.script.version}`); // Check if we are on a store

  const store = getStore(window.location.hostname);

  if (store !== null) {
    // If we have a store handler, attach and start
    store.attach($(window.document), window.unsafeWindow);
    return;
  } // Check if we are on a reshipping agent


  const login = getLogin(window.location.hostname);

  if (login !== null) {
    // If we are on one, execute whatever needed for that
    login.process();
    return;
  }

  external_Logger_default().error("Unsupported website");
})();
})();

/******/ })()
;