@global-savings-group/caa-engine
Advanced tools
Comparing version 4.0.3 to 4.0.4
@@ -1,1 +0,1 @@ | ||
(()=>{"use strict";var e,t={d:(e,n)=>{for(var o in n)t.o(n,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:n[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},n={};t.r(n),t.d(n,{AmountType:()=>A,BackgroundToClientMessageType:()=>Q,ClientToBackgroundMessageType:()=>Z,TestedCodeType:()=>G,getElements:()=>B,getGeneratedSelector:()=>q,getMainDomain:()=>R,setupBackgroundListeners:()=>ne,setupContentListeners:()=>x}),function(e){e.Reloading="Reloading",e.Done="Done",e.UnhandledError="UnhandledError",e.Timeout="Timeout",e.NoRequiredSelectorsProvided="NoRequiredSelectorsProvided",e.NoInputField="NoInputField"}(e||(e={}));let o=()=>{};function r(e){o=e}const i={error:(e,t)=>o({level:"ERROR",message:e,stack:t instanceof Error&&t.stack||(new Error).stack||""}),info:e=>o({details:JSON.stringify(e),level:"INFO"}),perf:(e,t)=>o({label:e,level:"PERF",meta:t})};async function a(e=500){return new Promise((t=>setTimeout(t,e)))}function l(e,t){return"object"==typeof e&&null!==e&&t in e}function u(e){return!l(e,"disabled")||!e.disabled}function s(e){return!!u(e)&&"none"!==window.getComputedStyle(e).getPropertyValue("pointer-events")}function c(e){if(e.hidden)return!1;const t=window.getComputedStyle(e);return"hidden"!==t.getPropertyValue("visibility")&&"0"!==t.getPropertyValue("opacity")&&"none"!==t.getPropertyValue("display")&&0!==e.offsetWidth&&0!==e.offsetHeight}function d(e){return u(e)&&s(e)&&c(e)}function f(e){return"INPUT"!==e.tagName&&!e.innerHTML.length}const m=1e3;function p(e=.5){return new Promise((t=>setTimeout(t,e*m)))}function h(e){e.dispatchEvent(new PointerEvent("pointerdown",{bubbles:!0,pointerType:"mouse"})),e.dispatchEvent(new MouseEvent("mousedown",{bubbles:!0})),e.dispatchEvent(new PointerEvent("pointerup",{bubbles:!0,pointerType:"mouse"})),e.dispatchEvent(new MouseEvent("mouseup",{bubbles:!0})),e.dispatchEvent(new PointerEvent("click",{bubbles:!0,cancelable:!0,pointerType:"mouse"}))}function y(e){try{const[,t=""]=e.split('"');return Object(JSON.parse(decodeURI(t)))}catch{return{}}}function v(e){return y(e)}const g=/[0-9.,]+/g;function b(e){return e?e.normalize("NFC").replaceAll(g,""):null}const w="data-caa-text";function E({innerText:e,tagName:t}){return function(e){try{return encodeURI(JSON.stringify(e))}catch(e){return i.error("Cannot encode a custom cssSelector: ",e),""}}({innerText:e,tagName:t})}function C(e){const{tagName:t,innerText:n}=y(e);return e.includes(w)&&"string"==typeof t&&"string"==typeof n}function S(e){return C(e)}function T(e){const t=Array.from(document.querySelectorAll(e));return C(e)?t.length>0?t.filter((n=e,function(e){const{tagName:t,innerText:o}=v(n);return e.tagName===t&&b(e.innerText)===b(o)})):function(e){const{tagName:t,innerText:n}=v(e);return Array.from(document.getElementsByTagName(t)).filter((e=>e instanceof HTMLElement)).filter((e=>b(e.innerText)===b(n))).map((e=>(e.setAttribute(w,E(e)),e)))}(e):[];var n}function P(e){try{if(S(e)){const[t=null]=T(e);return t}return document.querySelector(e)}catch(t){return i.error(`Cannot find the element in the DOM with the selector="${e}":`,t),null}}function B(e){try{return S(e)?T(e):Array.from(document.querySelectorAll(e))}catch(t){return i.error(`Cannot find elements in the DOM with the selector="${e}":`,t),[]}}function I(e){return!!e&&Boolean(P(e))}async function M(t,n){async function o(n=0){if(n>=4)throw e.Timeout;const r=t.couponInput&&P(t.couponInput);if(r&&d(r))return;if(!t.showFormButton)return;const a=P(t.showFormButton);return a&&d(a)&&(i.info("Trying to show the coupon form"),h(a)),await p(),o(n+1)}async function r(e=0){if(e>=10)return;const o=t.couponInput?P(t.couponInput):null;if(!(o&&(a=o,l(a,"value")&&d(a))))return r(e+1);var a;i.info("Trying to fill in the code"),function(e,t){const{value:n}=e;if(e.value=t,l(e,"_valueTracker")&&e._valueTracker){const t=e._valueTracker;l(t,"setValue")&&"function"==typeof t.setValue&&t.setValue(n)}e.dispatchEvent(new KeyboardEvent("keydown",{bubbles:!0})),e.dispatchEvent(new KeyboardEvent("keypress",{bubbles:!0}));const o=new CustomEvent("input",{bubbles:!0,detail:{simulated:!0}});e.dispatchEvent(o),e.dispatchEvent(new KeyboardEvent("keyup",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0}))}(o,n),await p();const u=t.applyButton?P(t.applyButton):null;return u&&d(u)?(i.info("Trying to submit the code"),void h(u)):r(e+1)}function a(){const[e,n]=function(){const e={pending:!0};return[(async()=>{for(let n=0;n<4;n++){const n=[t.error,t.removeButton,t.appliedCode];if(!e.pending||n.some(I))break;i.info("Waiting for feedback"),await p()}})(),()=>{e.pending=!1}]}(),[o,r]=t.loading?function(e){const t={bodyObserver:null,isLoading:I(e)};return[new Promise((n=>{t.bodyObserver=new MutationObserver((()=>{I(e)?t.isLoading=!0:t.isLoading&&n()})),t.bodyObserver.observe(document.body,{childList:!0,subtree:!0})})),()=>t.bodyObserver?.disconnect()]}(t.loading):[void 0,()=>{}],a=[e,o].filter(Boolean),l=[n,r];return Promise.race(a).finally((()=>{l.forEach((e=>e()))}))}async function u(n=0){if(t.totalAmount){if(n>=4)throw e.Timeout;if(!P(t.totalAmount))return i.info("Waiting for total price"),await p(),u(n+1)}}async function s(n=0,o=0){if(!t.closeModal)return;if(n>=4)throw e.Timeout;const r=P(t.closeModal);if(!r||!d(r)){if(n>0||o>=4)return;return await p(),s(n,o+1)}return i.info("Trying to close modal"),h(r),await p(),s(n+1)}return new Promise((l=>{const c=()=>{i.info("Page is about to reload."),l({type:e.Reloading})};(async()=>{try{if(!t.couponInput||!t.applyButton)throw e.NoRequiredSelectorsProvided;i.info(`Preparing to apply code: ${n}`),window.addEventListener("beforeunload",c),await o(),await r(),await s(),await a(),await u(),i.info(`Code: ${n} applied.`),l({type:e.Done})}catch(t){const o=function(t){switch(t){case e.Reloading:return e.Reloading;case e.Timeout:return e.Timeout;case e.NoInputField:return e.NoInputField;case e.NoRequiredSelectorsProvided:return e.NoRequiredSelectorsProvided;default:return e.UnhandledError}}(t);i.error(`Failed to apply code: ${n} -- ${o}`,t),l({type:o})}finally{window.removeEventListener("beforeunload",c),i.info("beforeunload listener removed.")}})()}))}var N,A,$;function R(e){const t=e.toLowerCase().replace(/^https?:\/\//,"").replace(/:\d+.*/,"").replace(/(:|\/|\?|#).*/,"");if(!/[a-z0-9-.]+/.test(t))throw new Error(`Cannot get main domain from ${e}`);const[n,o,r]=t.split(".").reverse();if("localhost"===n)return n;if(!n||n.length<2)throw new Error(`Wrong root domain "${n}" in ${e}`);if(!o)throw new Error(`Unknown main domain "${o}" in ${e}`);if(!["co.uk","co.za","com.au","com.de","org.uk","uk.com","com.br","com.pl","com.nl","com.mx"].includes(`${o}.${n}`))return`${o}.${n}`;if(!r)throw new Error(`Unknown main domain "${r}" in ${e}`);return`${r}.${o}.${n}`}function k(e){try{if(!e)return{html:"",isClickable:!1,isEmpty:!0,isEnabled:!1,isVisible:!1,multipleMatches:!1,result:$.NoSelectorProvided};const t=B(e),[n]=t;return n?{html:n.outerHTML,isClickable:Boolean(t.filter(s).length),isEmpty:f(n),isEnabled:Boolean(t.filter(u).length),isVisible:Boolean(t.filter(c).length),multipleMatches:t.length>1,result:$.ElementFound}:{html:"",isClickable:!1,isEmpty:!0,isEnabled:!1,isVisible:!1,multipleMatches:!1,result:$.NoElementsFound}}catch(e){return e instanceof Error&&"SyntaxError"===e.name?(i.error($.InvalidCSSSelector,e),{html:"",isClickable:!1,isEmpty:!0,isEnabled:!1,isVisible:!1,multipleMatches:!1,result:$.InvalidCSSSelector}):(i.error($.Unhandled,e),{html:"",isClickable:!1,isEmpty:!0,isEnabled:!1,isVisible:!1,multipleMatches:!1,result:$.Unhandled})}}function F(e){if(!e)return!1;const t=e.totalAmount?B(e.totalAmount):[],n=e.couponInput?B(e.couponInput).filter(d):[],o=e.applyButton?B(e.applyButton).filter(c):[],r=e.showFormButton?B(e.showFormButton).filter(d):[];return Boolean(n.length)&&Boolean(o.length)&&Boolean(t.length)||Boolean(t.length)&&Boolean(r.length)}function V(e){if(!e||!e.removeButton)return!1;const t=B(e.removeButton).filter(d);return Boolean(t.length)}function L(e){try{if(!e)return{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:$.NoSelectorProvided};const t=B(e),[n]=t;return n?{amount:function(e){if(!e)throw new Error("Cannot parse amount from empty value");if("string"!=typeof e)throw new Error(`Cannot parse amount from "${typeof e}"`);if(!e.match(/\d/))throw new Error(`Amount not found in "${e}"`);let t,n=e.replace(/[^0-9,.]/g,""),o=0;function r(e){t&&t!==e?i.error(`Amount has conflicting types: ${t} and ${e}`):t=e}return n.match(/^\d{1,3}(?:\.\d{3})*(?:,\d{2})?$/)&&(n=n.replaceAll(".","").replace(",",".")),n.match(/^\d{1,3}(?:,\d{3})*(?:.\d{2})?$/)&&(n=n.replaceAll(",","")),(n.match(/^\d*(?:,\d{2})?$/)||n.match(/^\d*(?:,\d{1})?$/))&&(n=n.replaceAll(",",".")),o=parseFloat(n.replace(/([^0-9.])/g,"")),(e.includes("€")||e.includes("EUR"))&&r(A.Euro),e.includes("$")&&(e.includes("R$")?r(A.Real):r(A.Dollar)),e.includes("£")&&r(A.Pound),e.includes("%")&&r(A.Percent),(e.includes("zł")||e.includes("PLN"))&&r(A.Zloty),t?{type:t,value:o}:{value:o}}(n.innerText),html:n.outerHTML,isEmpty:f(n),isVisible:Boolean(t.filter(c).length),multipleMatches:t.length>1,result:$.ElementFound}:{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:$.NoElementsFound}}catch(e){return e instanceof Error&&"SyntaxError"===e.name?(i.error($.InvalidCSSSelector,e),{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:$.InvalidCSSSelector}):(i.error($.Unhandled,e),{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:$.Unhandled})}}function U(e){try{if(!e)return{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:$.NoSelectorProvided,value:""};const t=B(e),[n]=t;return n?{html:n.outerHTML,isEmpty:f(n),isVisible:Boolean(t.filter(c).length),multipleMatches:t.length>1,result:$.ElementFound,value:n.innerHTML}:{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:$.NoElementsFound,value:""}}catch(e){return e instanceof Error&&"SyntaxError"===e.name?(i.error($.InvalidCSSSelector,e),{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:$.InvalidCSSSelector,value:""}):(i.error($.Unhandled,e),{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:$.Unhandled,value:""})}}function D(){return window.location.href}!function(e){e.GetPageState="caa-get-page-state",e.ApplyCode="caa-apply-code",e.RemoveCode="caa-remove-code"}(N||(N={})),function(e){e.Dollar="$",e.Euro="€",e.Percent="%",e.Pound="£",e.Real="R$",e.Zloty="zł"}(A||(A={})),function(e){e.ElementFound="ElementFound",e.NoSelectorProvided="NoSelectorProvided",e.Unhandled="Unhandled",e.NoElementsFound="NoElementsFound",e.InvalidCSSSelector="InvalidCSSSelector",e.NoConfigProvided="NoConfigProvided"}($||($={}));const O=function(){try{return"undefined"!=typeof browser?browser:chrome}catch{return console.warn("[CAA-ENGINE]: not running in a DOM environment, the browser object is not defined."),{}}}();function x({logger:t=(()=>{})}={}){O.runtime.onMessage.addListener(((n,o,l)=>{switch(r(t),n.type){case N.GetPageState:return async function(e){return{amounts:{discount:L(e.discountAmount),subtotal:L(e.subtotalAmount),total:L(e.totalAmount)},coupon:{appliedCode:U(e.appliedCode),canApply:F(e),canRemove:V(e)},currentUrl:D(),elements:{applyButton:k(e.applyButton),closeModal:k(e.closeModal),couponInput:k(e.couponInput),error:k(e.error),loading:k(e.loading),removeButton:k(e.removeButton),showFormButton:k(e.showFormButton)},mainDomain:R(D())}}(n.config).then(l),!0;case N.ApplyCode:return M(n.config,n.code).then(l),!0;case N.RemoveCode:return async function(t){let n=!1;try{if(!t.removeButton)throw e.NoRequiredSelectorsProvided;return i.info("Trying to remove applied code."),window.addEventListener("beforeunload",o),await async function o(r=0){if(r>=4)throw e.Timeout;if(n)throw e.Reloading;if(!t.removeButton)return;const l=P(t.removeButton);return l&&d(l)?(h(l),i.info("Waiting for coupon is removed"),await a(),o(r+1)):void 0}(),i.info("Code removed."),{type:e.Done}}catch(t){let n;return i.error("Failed to remove the code",t),n=t===e.Reloading?e.Reloading:e.UnhandledError,{type:n}}finally{window.removeEventListener("beforeunload",o),i.info("beforeunload listener removed.")}function o(){i.info("Page is about to reload."),n=!0}}(n.config).then(l),!0}}))}function q(e){const t=function(e){return`[${w}="${E(e)}"]`}(e);return 1===B(t).length?t:null}async function j(e,t,n=1e4){return new Promise((async o=>{let r=!1;const l=setTimeout((()=>{r=!0,o(null)}),n);for(;!r;){try{const n=await O.tabs.sendMessage(e,{config:t,type:N.GetPageState});if(n)return clearTimeout(l),void o(n)}catch(e){i.error("get caa page state",e)}await a(200)}}))}var G;function H(e,t){const n=e.isVisible,o=t.isVisible,r=e.html!==t.html;return!(n||!o)||!!(n&&o&&r)}async function W(e,t,n){const o=await j(e,n);if(!o)return{...t,type:G.Invalid};let r=o.amounts.total.amount;if(!r)return{...t,type:G.Invalid};if(o.elements.removeButton.isClickable){try{await async function(e,t){let n=10;try{await O.tabs.sendMessage(e,{config:t,type:N.RemoveCode})}catch(e){i.error("remove caa-engine error",e)}for(;n>0;){n--;const o=await j(e,t);if(o){if(!o.elements.removeButton.isVisible)return;await a(200)}}if(!n)throw new Error("remove code is not removed")}(e,n)}catch(e){return i.error("remove code caa-background",e),{...t,type:G.Invalid}}const o=await j(e,n);if(!o)return{...t,type:G.Invalid};!o.elements.removeButton.isVisible&&o.amounts.total.amount&&(r=o.amounts.total.amount)}try{const o=await O.tabs.sendMessage(e,{code:t.code,config:n,type:N.ApplyCode});i.info({codeApplicationResult:o})}catch(e){i.error("apply code caa-from-content",e)}let l=10;for(;l>0;){l--;const i=await j(e,n);if(!i)continue;const u=i.amounts.total.amount;if(u){if(u.value<r.value)return{...t,initialTotal:r,totalWithDiscount:u,type:G.Discount};if(H(o.elements.error,i.elements.error))return{...t,type:G.Invalid};await a(200)}}return i.info("timeout handleApplyProcess"),{...t,type:G.Invalid}}!function(e){e.Discount="Discount",e.Invalid="Invalid"}(G||(G={}));const z={};async function _(e,t){const n=R(e),o=new URL(e).pathname,r=t(n),i=await async function(e,t){const n=z[e];if(n?.length)return n;const o=await fetch(t).then((e=>e.json())).then(J).catch((()=>[]));return z[e]=o,o}(n,r).then(K);let a=null,l=null;for(const e of i)e.urlPattern?new RegExp(e.urlPattern).test(o)&&(l=e):a=e;if(l)return l;if(a)return a;throw new Error(`No config found for ${n}`)}function J(e){const t=e,n=[];for(const e of t.configs){const t=e;t.data&&(t.disabled||n.push({appliedCode:t.data.appliedCode||void 0,applyButton:t.data.applyButton||void 0,applyType:t.data.applyType||void 0,closeModal:t.data.closeModal||void 0,couponInput:t.data.couponInput||void 0,discountAmount:t.data.discountAmount||void 0,domain:t.data.domain||"",error:t.data.error||void 0,loading:t.data.loading||void 0,removeButton:t.data.removeButton||void 0,showFormButton:t.data.showFormButton||void 0,subtotalAmount:t.data.subtotalAmount||void 0,totalAmount:t.data.totalAmount||void 0,urlPattern:t.data.urlPattern||void 0}))}return n}function K(e){return e.sort(((e,t)=>e.urlPattern?t.urlPattern?e.urlPattern.length-t.urlPattern.length:1:-1))}var Z,Q,X;!function(e){e.TryCodes="caa-try-codes",e.Stop="caa-stop",e.GetPageState="caa-get-page-state"}(Z||(Z={})),function(e){e.CodeTested="caa-code-tested"}(Q||(Q={})),function(e){e.PageLoaded="caa-page-loaded"}(X||(X={}));class Y{active;testedCodes={};constructor(){this.active=!0}get isActive(){return this.active}stop(){this.active=!1}addTestedCode(e,t){this.testedCodes[e]=t}getTestedCode(e){return this.testedCodes[e]}}function ee(e){return e.code.trim().length&&!/\s/.test(e.code.trim())}const te={};function ne({getUnifiedConfigUrl:e,logger:t=(()=>()=>{})}){O.runtime.onMessage.addListener(((n,o,l)=>{const u=o.tab?.id,s=o.tab?.url;if(void 0!==u)if(r(t(u)),void 0!==s)switch(n.type){case X.PageLoaded:return void i.info({message:n,tabId:u});case Z.Stop:return i.info({message:n,tabId:u}),te[u]?.stop(),void i.info("stopping CAA for tab"+u);case Z.TryCodes:return i.info({message:n,tabId:u}),void async function(e,t,n,{codes:o,cacheDuplicates:r=!1,validateCodes:l=!1,minDelay:u=1e3,config:s}){let c;try{c=s||await _(t,n)}catch(e){return void i.error("Cannot get config for "+t,e)}i.info("starting CAA for tab "+e);const d=new Y;te[e]=d;for(const t of o){if(!d.isActive)break;const n=d.getTestedCode(t.code);if(r&&n){await a(u),await oe(e,{...n,...t});continue}if(l&&!ee(t)){await a(u),await oe(e,{...t,type:G.Invalid});continue}const o=(new Date).getTime(),s=await W(e,t,c);i.perf(t.code+" tested in: ",{code:t.code,timeSpent:(new Date).getTime()-o}),d.addTestedCode(t.code,s),await oe(e,s)}delete te[e]}(u,s,e,n);case Z.GetPageState:return i.info({message:n,tabId:u}),async function(e,t,n,o){let r;if(o)r=o;else try{r=await _(t,n)}catch(e){return void i.error("No config exists for: "+t,e)}const a=await j(e,r);return i.info({pageState:a,tabId:e}),a}(u,s,e,n.config).then(l),!0}else i.error("No tabUrl provided for "+u);else console.error("No tabId provided")}))}async function oe(e,t){i.info({code:t,info:"sending tried code",tabId:e});const n={code:t,type:Q.CodeTested};let o=!1;for(let r=0;r<10;r++){try{await re(e),o=await O.tabs.sendMessage(e,n)}catch(n){i.info({code:t,info:"Tried code not received by the tab.",tabId:e})}if(o)break;await a(200)}if(!o)throw new Error(`Cannot send tried code to the browser tab. code: ${t.code} , tabId: ${e}`)}async function re(e){let t=10;for(;t--;){if("complete"===(await O.tabs.get(e)).status)return;await a(100)}}module.exports=n})(); | ||
(()=>{"use strict";var e,t={d:(e,n)=>{for(var o in n)t.o(n,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:n[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},n={};t.r(n),t.d(n,{AmountType:()=>A,BackgroundToClientMessageType:()=>Z,ClientToBackgroundMessageType:()=>K,TestedCodeType:()=>G,getElements:()=>B,getGeneratedSelector:()=>q,getMainDomain:()=>R,setupBackgroundListeners:()=>te,setupContentListeners:()=>x}),function(e){e.Reloading="Reloading",e.Done="Done",e.UnhandledError="UnhandledError",e.Timeout="Timeout",e.NoRequiredSelectorsProvided="NoRequiredSelectorsProvided",e.NoInputField="NoInputField"}(e||(e={}));let o=()=>{};function r(e){o=e}const i={error:(e,t)=>o({level:"ERROR",message:e,stack:t instanceof Error&&t.stack||(new Error).stack||""}),info:e=>o({details:JSON.stringify(e),level:"INFO"}),perf:(e,t)=>o({label:e,level:"PERF",meta:t})};async function a(e=500){return new Promise((t=>setTimeout(t,e)))}function l(e,t){return"object"==typeof e&&null!==e&&t in e}function u(e){return!l(e,"disabled")||!e.disabled}function s(e){return!!u(e)&&"none"!==window.getComputedStyle(e).getPropertyValue("pointer-events")}function c(e){if(e.hidden)return!1;const t=window.getComputedStyle(e);return"hidden"!==t.getPropertyValue("visibility")&&"0"!==t.getPropertyValue("opacity")&&"none"!==t.getPropertyValue("display")&&0!==e.offsetWidth&&0!==e.offsetHeight}function d(e){return u(e)&&s(e)&&c(e)}function f(e){return"INPUT"!==e.tagName&&!e.innerHTML.length}const m=1e3;function p(e=.5){return new Promise((t=>setTimeout(t,e*m)))}function h(e){e.dispatchEvent(new PointerEvent("pointerdown",{bubbles:!0,pointerType:"mouse"})),e.dispatchEvent(new MouseEvent("mousedown",{bubbles:!0})),e.dispatchEvent(new PointerEvent("pointerup",{bubbles:!0,pointerType:"mouse"})),e.dispatchEvent(new MouseEvent("mouseup",{bubbles:!0})),e.dispatchEvent(new PointerEvent("click",{bubbles:!0,cancelable:!0,pointerType:"mouse"}))}function y(e){try{const[,t=""]=e.split('"');return Object(JSON.parse(decodeURI(t)))}catch{return{}}}function g(e){return y(e)}const v=/[0-9.,]+/g;function b(e){return e?e.normalize("NFC").replaceAll(v,""):null}const w="data-caa-text";function E({innerText:e,tagName:t}){return function(e){try{return encodeURI(JSON.stringify(e))}catch(e){return i.error("Cannot encode a custom cssSelector: ",e),""}}({innerText:e,tagName:t})}function C(e){const{tagName:t,innerText:n}=y(e);return e.includes(w)&&"string"==typeof t&&"string"==typeof n}function S(e){return C(e)}function T(e){const t=Array.from(document.querySelectorAll(e));return C(e)?t.length>0?t.filter((n=e,function(e){const{tagName:t,innerText:o}=g(n);return e.tagName===t&&b(e.innerText)===b(o)})):function(e){const{tagName:t,innerText:n}=g(e);return Array.from(document.getElementsByTagName(t)).filter((e=>e instanceof HTMLElement)).filter((e=>b(e.innerText)===b(n))).map((e=>(e.setAttribute(w,E(e)),e)))}(e):[];var n}function P(e){try{if(S(e)){const[t=null]=T(e);return t}return document.querySelector(e)}catch(t){return i.error(`Cannot find the element in the DOM with the selector="${e}":`,t),null}}function B(e){try{return S(e)?T(e):Array.from(document.querySelectorAll(e))}catch(t){return i.error(`Cannot find elements in the DOM with the selector="${e}":`,t),[]}}function I(e){return!!e&&Boolean(P(e))}async function M(t,n){async function o(n=0){if(n>=4)throw e.Timeout;const r=t.couponInput&&P(t.couponInput);if(r&&d(r))return;if(!t.showFormButton)return;const a=P(t.showFormButton);return a&&d(a)&&(i.info("Trying to show the coupon form"),h(a)),await p(),o(n+1)}async function r(e=0){if(e>=10)return;const o=t.couponInput?P(t.couponInput):null;if(!(o&&(a=o,l(a,"value")&&d(a))))return r(e+1);var a;i.info("Trying to fill in the code"),function(e,t){const{value:n}=e;if(e.value=t,l(e,"_valueTracker")&&e._valueTracker){const t=e._valueTracker;l(t,"setValue")&&"function"==typeof t.setValue&&t.setValue(n)}e.dispatchEvent(new KeyboardEvent("keydown",{bubbles:!0})),e.dispatchEvent(new KeyboardEvent("keypress",{bubbles:!0}));const o=new CustomEvent("input",{bubbles:!0,detail:{simulated:!0}});e.dispatchEvent(o),e.dispatchEvent(new KeyboardEvent("keyup",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0}))}(o,n),await p();const u=t.applyButton?P(t.applyButton):null;return u&&d(u)?(i.info("Trying to submit the code"),void h(u)):r(e+1)}function a(){const[e,n]=function(){const e={pending:!0};return[(async()=>{for(let n=0;n<4;n++){const n=[t.error,t.removeButton,t.appliedCode];if(!e.pending||n.some(I))break;i.info("Waiting for feedback"),await p()}})(),()=>{e.pending=!1}]}(),[o,r]=t.loading?function(e){const t={bodyObserver:null,isLoading:I(e)};return[new Promise((n=>{t.bodyObserver=new MutationObserver((()=>{I(e)?t.isLoading=!0:t.isLoading&&n()})),t.bodyObserver.observe(document.body,{childList:!0,subtree:!0})})),()=>t.bodyObserver?.disconnect()]}(t.loading):[void 0,()=>{}],a=[e,o].filter(Boolean),l=[n,r];return Promise.race(a).finally((()=>{l.forEach((e=>e()))}))}async function u(n=0){if(t.totalAmount){if(n>=4)throw e.Timeout;if(!P(t.totalAmount))return i.info("Waiting for total price"),await p(),u(n+1)}}async function s(n=0,o=0){if(!t.closeModal)return;if(n>=4)throw e.Timeout;const r=P(t.closeModal);if(!r||!d(r)){if(n>0||o>=4)return;return await p(),s(n,o+1)}return i.info("Trying to close modal"),h(r),await p(),s(n+1)}return new Promise((l=>{const c=()=>{i.info("Page is about to reload."),l({type:e.Reloading})};(async()=>{try{if(!t.couponInput||!t.applyButton)throw e.NoRequiredSelectorsProvided;i.info(`Preparing to apply code: ${n}`),window.addEventListener("beforeunload",c),await o(),await r(),await s(),await a(),await u(),i.info(`Code: ${n} applied.`),l({type:e.Done})}catch(t){const o=function(t){switch(t){case e.Reloading:return e.Reloading;case e.Timeout:return e.Timeout;case e.NoInputField:return e.NoInputField;case e.NoRequiredSelectorsProvided:return e.NoRequiredSelectorsProvided;default:return e.UnhandledError}}(t);i.error(`Failed to apply code: ${n} -- ${o}`,t),l({type:o})}finally{window.removeEventListener("beforeunload",c),i.info("beforeunload listener removed.")}})()}))}var N,A,$;function R(e){const t=e.toLowerCase().replace(/^https?:\/\//,"").replace(/:\d+.*/,"").replace(/(:|\/|\?|#).*/,"");if(!/[a-z0-9-.]+/.test(t))throw new Error(`Cannot get main domain from ${e}`);const[n,o,r]=t.split(".").reverse();if("localhost"===n)return n;if(!n||n.length<2)throw new Error(`Wrong root domain "${n}" in ${e}`);if(!o)throw new Error(`Unknown main domain "${o}" in ${e}`);if(!["co.uk","co.za","com.au","com.de","org.uk","uk.com","com.br","com.pl","com.nl","com.mx"].includes(`${o}.${n}`))return`${o}.${n}`;if(!r)throw new Error(`Unknown main domain "${r}" in ${e}`);return`${r}.${o}.${n}`}function k(e){try{if(!e)return{html:"",isClickable:!1,isEmpty:!0,isEnabled:!1,isVisible:!1,multipleMatches:!1,result:$.NoSelectorProvided};const t=B(e),[n]=t;return n?{html:n.outerHTML,isClickable:Boolean(t.filter(s).length),isEmpty:f(n),isEnabled:Boolean(t.filter(u).length),isVisible:Boolean(t.filter(c).length),multipleMatches:t.length>1,result:$.ElementFound}:{html:"",isClickable:!1,isEmpty:!0,isEnabled:!1,isVisible:!1,multipleMatches:!1,result:$.NoElementsFound}}catch(e){return e instanceof Error&&"SyntaxError"===e.name?(i.error($.InvalidCSSSelector,e),{html:"",isClickable:!1,isEmpty:!0,isEnabled:!1,isVisible:!1,multipleMatches:!1,result:$.InvalidCSSSelector}):(i.error($.Unhandled,e),{html:"",isClickable:!1,isEmpty:!0,isEnabled:!1,isVisible:!1,multipleMatches:!1,result:$.Unhandled})}}function F(e){if(!e)return!1;const t=e.totalAmount?B(e.totalAmount):[],n=e.couponInput?B(e.couponInput).filter(d):[],o=e.applyButton?B(e.applyButton).filter(c):[],r=e.showFormButton?B(e.showFormButton).filter(d):[];return Boolean(n.length)&&Boolean(o.length)&&Boolean(t.length)||Boolean(t.length)&&Boolean(r.length)}function V(e){if(!e||!e.removeButton)return!1;const t=B(e.removeButton).filter(d);return Boolean(t.length)}function L(e){try{if(!e)return{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:$.NoSelectorProvided};const t=B(e),[n]=t;return n?{amount:function(e){if(!e)throw new Error("Cannot parse amount from empty value");if("string"!=typeof e)throw new Error(`Cannot parse amount from "${typeof e}"`);if(!e.match(/\d/))throw new Error(`Amount not found in "${e}"`);let t,n=e.replace(/[^0-9,.]/g,""),o=0;function r(e){t&&t!==e?i.error(`Amount has conflicting types: ${t} and ${e}`):t=e}return n.match(/^\d{1,3}(?:\.\d{3})*(?:,\d{2})?$/)&&(n=n.replaceAll(".","").replace(",",".")),n.match(/^\d{1,3}(?:,\d{3})*(?:.\d{2})?$/)&&(n=n.replaceAll(",","")),(n.match(/^\d*(?:,\d{2})?$/)||n.match(/^\d*(?:,\d{1})?$/))&&(n=n.replaceAll(",",".")),o=parseFloat(n.replace(/([^0-9.])/g,"")),(e.includes("€")||e.includes("EUR"))&&r(A.Euro),e.includes("$")&&(e.includes("R$")?r(A.Real):r(A.Dollar)),e.includes("£")&&r(A.Pound),e.includes("%")&&r(A.Percent),(e.includes("zł")||e.includes("PLN"))&&r(A.Zloty),t?{type:t,value:o}:{value:o}}(n.innerText),html:n.outerHTML,isEmpty:f(n),isVisible:Boolean(t.filter(c).length),multipleMatches:t.length>1,result:$.ElementFound}:{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:$.NoElementsFound}}catch(e){return e instanceof Error&&"SyntaxError"===e.name?(i.error($.InvalidCSSSelector,e),{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:$.InvalidCSSSelector}):(i.error($.Unhandled,e),{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:$.Unhandled})}}function U(e){try{if(!e)return{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:$.NoSelectorProvided,value:""};const t=B(e),[n]=t;return n?{html:n.outerHTML,isEmpty:f(n),isVisible:Boolean(t.filter(c).length),multipleMatches:t.length>1,result:$.ElementFound,value:n.innerHTML}:{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:$.NoElementsFound,value:""}}catch(e){return e instanceof Error&&"SyntaxError"===e.name?(i.error($.InvalidCSSSelector,e),{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:$.InvalidCSSSelector,value:""}):(i.error($.Unhandled,e),{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:$.Unhandled,value:""})}}function D(){return window.location.href}!function(e){e.GetPageState="caa-get-page-state",e.ApplyCode="caa-apply-code",e.RemoveCode="caa-remove-code"}(N||(N={})),function(e){e.Dollar="$",e.Euro="€",e.Percent="%",e.Pound="£",e.Real="R$",e.Zloty="zł"}(A||(A={})),function(e){e.ElementFound="ElementFound",e.NoSelectorProvided="NoSelectorProvided",e.Unhandled="Unhandled",e.NoElementsFound="NoElementsFound",e.InvalidCSSSelector="InvalidCSSSelector",e.NoConfigProvided="NoConfigProvided"}($||($={}));const O=function(){try{return"undefined"!=typeof browser?browser:chrome}catch{return console.warn("[CAA-ENGINE]: not running in a DOM environment, the browser object is not defined."),{}}}();function x({logger:t=(()=>{})}={}){O.runtime.onMessage.addListener(((n,o,l)=>{switch(r(t),n.type){case N.GetPageState:return async function(e){return{amounts:{discount:L(e.discountAmount),subtotal:L(e.subtotalAmount),total:L(e.totalAmount)},coupon:{appliedCode:U(e.appliedCode),canApply:F(e),canRemove:V(e)},currentUrl:D(),elements:{applyButton:k(e.applyButton),closeModal:k(e.closeModal),couponInput:k(e.couponInput),error:k(e.error),loading:k(e.loading),removeButton:k(e.removeButton),showFormButton:k(e.showFormButton)},mainDomain:R(D())}}(n.config).then(l),!0;case N.ApplyCode:return M(n.config,n.code).then(l),!0;case N.RemoveCode:return async function(t){let n=!1;try{if(!t.removeButton)throw e.NoRequiredSelectorsProvided;return i.info("Trying to remove applied code."),window.addEventListener("beforeunload",o),await async function o(r=0){if(r>=4)throw e.Timeout;if(n)throw e.Reloading;if(!t.removeButton)return;const l=P(t.removeButton);return l&&d(l)?(h(l),i.info("Waiting for coupon is removed"),await a(),o(r+1)):void 0}(),i.info("Code removed."),{type:e.Done}}catch(t){let n;return i.error("Failed to remove the code",t),n=t===e.Reloading?e.Reloading:e.UnhandledError,{type:n}}finally{window.removeEventListener("beforeunload",o),i.info("beforeunload listener removed.")}function o(){i.info("Page is about to reload."),n=!0}}(n.config).then(l),!0}}))}function q(e){const t=function(e){return`[${w}="${E(e)}"]`}(e);return 1===B(t).length?t:null}async function j(e,t,n=1e4){return new Promise((async o=>{let r=!1;const l=setTimeout((()=>{r=!0,o(null)}),n);for(;!r;){try{const n=await O.tabs.sendMessage(e,{config:t,type:N.GetPageState});if(n)return clearTimeout(l),void o(n)}catch(e){i.error("get caa page state",e)}await a(200)}}))}var G;async function H(e,t,n){const o=await j(e,n);if(!o)return{...t,type:G.Invalid};let r=o.amounts.total.amount;if(!r)return{...t,type:G.Invalid};if(o.elements.removeButton.isClickable){try{await async function(e,t){let n=10;try{await O.tabs.sendMessage(e,{config:t,type:N.RemoveCode})}catch(e){i.error("remove caa-engine error",e)}for(;n>0;){n--;const o=await j(e,t);if(o){if(!o.elements.removeButton.isVisible)return;await a(200)}}if(!n)throw new Error("remove code is not removed")}(e,n)}catch(e){return i.error("remove code caa-background",e),{...t,type:G.Invalid}}const o=await j(e,n);if(!o)return{...t,type:G.Invalid};!o.elements.removeButton.isVisible&&o.amounts.total.amount&&(r=o.amounts.total.amount)}try{const o=await O.tabs.sendMessage(e,{code:t.code,config:n,type:N.ApplyCode});i.info({codeApplicationResult:o})}catch(e){i.error("apply code caa-from-content",e)}let l=10;for(;l>0;){l--;const o=await j(e,n);if(!o)continue;const i=o.amounts.total.amount;if(i){if(i.value<r.value)return{...t,initialTotal:r,totalWithDiscount:i,type:G.Discount};await a(200)}}return i.info("timeout handleApplyProcess"),{...t,type:G.Invalid}}!function(e){e.Discount="Discount",e.Invalid="Invalid"}(G||(G={}));const W={};async function z(e,t){const n=R(e),o=new URL(e).pathname,r=t(n),i=await async function(e,t){const n=W[e];if(n?.length)return n;const o=await fetch(t).then((e=>e.json())).then(_).catch((()=>[]));return W[e]=o,o}(n,r).then(J);let a=null,l=null;for(const e of i)e.urlPattern?new RegExp(e.urlPattern).test(o)&&(l=e):a=e;if(l)return l;if(a)return a;throw new Error(`No config found for ${n}`)}function _(e){const t=e,n=[];for(const e of t.configs){const t=e;t.data&&(t.disabled||n.push({appliedCode:t.data.appliedCode||void 0,applyButton:t.data.applyButton||void 0,applyType:t.data.applyType||void 0,closeModal:t.data.closeModal||void 0,couponInput:t.data.couponInput||void 0,discountAmount:t.data.discountAmount||void 0,domain:t.data.domain||"",error:t.data.error||void 0,loading:t.data.loading||void 0,removeButton:t.data.removeButton||void 0,showFormButton:t.data.showFormButton||void 0,subtotalAmount:t.data.subtotalAmount||void 0,totalAmount:t.data.totalAmount||void 0,urlPattern:t.data.urlPattern||void 0}))}return n}function J(e){return e.sort(((e,t)=>e.urlPattern?t.urlPattern?e.urlPattern.length-t.urlPattern.length:1:-1))}var K,Z,Q;!function(e){e.TryCodes="caa-try-codes",e.Stop="caa-stop",e.GetPageState="caa-get-page-state"}(K||(K={})),function(e){e.CodeTested="caa-code-tested"}(Z||(Z={})),function(e){e.PageLoaded="caa-page-loaded"}(Q||(Q={}));class X{active;testedCodes={};constructor(){this.active=!0}get isActive(){return this.active}stop(){this.active=!1}addTestedCode(e,t){this.testedCodes[e]=t}getTestedCode(e){return this.testedCodes[e]}}function Y(e){return e.code.trim().length&&!/\s/.test(e.code.trim())}const ee={};function te({getUnifiedConfigUrl:e,logger:t=(()=>()=>{})}){O.runtime.onMessage.addListener(((n,o,l)=>{const u=o.tab?.id,s=o.tab?.url;if(void 0!==u)if(r(t(u)),void 0!==s)switch(n.type){case Q.PageLoaded:return void i.info({message:n,tabId:u});case K.Stop:return i.info({message:n,tabId:u}),ee[u]?.stop(),void i.info("stopping CAA for tab"+u);case K.TryCodes:return i.info({message:n,tabId:u}),void async function(e,t,n,{codes:o,cacheDuplicates:r=!1,validateCodes:l=!1,minDelay:u=1e3,config:s}){let c;try{c=s||await z(t,n)}catch(e){return void i.error("Cannot get config for "+t,e)}i.info("starting CAA for tab "+e);const d=new X;ee[e]=d;for(const t of o){if(!d.isActive)break;const n=d.getTestedCode(t.code);if(r&&n){await a(u),await ne(e,{...n,...t});continue}if(l&&!Y(t)){await a(u),await ne(e,{...t,type:G.Invalid});continue}const o=(new Date).getTime(),s=await H(e,t,c);i.perf(t.code+" tested in: ",{code:t.code,timeSpent:(new Date).getTime()-o}),d.addTestedCode(t.code,s),await ne(e,s)}delete ee[e]}(u,s,e,n);case K.GetPageState:return i.info({message:n,tabId:u}),async function(e,t,n,o){let r;if(o)r=o;else try{r=await z(t,n)}catch(e){return void i.error("No config exists for: "+t,e)}const a=await j(e,r);return i.info({pageState:a,tabId:e}),a}(u,s,e,n.config).then(l),!0}else i.error("No tabUrl provided for "+u);else console.error("No tabId provided")}))}async function ne(e,t){i.info({code:t,info:"sending tried code",tabId:e});const n={code:t,type:Z.CodeTested};let o=!1;for(let r=0;r<10;r++){try{await oe(e),o=await O.tabs.sendMessage(e,n)}catch(n){i.info({code:t,info:"Tried code not received by the tab.",tabId:e})}if(o)break;await a(200)}if(!o)throw new Error(`Cannot send tried code to the browser tab. code: ${t.code} , tabId: ${e}`)}async function oe(e){let t=10;for(;t--;){if("complete"===(await O.tabs.get(e)).status)return;await a(100)}}module.exports=n})(); |
@@ -13,3 +13,3 @@ { | ||
"types": "dist/index.d.ts", | ||
"version": "4.0.3" | ||
"version": "4.0.4" | ||
} |
Sorry, the diff of this file is not supported yet
50810
56
361