// ==UserScript== // @name FR:ES - BaseTao // @namespace https://www.reddit.com/user/RobotOilInc // @author RobotOilInc // @version 1.0.0 // @description Upload Taobao and Yupoo QCs from BaseTao to Imgur // @match https://www.basetao.net/index/myhome/myorder/* // @match https://basetao.net/index/myhome/myorder/* // @match https://www.basetao.com/index/myhome/myorder/* // @match https://basetao.com/index/myhome/myorder/* // @include https://www.basetao.net/index/orderphoto/itemimg/* // @include https://basetao.net/index/orderphoto/itemimg/* // @include https://www.basetao.com/index/orderphoto/itemimg/* // @include https://basetao.com/index/orderphoto/itemimg/* // @connect self // @connect imgur.com // @connect fashionreps.tools // @connect 127.0.0.1 // @connect localhost // @require https://code.jquery.com/jquery-3.4.1.min.js // @require https://greasyfork.org/scripts/401399-gm-xhr/code/GM%20XHR.js // @require https://greasyfork.org/scripts/426288-webptojpg/code/WebpToJpg.js // @require https://cdnjs.cloudflare.com/ajax/libs/spark-md5/3.0.0/spark-md5.min.js // @grant GM_openInTab // @grant GM_notification // @grant GM_xmlhttpRequest // @run-at document-end // @icon https://i.imgur.com/1aQAxbC.png // @downloadURL none // ==/UserScript== 'use strict'; /* jshint esversion: 8 */ /* globals $:false, SparkMD5:false, GM_XHR: false, WebpToJpg: false */ const _version = "1.0.0"; const _url = "https://localhost:8000/"; const ClientIds = ["97a5f748b20b0ad", "1fb6eded0178bb6", "4d01890bba4949c", "fe9f4d770f42e53", "0999af252aaaba1", "6870f32f716ff3b", "bf02cd90c8a4f1a", "5ed540f56122e1c"]; const ActiveClientId = ClientIds[Math.floor(Math.random() * ClientIds.length)]; const username = $("#dropdownMenu1").text(); const userHash = SparkMD5.hash(username); const toDataURL = url => fetch(url) .then(response => response.blob()) .then(blob => new Promise((resolve, reject) => { const reader = new FileReader(); reader.onloadend = () => resolve(reader.result); reader.onerror = reject; reader.readAsDataURL(blob) })); // Setup GM_XHR $.ajaxSetup({ xhr: function() {return new GM_XHR; } }); const CreateOptions = async ($this) => { const options = await CreateBasicOptions($this); let sizingInfo = $.trim("Color: " + options.color + ((options.size != 'NO') ? " - Size: " + options.size : '')); let originalSizing = $.trim("Color: " + options.color + ((options.size != 'NO') ? " - Size: " + options.size : '')); let existingAlbum = await ExistingAlbum(options.w2c, sizingInfo, originalSizing); options.sizing = sizingInfo; options.originalSizing = originalSizing; options.existingAlbum = existingAlbum; return options; } const CreateBasicOptions = async ($this) => { const $baseElement = $this.parents("tr").find("td[colspan='2']").first(); const w2cLink = $baseElement.find(".goodsname_color").first().attr('href').replace("http://", "https://"); const title = $baseElement.find(".goodsname_color").first().text(); const color = $baseElement.find(".size_color_color:nth-child(1) > u").text(); const size = $baseElement.find(".size_color_color:nth-child(2) > u").text(); const id = parseInt($this.parents("tr").prev().find("td.tdpd > span:nth-child(2)").text()); return {id: id, title: title, object: $this, w2c: w2cLink, color: color, size: size}; } const ExistingAlbum = async (w2c, originalSizing) => { let existingAlbum; try { existingAlbum = await $.get(_url + "qcdb/hasUploadedBefore.php?userhash=" + userHash + "&w2c=" + encodeURI(w2c) + "&sizing=" + encodeURI(originalSizing)); // Connection failed, means an error on FR:ES. Return -1 to indicate issue. if (existingAlbum.indexOf("Connection failed") !== -1) { return -1; } if (existingAlbum != 0) { return existingAlbum; } return 0; } catch (error) { console.error("An error happened: " + error.statusText, error); } }; const HasExistingQc = async (w2c) => { try { const data = await $.get(_url + "qcdb/qcExists.php", {'w2c': w2c}) // No return equals no QC if (typeof data === 'undefined' || data === '') { return '0'; } // Connection failed, means an error on FR:ES. Return -1 to indicate issue. if (data.indexOf("Connection failed") !== -1) { return '-1'; } // Try to parse JSON, if it fails, issue with FR:ES. Return -1 to indicate issue. try { return JSON.parse(data).exists } catch (error) { console.error("An error happened when parsing JSON", error); return '-1'; } } catch (error) { // No actual error, means no QC if (error.responseText === '') { return '0'; } // Log error and return -1 to indicate issue. console.error("An error happened: " + error.statusText, error); return '-1'; } }; const CreateAlbum = async (options) => { let result; try { result = await $.ajax({ url: 'https://api.imgur.com/3/album', headers: {'Authorization': 'Client-ID ' + ActiveClientId}, type: 'POST', data: { 'title': options.title, 'privacy': 'hidden', 'description': 'Auto uploaded using BaseTao to Imgur (v' + _version + '): https://greasyfork.org/scripts/387421-fr-es-basetao-extension' } }); return result; } catch (error) { // Log the error somewhere console.error("Could not make an ablbum: " + error.statusText, error); // If we uploaded too fast, tell the user if (error.responseJSON.data.error.code === 429) { GM_notification("Imgur is telling us to slow down: " + error.responseJSON.data.error.message, "FR:ES - BaseTao"); return; } // Tell the user that "something" is wrong GM_notification("Could not make an ablbum, please try again later...", "FR:ES - BaseTao"); } }; const AddImageToAlbum = async (base64Image, deleteHash, w2c) => { try { await $.ajax({ url: 'https://api.imgur.com/3/image', headers: {'Authorization': 'Client-ID ' + ActiveClientId}, type: 'POST', data: {'image': base64Image, 'type': 'base64', 'album': deleteHash, 'description': "W2C: " + w2c} }); return true; } catch (error) { // If we uploaded too many files, tell the user if (error.responseJSON.data.error.code === 429) { GM_notification("Imgur is telling us to slow down: " + error.responseJSON.data.error.message, "FR:ES - BaseTao"); } // Log errors somewhere console.error("An error happened when uploading the image: " + error.responseJSON.data.error.message, error); return false; } }; const UploadToImgur = async (options) => { const $processing = $('