// ==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');
}());