// ==UserScript== // @name [e-dostavka.by, gipermall.by] price comparison // @namespace http://tampermonkey.net/ // @version 2.0 // @description Show prices per kilo, compare between sites // @author fulloftsars // @match https://e-dostavka.by/* // @match https://gipermall.by/* // @grant unsafeWindow // @grant GM.xmlHttpRequest // @require https://cdnjs.cloudflare.com/ajax/libs/arrive/2.4.1/arrive.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js // @require https://unpkg.com/ohm-js@0.14.0/dist/ohm.min.js // ==/UserScript== (function () { 'use strict'; const price = (() => { const float = n => parseFloat(n.sourceString) const priceG = ohm.grammar(`Price { Price = digit+ "р." digit+ "к." Price? }`) const priceS = priceG.createSemantics().addOperation('val', { Price: (rub, _2, kop, _4, _5) => float(rub) * 100 + float(kop), }) const weightG = ohm.grammar(`Weight { Exp = BS* AnyWeight BS* AnyWeight? BS* AnyWeight = MulWeight | Weight Weight = float (OneUnit | ThUnit) OneUnit = Dot<"г"> | Dot<"мл"> | Dot<"шт"> | Dot<"см"> ThUnit = Dot<"кг"> | Dot<"л"> | Dot<"м"> Dot = R "."* MulWeight = float ("x" | "х" | "*") Weight BS = ~AnyWeight any float = (digit digit* "." digit) -- fl | digit+ }`) const weightS = weightG.createSemantics().addOperation('val', { Exp: (_, weight, __, ___, _____) => weight.val(), Weight: (n, u) => float(n) * u.val(), OneUnit: _ => 1, ThUnit: _ => 1000, MulWeight: (d, _, w) => float(d) * w.val(), }) const interpret = (g, s) => (text) => s(g.match(text)) return (price, weight) => (interpret(priceG, priceS)(price).val() / interpret(weightG, weightS)(weight).val() / 100 * 1000) })() const $ = unsafeWindow.jQuery; // somehow, when @including jquery, infinite scroll stops working. const template = $("").css({ 'background-color': '#fbba00', 'color': 'black', // default is #cb4f2b 'padding': '2px', 'border-radius': '5px', 'font-size': '14px', 'font-family': 'MyriadProCondencedBoldItalic', 'position': 'absolute', 'right': '5px' }).attr('target', '_blank') $(document).arrive(".products_card", { existing: true }, div => { const normalizedPrice = price( $(div).find('div > form > div.prices__wrapper > div > div.prices_block > div > div.price').text(), $(div).find('a.fancy_ajax').text() ) const button = template.clone() const url = (R.test(/e-dostavka/, location.host) ? R.identity : R.flip)(R.replace)('e-dostavka', 'gipermall', $(div).find('a.fancy_ajax').attr('href')) $(div).find('a.fa').replaceWith(button) button.text(normalizedPrice.toFixed(2)) GM.xmlHttpRequest({ method: 'GET', url, onload: page => { try { const html = $($.parseHTML(page.responseText)) const competingPrice = price( html.find('div.services_wrap:nth-child(3) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1)').text(), html.find('.template_1_columns > h1:nth-child(2)').text() ) const difference = Math.abs(1 - competingPrice / normalizedPrice) * 100 button.text((i, _) => `${_} (${competingPrice >= normalizedPrice ? '>' : '<'}${difference.toFixed(0)}%)`).prop('href', url) } catch (e) { } } }); }); })();