// ==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/js-logger@1.6.1/src/logger.min.js
// @require https://unpkg.com/jquery@3.6.0/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
// @downloadURL none
// ==/UserScript==
/**
* Creates a SKU toast, which is shown because of Weidians CSS
*
* @param toast {string}
*/
const Snackbar = function (toast) {
const $toast = $(`
${toast}
`).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 = $('').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);
});
}());