Amazon a Pesos Argentos

Mostrar precios en pesos argentinos y comparador de precios con MercadoLibre y otras tiendas de amazon

  1. // ==UserScript==
  2. // @name Amazon a Pesos Argentos
  3. // @version 1.3.0
  4. // @author DSR!
  5. // @namespace dsr-amazon-pesos-argentos
  6. // @description Mostrar precios en pesos argentinos y comparador de precios con MercadoLibre y otras tiendas de amazon
  7. // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js#sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=
  8. // @require https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js#sha256-iaqfO5ue0VbSGcEiQn+OeXxnxAMK2+QgHXIDA5bWtGI=
  9. // @include *amazon.com/*
  10. // @include *amazon.co.uk/*
  11. // @include *amazon.ca/*
  12. // @include *amazon.es/*
  13. // @include *amazon.de/*
  14. // @include *amazon.fr/*
  15. // @include *amazon.it/*
  16. // @connect amazon.com
  17. // @connect amazon.co.uk
  18. // @connect amazon.ca
  19. // @connect amazon.es
  20. // @connect amazon.de
  21. // @connect amazon.fr
  22. // @connect amazon.it
  23. // @connect geeklab.com.ar
  24. // @connect europa.eu
  25. // @connect mercadolibre.com
  26. // @run-at document-start
  27. // @noframes
  28. // ==/UserScript==
  29.  
  30. var BANNER = "[ARG-LOG]";
  31. var LAST_RUN = "last_run_";
  32. var CURRENCY_RATE = "currency_rate_";
  33. var CURRENCY_RATE_EUR = "currency_rate_eur_";
  34. var decimalPlaces = 2;
  35. var prefixCurrencySymbol = true;
  36. var taxPorcentage = 0; //3.6; //no se de donde es esto
  37. var currencyToSymbol = 'ARS $';
  38.  
  39. // estos shims son de https://gist.githubusercontent.com/arantius/3123124/raw/grant-none-shim.js
  40. function GM_addStyle(aCss) {
  41. 'use strict';
  42. let head = document.getElementsByTagName('head')[0];
  43. if (head) {
  44. let style = document.createElement('style');
  45. style.setAttribute('type', 'text/css');
  46. style.textContent = aCss;
  47. head.appendChild(style);
  48. return style;
  49. }
  50. return null;
  51. }
  52.  
  53. function GM_getValue(aKey, aDefault) {
  54. 'use strict';
  55. let val = localStorage.getItem('dsr-amazon-pesos-argentos_config' + aKey)
  56. if (null === val && 'undefined' != typeof aDefault) return aDefault;
  57. return val;
  58. }
  59.  
  60. function GM_setValue(aKey, aVal) {
  61. 'use strict';
  62. localStorage.setItem('dsr-amazon-pesos-argentos_config' + aKey, aVal);
  63. }
  64.  
  65.  
  66.  
  67. // bloque principal
  68. (function() {
  69. if (typeof jQuery === 'undefined') {
  70. console.log(BANNER, 'jQuery === undefined');
  71. return;
  72. }
  73.  
  74. /*
  75. if (jQuery('#dsr-amazon-pesos-argentos-start-flag')) {
  76. console.log(BANNER, 'Already start', jQuery('#dsr-amazon-pesos-argentos-start-flag'));
  77. return;
  78. }
  79. */
  80.  
  81. console.log(BANNER, 'principal');
  82.  
  83. //jQuery('body').append('<input id="dsr-amazon-pesos-argentos-start-flag" type="hidden">');
  84. GM_addStyle('.price-ars{color:green;display:inline-block;margin:0 8px;background:linear-gradient(to bottom,#add8e6,#fff,#add8e6);border-radius:8px;padding:0 6px}'+
  85. '#sc-buy-box .price-ars{font-size:12px;display:block;padding:0;margin:0;background:0 0}div#sc-buy-box{margin-bottom:-14px}#orderDetails{width: 1200px;}#od-subtotals{width: 350px!important;margin-right:-350px!important;}');
  86. GM_addStyle('#snoop-icon{margin-left:4px;width:30px;height:20px}#snoop-placeholder{width:32px}div.snoop-loader{width:13px;height:13px}div.snoop-tooltip,div.snoop-tooltip-ml{display:none;font-size:13px;border-image:none;letter-spacing:0}'+
  87. 'div.snoop-tooltip div.entry,div.snoop-tooltip-ml div.entry{padding-top:5px}span.snoop-price{color:#900;font-size:1em;font-weight:700}span.snoop-warning{color:#C60!important}.snoop-not-found{text-decoration:line-through}'+
  88. 'span.snoop-on{color:#000;font-weight:400}span.back-link{line-height:0;margin-left:1px;top:-10px;position:relative}'+
  89. 'span.back-link>img{top:1;position:relative}span.back-link>a{font-size:1em;text-decoration:none!important}#snoop-icon-ml{margin-left:10px}');
  90. GM_addStyle('#pesos-carrito-html{width:400px;min-height:34px;margin:0 auto;left:calc(80% - 200px);top:150px;background:white;position: fixed;z-index:1000000;padding:20px;border:1px solid black;border-radius:8px;box-shadow: 0px 0px 40px black;}#pesos-carrito-html .price-ars{text-align: right; margin: 0;}');
  91.  
  92. var domainData = {
  93. com: {
  94. withVAT: false,
  95. vat: 0,
  96. symbol: "$",
  97. priceRegex: /\$\s*([\d,.]+\d)/,
  98. currencyFrom: "USD"
  99. },
  100. ca: {
  101. withVAT: false,
  102. vat: 0,
  103. symbol: "CDN$ ",
  104. priceRegex: /CDN\$\s*([\d,.]+\d)/,
  105. currencyFrom: "CAD"
  106. },
  107. uk: {
  108. withVAT: true,
  109. vat: 1.20,
  110. symbol: "£",
  111. priceRegex: /£\s*([\d,.]+\d)/,
  112. currencyFrom: "GBP"
  113. },
  114. es: {
  115. withVAT: true,
  116. vat: 1.21,
  117. symbol: "EUR ",
  118. priceRegex: /EUR\s*([\s\d,.]+\d)/,
  119. currencyFrom: "EUR"
  120. },
  121. de: {
  122. withVAT: true,
  123. vat: 1.19,
  124. symbol: "EUR ",
  125. priceRegex: /EUR\s*([\s\d,.]+\d)/,
  126. currencyFrom: "EUR"
  127. },
  128. fr: {
  129. withVAT: true,
  130. vat: 1.20,
  131. symbol: "EUR ",
  132. priceRegex: /EUR\s*([\s\d,.]+\d)/,
  133. currencyFrom: "EUR"
  134. },
  135. it: {
  136. withVAT: true,
  137. vat: 1.22,
  138. symbol: "EUR ",
  139. priceRegex: /EUR\s*([\s\d,.]+\d)/,
  140. currencyFrom: "EUR"
  141. },
  142. parseLinks: GM_getValue('parseLinks', true)
  143. };
  144.  
  145. var domain = document.domain.substr(document.domain.lastIndexOf('.') + 1);
  146. var rounding = Math.pow(10, decimalPlaces);
  147. var rate = GM_getValue(CURRENCY_RATE + domainData[domain].currencyFrom);
  148. var lastRun = GM_getValue(LAST_RUN, false);
  149. var showVAT = GM_getValue('show_vat', true);
  150.  
  151.  
  152. function regularPriceParser(price, currency) {
  153. price = price.replace(/\s/g, '');
  154. var regex = /^[\d.]+,[\d]{2}$/;
  155. var needProperPrice = regex.exec(price);
  156. if (needProperPrice) {
  157. price = price.replace(/\./g, '').replace(/,/, '.');
  158. } else {
  159. price = price.replace(/\,/g, '');
  160. }
  161. return parseFloat(price);
  162. }
  163.  
  164. function fetchCurrencyData(callback) {
  165. // tambien tengo
  166. // https://api.enhancedsteam.com/currencydata/?base=eur
  167. jQuery.getJSON(
  168. "http://ws.geeklab.com.ar/dolar/get-dolar-json.php"
  169. ).done(
  170. function(data) {
  171. // la api devuelve el precio libre y el blue
  172. console.log(BANNER, data);
  173. GM_setValue(CURRENCY_RATE + 'USD', data.libre);
  174.  
  175. callback();
  176. }
  177. );
  178. }
  179.  
  180. function appendConversionNoVAT(price, matched, offset, string) {
  181. return appendConversion(price, matched, offset, string, true);
  182. }
  183.  
  184. function appendConversion(price, matched, offset, string, novat, customvat) {
  185. var originalPrice = regularPriceParser(matched, domainData[domain].currencyFrom);
  186. if (isNaN(originalPrice)) {
  187. return price;
  188. }
  189. if (novat !== true) {
  190. if (customvat > 1) {
  191. originalPrice /= customvat;
  192. } else if (customvat === undefined && domainData[domain].withVAT) {
  193. originalPrice /= domainData[domain].vat;
  194. }
  195. }
  196.  
  197. if (isNaN(rate)) {
  198. rate = GM_getValue(CURRENCY_RATE + domainData[domain].currencyFrom);
  199. console('fix?', rate);
  200. }
  201.  
  202. var converted = formatCurrency(originalPrice * (rate * (taxPorcentage / 100 + 1)), rounding, currencyToSymbol, prefixCurrencySymbol);
  203. if (showVAT && novat !== true && (customvat > 1 || (customvat === undefined && domainData[domain].withVAT))) {
  204. originalPrice = formatCurrency(originalPrice, rounding, domainData[domain].symbol, prefixCurrencySymbol);
  205. return '<span title="Original: ' + price + (customvat > 1 ? ' - VAT: ' + Math.round((customvat - 1) * 100) + '%' : '') + '">' + originalPrice + '<div class="price-ars">' + converted + '</div></span>';
  206. } else {
  207. return price + '<div class="price-ars">' + converted + '</div>';
  208. }
  209. }
  210.  
  211. function formatCurrency(num, rounding, symbol, prefix) {
  212. sign = (num == (num = Math.abs(num)));
  213. num = Math.floor(num * rounding + 0.50000000001);
  214. cents = num % rounding;
  215. num = Math.floor(num / rounding).toString();
  216. if (cents < 10) {
  217. cents = "0" + cents;
  218. }
  219. for (var i = 0; i < Math.floor((num.length - (1 + i)) / 3); i++) {
  220. num = num.substring(0, num.length - (4 * i + 3)) + ',' + num.substring(num.length - (4 * i + 3));
  221. }
  222. if (prefix) {
  223. return (symbol + ((sign) ? '' : '-') + num + '.' + cents);
  224. } else {
  225. return (((sign) ? '' : '-') + num + '.' + cents + symbol);
  226. }
  227. }
  228. convertCurrency = function(carrito, vat) {
  229. switch (carrito) {
  230. case 1:
  231. if (jQuery('.a-size-base.a-text-bold:contains(Order summary)').length === 0 &&
  232. jQuery('.a-size-base.a-text-bold:contains(Récapitulatif de commande)').length === 0 &&
  233. jQuery('.a-size-base.a-text-bold:contains(Riepilogo ordine)').length === 0 &&
  234. jQuery('.a-size-base.a-text-bold:contains(Resumen del pedido)').length === 0 &&
  235. jQuery('.a-size-base.a-text-bold:contains(Zusammenfassung der Bestellung)').length === 0 &&
  236. jQuery('.ap_popover.ap_popover_sprited.snoop-tooltip').length === 0) {
  237. return false;
  238. } else {
  239. if (jQuery('#sc-buy-box.price-ars-cart').length === 0) {
  240. jQuery('#sc-buy-box').addClass('price-ars-cart');
  241. } else {
  242. return false;
  243. }
  244. }
  245. break;
  246. case 2:
  247. if (jQuery('.entry.snoop-price:not(.snoop-warning):not(.price-ars-cart)').length === 0) {
  248. return false;
  249. }
  250. break;
  251. default:
  252. break;
  253. }
  254. console.log(BANNER, 'Cambiando precios', carrito);
  255. jQuery('.a-column.a-span3.a-text-right.a-span-last.sc-value').removeClass('a-span3').addClass('a-span4');
  256. jQuery('.a-column.a-span9.sc-text').removeClass('a-span9').addClass('a-span8');
  257. jQuery('a.a-popover-trigger.a-declarative:contains(Estimated)').html('Shipping & handling <i class="a-icon a-icon-popover"></i>');
  258. if (carrito == 2) {
  259. jQuery('.entry.snoop-price:not(.snoop-warning)').each(function() {
  260. var text = jQuery(this).text();
  261. if (jQuery(this).children().length === 0 && text.indexOf(domainData[domain].symbol) != -1 && text.indexOf('ARS') == -1) {
  262. jQuery(this).addClass('price-ars-cart').html(text.replace(domainData[domain].priceRegex, appendConversion));
  263. }
  264. });
  265. } else {
  266. jQuery('span:not(:has(*))').each(function(){
  267. var parent = false;
  268. var text = jQuery(this).text();
  269. if( jQuery(this).hasClass('a-price-symbol') ){
  270. parent = true;
  271. text = jQuery(this).parent().text();
  272. }
  273. if( jQuery(this).children().length === 0 && domainData[domain].priceRegex.test(text) && text.indexOf('ARS') == -1){
  274. if( jQuery(this).parents('#sc-buy-box').length == 1 ||
  275. jQuery(this).parents('#pesos-carrito-html').length == 1 ||
  276. window.location.href.indexOf("/gp/css/summary/") > -1 ||
  277. window.location.href.indexOf("/order-details") > -1 ||
  278. window.location.href.indexOf("/order-history") > -1 ||
  279. window.location.href.indexOf("/shipoptionselect/") > -1
  280. ){
  281. if(parent){
  282. jQuery(this).closest('.a-price').html( text.replace(domainData[domain].priceRegex, appendConversionNoVAT) );
  283. }else{
  284. jQuery(this).html( text.replace(domainData[domain].priceRegex, appendConversionNoVAT) );
  285. }
  286. }else{
  287. var customVAT = function(price, matched, offset, string){
  288. return appendConversion(price, matched, offset, string, false, vat);
  289. };
  290. if(parent){
  291. jQuery(this).closest('.a-price').html( text.replace(domainData[domain].priceRegex, customVAT) );
  292. }else{
  293. jQuery(this).html( text.replace(domainData[domain].priceRegex, customVAT) );
  294. }
  295. }
  296. }
  297. });
  298. }
  299. };
  300.  
  301. function parseLinks() {
  302. jQuery('head').append('<meta name="referrer" content="no-referrer">');
  303. jQuery('a[href*="/dp/"]:not([href*="?tag="])').each(function(i, item) {
  304. jQuery(item).attr('href', jQuery(item).attr('href').replace('?', '?tag=' + domainData[domain].tag + '&'));
  305. });
  306. }
  307.  
  308. var running_convert_1 = false;
  309. var running_convert_2 = false;
  310. jQuery(document).ready(function() {
  311. console.log(BANNER, 'onReady');
  312. // como no uso lo de los referidos esto no va
  313. //jQuery('#nav-tools').prepend('<a href="javascript:void(0)" id="pesos-config" class="nav-a nav-a-2 nav-truncate"><span class="nav-line-1">Configurar Script</span><span class="nav-line-2"><img src="https://i.imgur.com/qa5ZXdT.png" width="95"></span></a>');
  314. //if (domainData.parseLinks) {
  315. // parseLinks();
  316. //}
  317.  
  318. var ageInHours = lastRun ? (new Date() - new Date(lastRun)) / 1000 / 60 / 60 : false;
  319. if (isNaN(rate) || ageInHours === false || ageInHours > 3) {
  320. console.log(BANNER, 'Refreshing conversion rates...', ageInHours);
  321. fetchCurrencyData(function () {
  322. refreshRates(function () {
  323. lastRun = new Date().toISOString();
  324. GM_setValue(LAST_RUN, lastRun);
  325. convertCurrency();
  326. });
  327. });
  328. } else {
  329. console.log(BANNER, 'Currency rate from cache: ', rate, ' LastRun:', lastRun);
  330. convertCurrency();
  331. }
  332.  
  333. // esto vino del 5.1
  334. jQuery('#pesos-carrito').click(function(){
  335. jQuery('body').append('<div id="pesos-carrito-html"><img src="https://i.imgur.com/Dp92MjH.gif" /> Cargando...</div>');
  336. P.when("LUXController").execute(function(LUXController){
  337. var addressId = LUXController.getLocationData().obfuscatedId;
  338. if(addressId !== undefined){
  339. //GM_setClipboard(addressId+(16*8),"text");
  340. console.log(BANNER, addressId);
  341. $.get("/gp/cart/view.html/ref=nav_cart", function(){
  342. $.getJSON("/gp/cart/ajax-load-flc.html/ref=flc-for-enable-flc",{addressId: addressId, flcExpanded: 1}, function(result){
  343. var cartTotal = jQuery(result.features["buy-box"].featurehtml).find('#a-popover-vat_breakdown,.sc-subtotal-detail');
  344. jQuery('#pesos-carrito-html').html(cartTotal.html());
  345. jQuery('#pesos-carrito-html span').removeClass("a-nowrap");
  346. jQuery('#pesos-carrito-html span.sc-importfee').addClass("a-spacing-small");
  347. convertCurrency();
  348. });
  349. });
  350. }
  351. });
  352. });
  353.  
  354. jQuery('.a-fixed-right-grid-col.a-col-right').bind("DOMSubtreeModified", function(e) {
  355. if (running_convert_1 === false) {
  356. console.log(BANNER, 'Auto 1');
  357. running_convert_1 = true;
  358. setTimeout(function() {
  359. convertCurrency(1);
  360. running_convert_1 = false;
  361. }, 1000);
  362. }
  363. });
  364.  
  365. // este es el contenedor donde se ve el precio del producto
  366. jQuery('#priceblock_ourprice').bind("DOMSubtreeModified", function(e) {
  367. if (running_convert_2 === false) {
  368. console.log(BANNER, 'Auto 2');
  369. running_convert_2 = true;
  370. setTimeout(function() {
  371. convertCurrency(2);
  372. running_convert_2 = false;
  373. }, 1000);
  374. }
  375. });
  376.  
  377. var asin = jQuery('#ASIN').val();
  378. if (asin === undefined) {
  379. return;
  380. }
  381.  
  382. snoop.initialize(asin, domainData, domain);
  383. });
  384. })();
  385.  
  386.  
  387.  
  388. // helpers
  389. var settings;
  390.  
  391. function refreshRates(callback) {
  392. jQuery.get(
  393. 'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'
  394. ).done(function(data) {
  395. var $document = jQuery(data);
  396.  
  397. // cotizaciones
  398. usdToEur = parseFloat($document.find('Cube[currency="USD"]').attr('rate'));
  399. gbpToEur = parseFloat($document.find('Cube[currency="GBP"]').attr('rate'));
  400. GM_setValue(CURRENCY_RATE_EUR + 'USD', usdToEur);
  401. GM_setValue(CURRENCY_RATE_EUR + 'GBP', gbpToEur);
  402. GM_setValue(CURRENCY_RATE_EUR + 'EUR', 1);
  403.  
  404. arsToUsd = GM_getValue(CURRENCY_RATE + 'USD');
  405. arsToEur = arsToUsd * usdToEur;
  406.  
  407. // pesificaciones
  408. GM_setValue(CURRENCY_RATE + 'GBP', (1 / gbpToEur) * arsToEur);
  409. GM_setValue(CURRENCY_RATE + 'EUR', arsToEur);
  410.  
  411. callback();
  412. });
  413. }
  414.  
  415. var Money = function(amount, currency, currency_symbol, extraAmount) {
  416. this.amount = amount;
  417. this.extraAmount = extraAmount;
  418. this.currency = currency;
  419. this.currency_symbol = currency_symbol;
  420. };
  421.  
  422. Money.prototype.for = function(currency, currency_symbol) {
  423. rate = GM_getValue(CURRENCY_RATE_EUR + this.currency);
  424. // fix eur to gbp
  425. if (this.currency === 'EUR' && currency === 'GBP') {
  426. rate = GM_getValue(CURRENCY_RATE_EUR + 'GBP');
  427. }
  428.  
  429. if (rate === undefined) {
  430. return this;
  431. }
  432.  
  433. // fix gbp to eur
  434. if (this.currency === 'GBP' && currency === 'EUR') {
  435. rate = 1 / rate;
  436. }
  437.  
  438. console.log(BANNER, this.currency, rate, currency);
  439.  
  440. convertedAmount = this.amount * rate;
  441. convertedExtraAmount = this.extraAmount !== undefined ? this.extraAmount * rate : undefined;
  442.  
  443. return new Money(convertedAmount, currency, currency_symbol, convertedExtraAmount);
  444. };
  445.  
  446. Money.prototype.toString = function() {
  447. if (this.extraAmount === undefined){
  448. return this.currency_symbol + (this.amount.toFixed(2));
  449. } else {
  450. return this.currency_symbol + (this.amount.toFixed(2)) + ' - ' + this.currency_symbol + (this.extraAmount.toFixed(2));
  451. }
  452. };
  453.  
  454. Number.prototype.formatMoney = function(c, d, t) {
  455. var n = this;
  456. c = isNaN(c = Math.abs(c)) ? 2 : c;
  457. d = d === undefined ? "." : d;
  458. t = t === undefined ? "," : t;
  459. var s = n < 0 ? "-" : "",
  460. i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "",
  461. j = (j = i.length) > 3 ? j % 3 : 0;
  462. return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
  463. };
  464.  
  465. var Shop = function(id, title, domain, base_url, currency, currency_symbol, vat, seller) {
  466. this.id = id;
  467. this.title = title;
  468. this.domain = domain;
  469. this.base_url = base_url;
  470. this.url = this.base_url;
  471. this.currency = currency;
  472. this.currency_symbol = currency_symbol;
  473. this.vat = vat;
  474. this.seller = seller;
  475. this.setAsin = function(asin) {
  476. this.url = this.urlFor(asin);
  477. };
  478. this.urlFor = function(asin) {
  479. return this.base_url.replace('{asin}', asin);
  480. };
  481. this.moneyFrom = function(amount) {
  482. console.log(BANNER, 'moneyfrom()', amount);
  483. var culture = this.culture;
  484. if (amount.indexOf('-') == -1) {
  485. var sanitizedAmount = amount.replace(/[^\d^,^.]/g, '');
  486. var regex = /^[\d.]+,[\d]{2}$/;
  487. var needProperPrice = regex.exec(sanitizedAmount);
  488. if (needProperPrice) {
  489. sanitizedAmount = sanitizedAmount.replace(/\./g, '').replace(/,/, '.');
  490. } else {
  491. sanitizedAmount = sanitizedAmount.replace(/\,/g, '');
  492. }
  493.  
  494. return new Money(sanitizedAmount, this.currency);
  495. }
  496.  
  497. var sanitizedAmounts = amount.split('-').map(function(a) {
  498. return a.replace(/[^\d^,^.]/g, '');
  499. });
  500. return new Money(sanitizedAmounts[0], this.currency, sanitizedAmounts[1]);
  501. };
  502. };
  503.  
  504. var Settings = function(asin, domainData, domain) {
  505. console.log(BANNER, 'Settings()', asin);
  506. this.asin = asin;
  507. this.shops = [
  508. new Shop(1, 'amazon.co.uk', 'www.amazon.co.uk', 'https://www.amazon.co.uk/dp/{asin}?smid=A3P5ROKL5A1OLE', 'GBP', '£', domainData.uk.vat, 'Dispatched from and sold by Amazon|Dispatched and sold by Amazon'),
  509. new Shop(2, 'amazon.de', 'www.amazon.de', 'https://www.amazon.de/dp/{asin}?smid=A3JWKAKR8XB7XF', 'EUR', 'EUR ', domainData.de.vat, 'Verkauf und Versand durch Amazon|Versandt und verkauft von Amazon|Dispatched from and sold by Amazon|Dispatched and sold by Amazon'),
  510. new Shop(3, 'amazon.es', 'www.amazon.es', 'https://www.amazon.es/dp/{asin}?smid=A1AT7YVPFBWXBL', 'EUR', 'EUR ', domainData.es.vat, 'Vendido y enviado por Amazon'),
  511. new Shop(4, 'amazon.fr', 'www.amazon.fr', 'https://www.amazon.fr/dp/{asin}?smid=A1X6FK5RDHNB96', 'EUR', 'EUR ', domainData.fr.vat, 'Expédié et vendu par Amazon'),
  512. new Shop(5, 'amazon.it', 'www.amazon.it', 'https://www.amazon.it/dp/{asin}?smid=A11IL2PNWYJU7H', 'EUR', 'EUR ', domainData.it.vat, 'Venduto e spedito da Amazon'),
  513. new Shop(6, 'amazon.com', 'www.amazon.com', 'https://www.amazon.com/dp/{asin}?smid=ATVPDKIKX0DER', 'USD', '$', domainData.com.vat, 'Ships from and sold by Amazon.com'),
  514. new Shop(7, 'amazon.ca', 'www.amazon.ca', 'https://www.amazon.ca/dp/{asin}?smid=ATVPDKIKX0DER', 'CAD', 'CDN$', domainData.ca.vat, 'Ships from and sold by Amazon.ca')
  515. ];
  516. this.shops.forEach(function(shop) {
  517. shop.setAsin(asin);
  518. });
  519. this.currentShop = this.shops.filter(function(shop) {
  520. return shop.domain == document.domain;
  521. })[0];
  522. this.desiredCurrency = this.currentShop.currency;
  523. if (this.currentShop.currency != this.desiredCurrency) {
  524. this.filteredShops = this.shops;
  525. } else {
  526. this.filteredShops = this.shops.filter(function(shop) {
  527. return shop.domain != document.domain;
  528. });
  529. }
  530. this.shop = function(id) {
  531. var shopById = this.shops.filter(function(shop) {
  532. return shop.id == id;
  533. });
  534. if (shopById.length == 1) return shopById[0];
  535. return null;
  536. };
  537. };
  538.  
  539. // este es el callback que revisa si encontre el producto en la pagina de otro amazon
  540. var PageScraper = {
  541. warning: {
  542. networkError: 'Error al consultar',
  543. unavailable: 'No disponible',
  544. wrongSeller: 'No vendido por Amazon',
  545. notFound: 'No encontrado',
  546. multipleOptions: 'Opciones multiples'
  547. },
  548. getPriceOn: function(shop, displayPriceCB, displayWarningCB) {
  549. console.log(BANNER, 'PageScraper.getPriceOn()')
  550. jQuery.get(
  551. shop.url
  552. ).done(function(data) {
  553. var regex = /[nb]\s*?id="priceblock_[\w]*?price".*?>(.*?)</img;
  554. var price = regex.exec(data);
  555. if (price === null || price.length != 2) {
  556. displayWarningCB(PageScraper.warning.unavailable, false);
  557. return;
  558. }
  559.  
  560. regex = new RegExp(shop.seller);
  561. var seller = regex.exec(data);
  562. if (seller === null) {
  563. displayWarningCB(PageScraper.warning.wrongSeller, false);
  564. return;
  565. }
  566.  
  567. displayPriceCB(price[1]);
  568. }).fail(function(jqXHR) {
  569. if (jqXHR.status == 404) {
  570. displayWarningCB(PageScraper.warning.notFound, true);
  571. } else {
  572. displayWarningCB(PageScraper.warnings.networkError, false);
  573. }
  574. });
  575. }
  576. };
  577.  
  578. var tooltip = {
  579. _mouseIsOnIcon: false,
  580. _mouseIsOnTooltip: false,
  581. registerShowHideHandlers: function() {
  582. this._genericRegisterShowHideHandlers(jQuery('.snoop-tooltip'), function(on) {
  583. tooltip._mouseIsOnTooltip = on;
  584. });
  585. this._genericRegisterShowHideHandlers(jQuery('#snoop-icon'), function(on) {
  586. tooltip._mouseIsOnIcon = on;
  587. });
  588. },
  589. _genericRegisterShowHideHandlers: function($selector, isOn) {
  590. $selector.mouseenter(function() {
  591. jQuery('.snoop-tooltip').show();
  592. isOn(true);
  593. }).mouseleave(function() {
  594. isOn(false);
  595. setTimeout(function() {
  596. if (!tooltip._mouseIsOnIcon && !tooltip._mouseIsOnTooltip) jQuery('.snoop-tooltip').hide();
  597. }, 100);
  598. });
  599. }
  600. };
  601.  
  602. var tooltipML = {
  603. _mouseIsOnIcon: false,
  604. _mouseIsOnTooltip: false,
  605. registerShowHideHandlers: function() {
  606. this._genericRegisterShowHideHandlers(jQuery('.snoop-tooltip-ml'), function(on) {
  607. tooltipML._mouseIsOnTooltip = on;
  608. });
  609. this._genericRegisterShowHideHandlers(jQuery('#snoop-icon-ml'), function(on) {
  610. tooltipML._mouseIsOnIcon = on;
  611. });
  612. },
  613. _genericRegisterShowHideHandlers: function($selector, isOn) {
  614. $selector.mouseenter(function() {
  615. jQuery('.snoop-tooltip-ml').show();
  616. isOn(true);
  617. }).mouseleave(function() {
  618. isOn(false);
  619. setTimeout(function() {
  620. if (!tooltipML._mouseIsOnIcon && !tooltipML._mouseIsOnTooltip) jQuery('.snoop-tooltip-ml').hide();
  621. }, 100);
  622. });
  623. }
  624. };
  625.  
  626. var tooltipSettings = {
  627. _mouseIsOnIcon: false,
  628. _mouseIsOnTooltip: false,
  629. registerShowHideHandlers: function() {
  630. this._hookSettings();
  631. this._genericRegisterShowHideHandlers(jQuery('.snoop-tooltip-settings'), function(on) {
  632. tooltipSettings._mouseIsOnTooltip = on;
  633. });
  634. this._genericRegisterShowHideHandlers(jQuery('#pesos-config'), function(on) {
  635. tooltipSettings._mouseIsOnIcon = on;
  636. });
  637. },
  638. _genericRegisterShowHideHandlers: function($selector, isOn) {
  639. $selector.mouseenter(function() {
  640. jQuery('.snoop-tooltip-settings').show();
  641. isOn(true);
  642. }).mouseleave(function() {
  643. isOn(false);
  644. setTimeout(function() {
  645. if (!tooltipSettings._mouseIsOnIcon && !tooltipSettings._mouseIsOnTooltip) {
  646. jQuery('.snoop-tooltip-settings').hide();
  647. }
  648. }, 100);
  649. });
  650. },
  651. _hookSettings: function() {
  652. var showVAT = GM_getValue('show_vat', true);
  653. var parseLinks = GM_getValue('parseLinks', true);
  654. jQuery('#pesos-config-vat').prop('checked', showVAT);
  655. jQuery('#pesos-config-parse').prop('checked', !parseLinks);
  656. jQuery('#pesos-config-vat').change(function() {
  657. GM_setValue('show_vat', jQuery('#pesos-config-vat').is(':checked'));
  658. location.reload();
  659. });
  660. jQuery('#pesos-config-parse').change(function() {
  661. GM_setValue('parseLinks', !jQuery('#pesos-config-parse').is(':checked'));
  662. location.reload();
  663. });
  664. }
  665. };
  666.  
  667. var tooltipTemplate = '<div class="ap_popover ap_popover_sprited snoop-tooltip" surround="6,16,18,16" tabindex="0" style="z-index: 200; width: 375px;"><div class="ap_header"><div class="ap_left"></div>' + '<div class="ap_middle"></div><div class="ap_right"></div></div><div class="ap_body"><div class="ap_left"></div><div class="ap_content" style="padding-left: 17px; padding-right: 17px; padding-bottom: 8px; ">' + '<div class="tmm_popover" >{{#shops}}<div class="entry title" style=""><span id="snoop-shop-{{id}}" class="entry snoop-price"><img class="snoop-loader" src="{{loader_url}}" /></span>' + '<span class="snoop-on"> en </span><a href="{{base_url}}&snoop-from={{from_shop}}&snoop-from-asin={asin}" class="snoop-link">{{title}}</a></div>{{/shops}}</div></div><div class="ap_right"></div></div>' + '<div class="ap_footer"><div class="ap_left"></div><div class="ap_middle"></div><div class="ap_right"></div></div></div>';
  668.  
  669. var Page = {
  670. addTooltipToPage: function(tooltipMarkup) {
  671. console.log(BANNER, 'Page.addTooltipToPage()');
  672.  
  673. var $placeholderMarkup = jQuery('<img id="snoop-placeholder" src="https://i.imgur.com/7vqGfyT.png" alt="Placeholder" />');
  674. var $imageMarkup = jQuery('<img id="snoop-icon" src="https://i.imgur.com/lTWMEoH.png" />');
  675. var $imageMarkupMELI = jQuery('<img id="snoop-icon-ml" src="https://i.imgur.com/mxQjoLn.png" />');
  676. var $container = this.findAppropriateTooltipContainer();
  677. var $settings = '<a href="javascript:void(0)" id="pesos-config" class="nav-a nav-a-2 nav-truncate"><span class="nav-line-1">Configurar Script</span><span class="nav-line-2"><img src="https://i.imgur.com/qa5ZXdT.png" width="95"></span></a>';
  678. var $containerHeader = jQuery('#nav-tools');
  679. var tooltipTemplateML = '<div class="ap_popover ap_popover_sprited snoop-tooltip-ml" surround="6,16,18,16" tabindex="0" style="z-index: 200; width: 700px;"><div class="ap_header"><div class="ap_left"></div>' + '<div class="ap_middle"></div><div class="ap_right"></div></div><div class="ap_body"><div class="ap_left"></div><div class="ap_content" style="padding-left: 17px; padding-right: 17px; padding-bottom: 8px; ">' + '<div class="tmm_popover"><img class="snoop-loader" src="https://i.imgur.com/Dp92MjH.gif" /> Cargando...</div></div><div class="ap_right"></div></div><div class="ap_footer"><div class="ap_left"></div><div class="ap_middle"></div><div class="ap_right"></div></div></div>';
  680. var tooltipTemplateSettings = '<div class="ap_popover ap_popover_sprited snoop-tooltip-settings" surround="6,16,18,16" tabindex="0" style="z-index: 200; width: 350px; margin-top: 50px; display: none"><div class="ap_header"><div class="ap_left"></div>' + '<div class="ap_middle"></div><div class="ap_right"></div></div><div class="ap_body"><div class="ap_left"></div><div class="ap_content" style="padding-left: 17px; padding-right: 17px; padding-bottom: 8px; ">' + '<div class="tmm_popover">' + '<div class="a-checkbox"><label for="pesos-config-vat"><input type="checkbox" id="pesos-config-vat" style="vertical-align: 0%;"><span class="a-label a-checkbox-label">Restar VAT de los precios automáticamente<span></label></div><br>' + '<div class="a-checkbox"><label for="pesos-config-parse"><input type="checkbox" id="pesos-config-parse" style="vertical-align: 0%;"><span class="a-label a-checkbox-label">Deshabilitar referidos del script<span></label></div>' + '</div></div><div class="ap_right"></div></div><div class="ap_footer"><div class="ap_left"></div><div class="ap_middle"></div><div class="ap_right"></div></div></div>';
  681. if (jQuery('#merchant-info').text().trim().replace(/\s\s+/g, ' ').match(new RegExp(settings.currentShop.seller, 'i')) === null && jQuery('#olp_feature_div').length > 0) {
  682. var merchant_expected = settings.currentShop.base_url.match(/smid=([A-Z0-9]+)/);
  683. var merchant_current = window.location.href.match(/smid=([A-Z0-9]+)/);
  684. if (merchant_expected && merchant_current && merchant_expected[1] == merchant_current[1]) {
  685. $container.after(' &nbsp; <span class="a-color-error"><b>[Este producto no lo vende Amazon]</b></span> &nbsp; ');
  686. } else {
  687. $container.after(' &nbsp; <a href="' + settings.currentShop.base_url.replace('{asin}', jQuery('#ASIN').val()) + '"><b>[Cambiar al vendido por Amazon]</b></a> &nbsp; ');
  688. }
  689. } else {
  690. jQuery('#ddmDeliveryMessage .a-color-error').css('text-decoration','line-through');
  691. }
  692.  
  693. $container.after($imageMarkupMELI);
  694. $container.after(tooltipTemplateML);
  695. $container.after($imageMarkup);
  696. $container.after(tooltipMarkup);
  697. if (jQuery('#pesos-config').length === 0) {
  698. $containerHeader.prepend($settings);
  699. $containerHeader.prepend(tooltipTemplateSettings);
  700. tooltipSettings.registerShowHideHandlers();
  701. }
  702. tooltip.registerShowHideHandlers();
  703. tooltipML.registerShowHideHandlers();
  704. convertCurrency();
  705. },
  706. findAppropriateTooltipContainer: function() {
  707. console.log(BANNER, 'Page.findAppropriateTooltipContainer()');
  708.  
  709. var $tries = [
  710. jQuery('table.product .priceLarge:first', jQuery('#priceBlock')),
  711. jQuery('#priceblock_ourprice'),
  712. jQuery('#priceblock_saleprice'),
  713. jQuery('#priceblock_dealprice'),
  714. jQuery('#availability_feature_div > #availability > .a-color-price'),
  715. jQuery('div.buying span.availGreen', jQuery('#handleBuy')),
  716. jQuery('div.buying span.availRed:nth-child(2)', jQuery('#handleBuy')),
  717. jQuery('#availability')
  718. ];
  719.  
  720. for (var i = 0; i < $tries.length; i++) {
  721. if ($tries[i].length > 0) {
  722. console.log(BANNER, 'Page.findAppropriateTooltipContainer() i = ' + i);
  723.  
  724. return $tries[i];
  725. }
  726. }
  727.  
  728. throw new Error('Unable to find the price section.');
  729. },
  730. displayPrice: function($shopInfo, price, vat) {
  731. var convertedPrice = price.for(settings.currentShop.currency, settings.currentShop.currency_symbol);
  732. var convertedString = convertedPrice.toString();
  733.  
  734. // este es un fix provisorio hasta que termine el refactor
  735. if (convertedString !== 'EUR 0.00') {
  736. $shopInfo.text(convertedPrice.toString());
  737. convertCurrency(0, vat);
  738. }
  739.  
  740. },
  741. displayWarning: function($shopInfo, warning, addNotFoundClass) {
  742. $shopInfo.text(warning).addClass('snoop-warning');
  743. if (addNotFoundClass) {
  744. $shopInfo.parent().addClass('snoop-not-found');
  745. }
  746. },
  747. registerInitializationHandler: function(shops) {
  748. console.log(BANNER, 'Page.registerInitializationHandler()');
  749.  
  750. jQuery('#snoop-icon').mouseover(function() {
  751. if (window.snoop_tooltipInitialized !== undefined && window.snoop_tooltipInitialized !== false) return;
  752. window.snoop_tooltipInitialized = true;
  753. $.each(shops, function(index, shop) {
  754. var $shopInfo = jQuery('#snoop-shop-' + shop.id);
  755. PageScraper.getPriceOn(
  756. shop,
  757. function(price) {
  758. Page.displayPrice($shopInfo, shop.moneyFrom(price), shop.vat);
  759. },
  760. function(warning, addNotFoundClass) {
  761. Page.displayWarning($shopInfo, warning, addNotFoundClass);
  762. }
  763. );
  764. });
  765. });
  766. jQuery('#snoop-icon-ml').mouseover(function() {
  767. if (window.snoopML_tooltipInitialized !== undefined && window.snoopML_tooltipInitialized !== false) return;
  768. window.snoopML_tooltipInitialized = true;
  769. var productName = decodeURI(jQuery('#productTitle').html().replace('&nbsp;', ' ').replace(/[^\w\d\s\.]/g, ' ').trim());
  770. Meli.showPrices(productName);
  771. });
  772. }
  773. };
  774.  
  775. var snoop = {
  776. tooltip: null,
  777. asin: null,
  778. _startMonitoringAsin: function(domainData, domain) {
  779. var observer = new MutationObserver(function(mutations) {
  780. var asinHasProbablyChanged = mutations.some(function(mutation) {
  781. return mutation.addedNodes.length > 0;
  782. });
  783. if (!asinHasProbablyChanged) return;
  784. var newAsin = jQuery('#ASIN').val();
  785. if (snoop.asin == newAsin) return;
  786. snoop.run(newAsin, domainData, domain);
  787. });
  788. if (jQuery('#buybox_feature_div').get(0)) {
  789. observer.observe(jQuery('#buybox_feature_div').get(0), {
  790. attributes: true,
  791. subtree: true,
  792. childList: true,
  793. characterData: true
  794. });
  795. }
  796. },
  797. initialize: function(asin, domainData, domain) {
  798. this.asin = asin;
  799. this._startMonitoringAsin(domainData, domain);
  800. //refreshRates();
  801. console.log(BANNER, 'snoop.initialize()');
  802. settings = new Settings(asin, domainData, domain);
  803. snoop.tooltip = Mustache.to_html(tooltipTemplate, {
  804. shops: settings.filteredShops,
  805. from_shop: settings.currentShop.id,
  806. from_asin: settings.asin,
  807. loader_url: 'https://i.imgur.com/Dp92MjH.gif'
  808. });
  809. snoop.run(asin, domainData, domain);
  810. },
  811. run: function(asin, domainData, domain) {
  812. console.log(BANNER, 'snoop.run()');
  813. this.asin = asin;
  814. settings = new Settings(asin, domainData, domain);
  815. window.snoop_tooltipInitialized = false;
  816. window.snoopML_tooltipInitialized = false;
  817. var ensureTooltipHasBeenLoaded = function() {
  818. if (snoop.tooltip === null) {
  819. setTimeout(ensureTooltipHasBeenLoaded, 50);
  820. } else {
  821. var tooltipMarkup = snoop.tooltip.replace(/{asin}/gm, settings.asin);
  822. Page.addTooltipToPage(tooltipMarkup);
  823. Page.registerInitializationHandler(settings.filteredShops);
  824. }
  825. };
  826. ensureTooltipHasBeenLoaded();
  827. }
  828. };
  829.  
  830. var Meli = {
  831. showPrices: function(productName) {
  832. console.log(BANNER, 'Meli.fetchApiData()');
  833. Meli.fetchApiData(productName, Meli.showProducts);
  834. },
  835. showProducts: function(data) {
  836. var products = jQuery('.snoop-tooltip-ml .tmm_popover');
  837. products.html('<div class="entry title" style="font-size:10px"><b>Buscando por:</b> ' + data.query + '</div>');
  838. if (data.results.length === 0) {
  839. products.append('<div class="entry title">No se encontraron productos en MercadoLibre con esta búsqueda.</div>');
  840. }
  841. data.results.forEach(function(product) {
  842. products.append('<div class="entry title"><div class="snoop-price" style="width:130px;display:inline-block;text-align:right;"><div class="price-ars">ARS $' + product.price.formatMoney(2) + '</div></div><span class="snoop-on"> &raquo; </span><a href="' + product.permalink + '" target="_blank" class="snoop-link">' + product.title + '</a></div>');
  843. });
  844. },
  845. fetchApiData: function(productName, callback) {
  846. jQuery.getJSON(
  847. "https://api.mercadolibre.com/sites/MLA/search?q=" + encodeURI(productName) + "&condition=new"
  848. ).done(function(data) {
  849. callback(data);
  850. });
  851. }
  852. };

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址