Make d3-geoPath with a different fillStyle in svelte-canvas

Actually the basic are already answered here, but I can’t translate the method if I use svelte-canvas.

<script>
    import { onMount } from 'svelte'
    import { Canvas, Layer } from "svelte-canvas";
    import { feature } from "topojson-client";
    import { geoOrthographic, geoPath, geoGraticule10 } from "d3-geo";
    
    let map, color="red"

    const projection = geoOrthographic(), 
                path = geoPath(projection);
    
    onMount(() => {
        fetch("https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json")
            .then(data => data.json())
            .then(data => {
                map = feature(data, 'countries')
            })
        })
        
    $: graticule = ({ context, width, time }) => {
        projection
            .fitSize([width, width], { type: "Sphere" })
            .rotate([0, -10]);
        
    context.strokeStyle = "#ccc";
    context.beginPath(), path(geoGraticule10()), context.stroke();
  };

  $: globe = ({ context }) => {
    // this set the fill style of all countries,
    // If i use `map.features.forEach` it will lag very much
    // and only set the color based on the last condition
    context.fillStyle = "red";

    // I tried path(map.features[10].geometry...) or similar,
    // but doesn't work, It gives error
    context.beginPath(), path(map), context.fill();
  };
</script>

    <Canvas autoplay>
        <Layer render={bg} />
        <Layer setup={({ context }) => path.context(context)} render={graticule} />
        <Layer render={globe} />
    </Canvas>

what I’ve already tried to do

$: globe = ({ context }) => {
    map.features.forEach(d => {
       if (d.properties.name == "Chile") {
           color = "green"
       } else {
           color = "red"
       }
    })
  
    context.fillStyle = color;
    context.beginPath(), path(map), context.fill();
  };

How does this pop-under js technique work?

The following js code is given openly by an ad company (which I’d rather not name, though it’s not difficult to find). I just formatted it for readability. It is supposed to allow the website owner to display popunder ads.

I want to know how it works, but I’m not a js expert and this is a bit over my head, though I have basic js knowledge. Can someone please break down how it works step by step, when using firefox for example, and explain how it can circumvent adblock filters and browser settings (to block popups) ?

(function() {

    //version 6.0.0
  
    var adConfig = {
      "ads_host": "a.pemsrv.com",
      "syndication_host": "s.pemsrv.com",
      "idzone": 1234567,
      "popup_fallback": false,
      "popup_force": false,
      "chrome_enabled": true,
      "new_tab": false,
      "frequency_period": 1,
      "frequency_count": 1,
      "trigger_method": 3,
      "trigger_class": "",
      "trigger_delay": 0,
      "capping_enabled": true,
      "tcf_enabled": true,
      "only_inline": false,
      "tags": "cartoon"
    };
  
    window.document.querySelectorAll || (document.querySelectorAll = document.body.querySelectorAll = Object.querySelectorAll = function(e, o, t, i, n) {
      var r = document,
        a = r.createStyleSheet();
      for (n = r.all, o = [], t = (e = e.replace(/[forb/gi, "[htmlFor").split(",")).length; t--;) {
        for (a.addRule(e[t], "k:v"), i = n.length; i--;) n[i].currentStyle.k && o.push(n[i]);
        a.removeRule(0)
      }
      return o
    });
    var popMagic = {
      version: 6,
      cookie_name: "",
      url: "",
      config: {},
      open_count: 0,
      top: null,
      browser: null,
      venor_loaded: !1,
      venor: !1,
      tcfData: null,
      configTpl: {
        ads_host: "",
        syndication_host: "",
        idzone: "",
        frequency_period: 720,
        frequency_count: 1,
        trigger_method: 1,
        trigger_class: "",
        popup_force: !1,
        popup_fallback: !1,
        chrome_enabled: !0,
        new_tab: !1,
        cat: "",
        tags: "",
        el: "",
        sub: "",
        sub2: "",
        sub3: "",
        only_inline: !1,
        trigger_delay: 0,
        capping_enabled: !0,
        tcf_enabled: !1,
        cookieconsent: !0,
        should_fire: function() {
          return !0
        }
      },
      init: function(e) {
        if (void 0 !== e.idzone && e.idzone) {
          void 0 === e.customTargeting && (e.customTargeting = []), window.customTargeting = e.customTargeting || null;
          var o = Object.keys(e.customTargeting).filter((function(e) {
            return e.search("ex_") >= 0
          }));
          for (var t in o.length && o.forEach(function(e) {
              return this.configTpl[e] = null
            }.bind(this)), this.configTpl) Object.prototype.hasOwnProperty.call(this.configTpl, t) && (void 0 !== e[t] ? this.config[t] = e[t] : this.config[t] = this.configTpl[t]);
          if (void 0 !== this.config.idzone && "" !== this.config.idzone) {
            !0 !== this.config.only_inline && this.loadHosted();
            var i = this;
            this.checkTCFConsent((function() {
              "complete" === document.readyState ? i.preparePopWait() : i.addEventToElement(window, "load", i.preparePop)
            }))
          }
        }
      },
      getCountFromCookie: function() {
        if (!this.config.cookieconsent) return 0;
        var e = popMagic.getCookie(popMagic.cookie_name),
          o = void 0 === e ? 0 : parseInt(e);
        return isNaN(o) && (o = 0), o
      },
      getLastOpenedTimeFromCookie: function() {
        var e = popMagic.getCookie(popMagic.cookie_name),
          o = null;
        if (void 0 !== e) {
          var t = e.split(";")[1];
          o = t > 0 ? parseInt(t) : 0
        }
        return isNaN(o) && (o = null), o
      },
      shouldShow: function() {
        if (!popMagic.config.capping_enabled) {
          var e = !0,
            o = popMagic.config.should_fire;
          try {
            "function" == typeof o && (e = Boolean(o()))
          } catch (e) {
            console.error("Error executing should fire callback function:", e)
          }
          return e && 0 === popMagic.open_count
        }
        if (popMagic.open_count >= popMagic.config.frequency_count) return !1;
        var t = popMagic.getCountFromCookie(),
          i = popMagic.getLastOpenedTimeFromCookie(),
          n = Math.floor(Date.now() / 1e3),
          r = i + popMagic.config.trigger_delay;
        return !(i && r > n) && (popMagic.open_count = t, !(t >= popMagic.config.frequency_count))
      },
      venorShouldShow: function() {
        return popMagic.venor_loaded && "0" === popMagic.venor
      },
      setAsOpened: function(e) {
        var o = e ? e.target || e.srcElement : null,
          t = {
            id: "",
            tagName: "",
            classes: "",
            text: "",
            href: "",
            elm: ""
          };
        void 0 !== o && null != o && (t = {
          id: void 0 !== o.id && null != o.id ? o.id : "",
          tagName: void 0 !== o.tagName && null != o.tagName ? o.tagName : "",
          classes: void 0 !== o.classList && null != o.classList ? o.classList : "",
          text: void 0 !== o.outerText && null != o.outerText ? o.outerText : "",
          href: void 0 !== o.href && null != o.href ? o.href : "",
          elm: o
        });
        var i = new CustomEvent("creativeDisplayed-" + popMagic.config.idzone, {
          detail: t
        });
        if (document.dispatchEvent(i), popMagic.config.capping_enabled) {
          var n = 1;
          n = 0 !== popMagic.open_count ? popMagic.open_count + 1 : popMagic.getCountFromCookie() + 1;
          var r = Math.floor(Date.now() / 1e3);
          popMagic.config.cookieconsent && popMagic.setCookie(popMagic.cookie_name, n + ";" + r, popMagic.config.frequency_period)
        } else ++popMagic.open_count
      },
      loadHosted: function() {
        var e = document.createElement("script");
        for (var o in e.type = "application/javascript", e.async = !0, e.src = "//" + this.config.ads_host + "/popunder1000.js", e.id = "popmagicldr", this.config) Object.prototype.hasOwnProperty.call(this.config, o) && "ads_host" !== o && "syndication_host" !== o && e.setAttribute("data-exo-" + o, this.config[o]);
        var t = document.getElementsByTagName("body").item(0);
        t.firstChild ? t.insertBefore(e, t.firstChild) : t.appendChild(e)
      },
      preparePopWait: function() {
        setTimeout(popMagic.preparePop, 400)
      },
      preparePop: function() {
        if ("object" != typeof exoJsPop101 || !Object.prototype.hasOwnProperty.call(exoJsPop101, "add")) {
          if (popMagic.top = self, popMagic.top !== self) try {
            top.document.location.toString() && (popMagic.top = top)
          } catch (e) {}
          if (popMagic.cookie_name = "zone-cap-" + popMagic.config.idzone, popMagic.config.capping_enabled || (document.cookie = popMagic.cookie_name + "=;expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/"), popMagic.shouldShow()) {
            var e = new XMLHttpRequest;
            e.onreadystatechange = function() {
              e.readyState == XMLHttpRequest.DONE && (popMagic.venor_loaded = !0, 200 == e.status ? popMagic.venor = e.responseText : popMagic.venor = "0")
            };
            var o = "https:" !== document.location.protocol && "http:" !== document.location.protocol ? "https:" : document.location.protocol;
            e.open("GET", o + "//" + popMagic.config.syndication_host + "/venor.php", !0);
            try {
              e.send()
            } catch (e) {
              popMagic.venor_loaded = !0
            }
          }
          if (popMagic.buildUrl(), popMagic.browser = popMagic.browserDetector.getBrowserInfo(), popMagic.config.chrome_enabled || !popMagic.browser.isChrome) {
            var t = popMagic.getPopMethod(popMagic.browser);
            popMagic.addEvent("click", t)
          }
        }
      },
      getPopMethod: function(e) {
        return popMagic.config.popup_force || popMagic.config.popup_fallback && e.isChrome && e.version >= 68 && !e.isMobile ? popMagic.methods.popup : e.isMobile ? popMagic.methods.default : e.isChrome ? popMagic.methods.chromeTab : popMagic.methods.default
      },
      checkTCFConsent: function(e) {
        if (this.config.tcf_enabled && "function" == typeof window.__tcfapi) {
          var o = this;
          window.__tcfapi("addEventListener", 2, (function(t, i) {
            i && (o.tcfData = t, "tcloaded" !== t.eventStatus && "useractioncomplete" !== t.eventStatus || (window.__tcfapi("removeEventListener", 2, (function() {}), t.listenerId), e()))
          }))
        } else e()
      },
      buildUrl: function() {
        var e, o = "https:" !== document.location.protocol && "http:" !== document.location.protocol ? "https:" : document.location.protocol,
          t = top === self ? document.URL : document.referrer,
          i = {
            type: "inline",
            name: "popMagic",
            ver: this.version
          },
          n = "";
        customTargeting && Object.keys(customTargeting).length && ("object" == typeof customTargeting ? Object.keys(customTargeting) : customTargeting).forEach((function(o) {
          "object" == typeof customTargeting ? e = customTargeting[o] : Array.isArray(customTargeting) && (e = scriptEl.getAttribute(o));
          var t = o.replace("data-exo-", "");
          n += "&" + t + "=" + e
        }));
        var r = this.tcfData && this.tcfData.gdprApplies && !0 === this.tcfData.gdprApplies ? 1 : 0;
        this.url = o + "//" + this.config.syndication_host + "/v1/link.php?cat=" + this.config.cat + "&idzone=" + this.config.idzone + "&type=8&p=" + encodeURIComponent(t) + "&sub=" + this.config.sub + ("" !== this.config.sub2 ? "&sub2=" + this.config.sub2 : "") + ("" !== this.config.sub3 ? "&sub3=" + this.config.sub3 : "") + "&block=1&el=" + this.config.el + "&tags=" + this.config.tags + "&scr_info=" + function(e) {
          var o = e.type + "|" + e.name + "|" + e.ver;
          return encodeURIComponent(btoa(o))
        }(i) + n + "&gdpr=" + r + "&cb=" + Math.floor(1e9 * Math.random()), this.tcfData && this.tcfData.tcString ? this.url += "&gdpr_consent=" + encodeURIComponent(this.tcfData.tcString) : this.url += "&cookieconsent=" + this.config.cookieconsent
      },
      addEventToElement: function(e, o, t) {
        e.addEventListener ? e.addEventListener(o, t, !1) : e.attachEvent ? (e["e" + o + t] = t, e[o + t] = function() {
          e["e" + o + t](window.event)
        }, e.attachEvent("on" + o, e[o + t])) : e["on" + o] = e["e" + o + t]
      },
      getTriggerClasses: function() {
        var e, o = []; - 1 === popMagic.config.trigger_class.indexOf(",") ? e = popMagic.config.trigger_class.split(" ") : e = popMagic.config.trigger_class.replace(/s/g, "").split(",");
        for (var t = 0; t < e.length; t++) "" !== e[t] && o.push("." + e[t]);
        return o
      },
      addEvent: function(e, o) {
        var t;
        if ("3" != popMagic.config.trigger_method)
          if ("2" != popMagic.config.trigger_method || "" == popMagic.config.trigger_method)
            if ("4" != popMagic.config.trigger_method || "" == popMagic.config.trigger_method) popMagic.addEventToElement(document, e, o);
            else {
              var n = popMagic.getTriggerClasses();
              popMagic.addEventToElement(document, e, (function(e) {
                n.some((function(o) {
                  return null !== e.target.closest(o)
                })) || o.call(e.target, e)
              }))
            }
        else {
          var r = popMagic.getTriggerClasses();
          for (t = document.querySelectorAll(r.join(", ")), i = 0; i < t.length; i++) popMagic.addEventToElement(t[i], e, o)
        } else
          for (t = document.querySelectorAll("a"), i = 0; i < t.length; i++) popMagic.addEventToElement(t[i], e, o)
      },
      setCookie: function(e, o, t) {
        if (!this.config.cookieconsent) return !1;
        t = parseInt(t, 10);
        var i = new Date;
        i.setMinutes(i.getMinutes() + parseInt(t));
        var n = encodeURIComponent(o) + "; expires=" + i.toUTCString() + "; path=/";
        document.cookie = e + "=" + n
      },
      getCookie: function(e) {
        if (!this.config.cookieconsent) return !1;
        var o, t, i, n = document.cookie.split(";");
        for (o = 0; o < n.length; o++)
          if (t = n[o].substr(0, n[o].indexOf("=")), i = n[o].substr(n[o].indexOf("=") + 1), (t = t.replace(/^s+|s+$/g, "")) === e) return decodeURIComponent(i)
      },
      randStr: function(e, o) {
        for (var t = "", i = o || "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", n = 0; n < e; n++) t += i.charAt(Math.floor(Math.random() * i.length));
        return t
      },
      isValidUserEvent: function(e) {
        return !(!("isTrusted" in e) || !e.isTrusted || "ie" === popMagic.browser.name || "safari" === popMagic.browser.name) || 0 != e.screenX && 0 != e.screenY
      },
      isValidHref: function(e) {
        if (void 0 === e || "" == e) return !1;
        return !/s?javascripts?:/i.test(e)
      },
      findLinkToOpen: function(e) {
        var o = e,
          t = !1;
        try {
          for (var i = 0; i < 20 && !o.getAttribute("href") && o !== document && "html" !== o.nodeName.toLowerCase();) o = o.parentNode, i++;
          var n = o.getAttribute("target");
          n && -1 !== n.indexOf("_blank") || (t = o.getAttribute("href"))
        } catch (e) {}
        return popMagic.isValidHref(t) || (t = !1), t || window.location.href
      },
      getPuId: function() {
        return "ok_" + Math.floor(89999999 * Math.random() + 1e7)
      },
      browserDetector: {
        browserDefinitions: [
          ["firefox", /Firefox/([0-9.]+)(?:s|$)/],
          ["opera", /Opera/([0-9.]+)(?:s|$)/],
          ["opera", /OPR/([0-9.]+)(:?s|$)$/],
          ["edge", /Edg(?:e|)/([0-9._]+)/],
          ["ie", /Trident/7.0.*rv:([0-9.]+)).*Gecko$/],
          ["ie", /MSIEs([0-9.]+);.*Trident/[4-7].0/],
          ["ie", /MSIEs(7.0)/],
          ["safari", /Version/([0-9._]+).*Safari/],
          ["chrome", /(?!Chrom.*Edg(?:e|))Chrom(?:e|ium)/([0-9.]+)(:?s|$)/],
          ["chrome", /(?!Chrom.*OPR)Chrom(?:e|ium)/([0-9.]+)(:?s|$)/],
          ["bb10", /BB10;sTouch.*Version/([0-9.]+)/],
          ["android", /Androids([0-9.]+)/],
          ["ios", /Version/([0-9._]+).*Mobile.*Safari.*/],
          ["yandexbrowser", /YaBrowser/([0-9._]+)/],
          ["crios", /CriOS/([0-9.]+)(:?s|$)/]
        ],
        isChromeOrChromium: function() {
          var e = window.navigator,
            o = (e.userAgent || "").toLowerCase(),
            t = e.vendor || "";
          if (-1 !== o.indexOf("crios")) return !0;
          if (e.userAgentData && Array.isArray(e.userAgentData.brands) && e.userAgentData.brands.length > 0) {
            var i = e.userAgentData.brands,
              n = i.some((function(e) {
                return "Google Chrome" === e.brand
              })),
              r = i.some((function(e) {
                return "Chromium" === e.brand
              })) && 2 === i.length;
            return n || r
          }
          var a = !!window.chrome,
            c = -1 !== o.indexOf("edg"),
            p = !!window.opr || -1 !== o.indexOf("opr"),
            s = !(!e.brave || !e.brave.isBrave),
            g = -1 !== o.indexOf("vivaldi"),
            l = -1 !== o.indexOf("yabrowser"),
            d = -1 !== o.indexOf("samsungbrowser"),
            u = -1 !== o.indexOf("ucbrowser");
          return a && "Google Inc." === t && !c && !p && !s && !g && !l && !d && !u
        },
        getBrowserInfo: function() {
          var e = window.navigator.userAgent,
            o = {
              name: "other",
              version: "1.0",
              versionNumber: 1,
              isChrome: this.isChromeOrChromium(),
              isMobile: !!e.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile|WebOS|Windows Phone/i)
            };
          for (var t in this.browserDefinitions) {
            var i = this.browserDefinitions[t];
            if (i[1].test(e)) {
              var n = i[1].exec(e),
                r = n && n[1].split(/[._]/).slice(0, 3),
                a = Array.prototype.slice.call(r, 1).join("") || "0";
              r && r.length < 3 && Array.prototype.push.apply(r, 1 === r.length ? [0, 0] : [0]), o.name = i[0], o.version = r.join("."), o.versionNumber = parseFloat(r[0] + "." + a);
              break
            }
          }
          return o
        }
      },
      methods: {
        default: function(e) {
          if (!popMagic.shouldShow() || !popMagic.venorShouldShow() || !popMagic.isValidUserEvent(e)) return !0;
          var o = e.target || e.srcElement,
            t = popMagic.findLinkToOpen(o);
          return window.open(t, "_blank"), popMagic.setAsOpened(e), popMagic.top.document.location = popMagic.url, void 0 !== e.preventDefault && (e.preventDefault(), e.stopPropagation()), !0
        },
        chromeTab: function(e) {
          if (!popMagic.shouldShow() || !popMagic.venorShouldShow() || !popMagic.isValidUserEvent(e)) return !0;
          if (void 0 === e.preventDefault) return !0;
          e.preventDefault(), e.stopPropagation();
          var o = top.window.document.createElement("a"),
            t = e.target || e.srcElement;
          o.href = popMagic.findLinkToOpen(t), document.getElementsByTagName("body")[0].appendChild(o);
          var i = new MouseEvent("click", {
            bubbles: !0,
            cancelable: !0,
            view: window,
            screenX: 0,
            screenY: 0,
            clientX: 0,
            clientY: 0,
            ctrlKey: !0,
            altKey: !1,
            shiftKey: !1,
            metaKey: !0,
            button: 0
          });
          i.preventDefault = void 0, o.dispatchEvent(i), o.parentNode.removeChild(o), window.open(popMagic.url, "_self"), popMagic.setAsOpened(e)
        },
        popup: function(e) {
          if (!popMagic.shouldShow() || !popMagic.venorShouldShow() || !popMagic.isValidUserEvent(e)) return !0;
          var o = "";
          if (popMagic.config.popup_fallback && !popMagic.config.popup_force) {
            var t = Math.max(Math.round(.8 * window.innerHeight), 300);
            o = "menubar=1,resizable=1,width=" + Math.max(Math.round(.7 * window.innerWidth), 300) + ",height=" + t + ",top=" + (window.screenY + 100) + ",left=" + (window.screenX + 100)
          }
          var i = document.location.href,
            n = window.open(i, popMagic.getPuId(), o);
          setTimeout((function() {
            n.location.href = popMagic.url
          }), 200), popMagic.setAsOpened(e), void 0 !== e.preventDefault && (e.preventDefault(), e.stopPropagation())
        }
      }
    };
    popMagic.init(adConfig);
  })();

How does this popunder technique work and how to prevent it?

The following js code is given openly by an ad company (which I’d rather not name, though it’s not difficult to find). I just formatted it for readability. It is supposed to allow the website owner to display popunder ads.

I want to know how it works, but I’m not a js expert and this is a bit over my head, though I have basic js knowledge. Can someone please break down how it works step by step, when using firefox for example, and explain how it can circumvent adblock filters and browser settings (to block popups) ?

From the user point of view, is it possible, using a browser extension (adblock, …), or native settings, to block such popunders, or does it use a bug in the browsers that need fixing at the browser level, or is it just the web protocols that currently allow such behavior ?

(function() {

    //version 6.0.0
  
    var adConfig = {
      "ads_host": "a.pemsrv.com",
      "syndication_host": "s.pemsrv.com",
      "idzone": 1234567,
      "popup_fallback": false,
      "popup_force": false,
      "chrome_enabled": true,
      "new_tab": false,
      "frequency_period": 1,
      "frequency_count": 1,
      "trigger_method": 3,
      "trigger_class": "",
      "trigger_delay": 0,
      "capping_enabled": true,
      "tcf_enabled": true,
      "only_inline": false,
      "tags": "cartoon"
    };
  
    window.document.querySelectorAll || (document.querySelectorAll = document.body.querySelectorAll = Object.querySelectorAll = function(e, o, t, i, n) {
      var r = document,
        a = r.createStyleSheet();
      for (n = r.all, o = [], t = (e = e.replace(/[forb/gi, "[htmlFor").split(",")).length; t--;) {
        for (a.addRule(e[t], "k:v"), i = n.length; i--;) n[i].currentStyle.k && o.push(n[i]);
        a.removeRule(0)
      }
      return o
    });
    var popMagic = {
      version: 6,
      cookie_name: "",
      url: "",
      config: {},
      open_count: 0,
      top: null,
      browser: null,
      venor_loaded: !1,
      venor: !1,
      tcfData: null,
      configTpl: {
        ads_host: "",
        syndication_host: "",
        idzone: "",
        frequency_period: 720,
        frequency_count: 1,
        trigger_method: 1,
        trigger_class: "",
        popup_force: !1,
        popup_fallback: !1,
        chrome_enabled: !0,
        new_tab: !1,
        cat: "",
        tags: "",
        el: "",
        sub: "",
        sub2: "",
        sub3: "",
        only_inline: !1,
        trigger_delay: 0,
        capping_enabled: !0,
        tcf_enabled: !1,
        cookieconsent: !0,
        should_fire: function() {
          return !0
        }
      },
      init: function(e) {
        if (void 0 !== e.idzone && e.idzone) {
          void 0 === e.customTargeting && (e.customTargeting = []), window.customTargeting = e.customTargeting || null;
          var o = Object.keys(e.customTargeting).filter((function(e) {
            return e.search("ex_") >= 0
          }));
          for (var t in o.length && o.forEach(function(e) {
              return this.configTpl[e] = null
            }.bind(this)), this.configTpl) Object.prototype.hasOwnProperty.call(this.configTpl, t) && (void 0 !== e[t] ? this.config[t] = e[t] : this.config[t] = this.configTpl[t]);
          if (void 0 !== this.config.idzone && "" !== this.config.idzone) {
            !0 !== this.config.only_inline && this.loadHosted();
            var i = this;
            this.checkTCFConsent((function() {
              "complete" === document.readyState ? i.preparePopWait() : i.addEventToElement(window, "load", i.preparePop)
            }))
          }
        }
      },
      getCountFromCookie: function() {
        if (!this.config.cookieconsent) return 0;
        var e = popMagic.getCookie(popMagic.cookie_name),
          o = void 0 === e ? 0 : parseInt(e);
        return isNaN(o) && (o = 0), o
      },
      getLastOpenedTimeFromCookie: function() {
        var e = popMagic.getCookie(popMagic.cookie_name),
          o = null;
        if (void 0 !== e) {
          var t = e.split(";")[1];
          o = t > 0 ? parseInt(t) : 0
        }
        return isNaN(o) && (o = null), o
      },
      shouldShow: function() {
        if (!popMagic.config.capping_enabled) {
          var e = !0,
            o = popMagic.config.should_fire;
          try {
            "function" == typeof o && (e = Boolean(o()))
          } catch (e) {
            console.error("Error executing should fire callback function:", e)
          }
          return e && 0 === popMagic.open_count
        }
        if (popMagic.open_count >= popMagic.config.frequency_count) return !1;
        var t = popMagic.getCountFromCookie(),
          i = popMagic.getLastOpenedTimeFromCookie(),
          n = Math.floor(Date.now() / 1e3),
          r = i + popMagic.config.trigger_delay;
        return !(i && r > n) && (popMagic.open_count = t, !(t >= popMagic.config.frequency_count))
      },
      venorShouldShow: function() {
        return popMagic.venor_loaded && "0" === popMagic.venor
      },
      setAsOpened: function(e) {
        var o = e ? e.target || e.srcElement : null,
          t = {
            id: "",
            tagName: "",
            classes: "",
            text: "",
            href: "",
            elm: ""
          };
        void 0 !== o && null != o && (t = {
          id: void 0 !== o.id && null != o.id ? o.id : "",
          tagName: void 0 !== o.tagName && null != o.tagName ? o.tagName : "",
          classes: void 0 !== o.classList && null != o.classList ? o.classList : "",
          text: void 0 !== o.outerText && null != o.outerText ? o.outerText : "",
          href: void 0 !== o.href && null != o.href ? o.href : "",
          elm: o
        });
        var i = new CustomEvent("creativeDisplayed-" + popMagic.config.idzone, {
          detail: t
        });
        if (document.dispatchEvent(i), popMagic.config.capping_enabled) {
          var n = 1;
          n = 0 !== popMagic.open_count ? popMagic.open_count + 1 : popMagic.getCountFromCookie() + 1;
          var r = Math.floor(Date.now() / 1e3);
          popMagic.config.cookieconsent && popMagic.setCookie(popMagic.cookie_name, n + ";" + r, popMagic.config.frequency_period)
        } else ++popMagic.open_count
      },
      loadHosted: function() {
        var e = document.createElement("script");
        for (var o in e.type = "application/javascript", e.async = !0, e.src = "//" + this.config.ads_host + "/popunder1000.js", e.id = "popmagicldr", this.config) Object.prototype.hasOwnProperty.call(this.config, o) && "ads_host" !== o && "syndication_host" !== o && e.setAttribute("data-exo-" + o, this.config[o]);
        var t = document.getElementsByTagName("body").item(0);
        t.firstChild ? t.insertBefore(e, t.firstChild) : t.appendChild(e)
      },
      preparePopWait: function() {
        setTimeout(popMagic.preparePop, 400)
      },
      preparePop: function() {
        if ("object" != typeof exoJsPop101 || !Object.prototype.hasOwnProperty.call(exoJsPop101, "add")) {
          if (popMagic.top = self, popMagic.top !== self) try {
            top.document.location.toString() && (popMagic.top = top)
          } catch (e) {}
          if (popMagic.cookie_name = "zone-cap-" + popMagic.config.idzone, popMagic.config.capping_enabled || (document.cookie = popMagic.cookie_name + "=;expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/"), popMagic.shouldShow()) {
            var e = new XMLHttpRequest;
            e.onreadystatechange = function() {
              e.readyState == XMLHttpRequest.DONE && (popMagic.venor_loaded = !0, 200 == e.status ? popMagic.venor = e.responseText : popMagic.venor = "0")
            };
            var o = "https:" !== document.location.protocol && "http:" !== document.location.protocol ? "https:" : document.location.protocol;
            e.open("GET", o + "//" + popMagic.config.syndication_host + "/venor.php", !0);
            try {
              e.send()
            } catch (e) {
              popMagic.venor_loaded = !0
            }
          }
          if (popMagic.buildUrl(), popMagic.browser = popMagic.browserDetector.getBrowserInfo(), popMagic.config.chrome_enabled || !popMagic.browser.isChrome) {
            var t = popMagic.getPopMethod(popMagic.browser);
            popMagic.addEvent("click", t)
          }
        }
      },
      getPopMethod: function(e) {
        return popMagic.config.popup_force || popMagic.config.popup_fallback && e.isChrome && e.version >= 68 && !e.isMobile ? popMagic.methods.popup : e.isMobile ? popMagic.methods.default : e.isChrome ? popMagic.methods.chromeTab : popMagic.methods.default
      },
      checkTCFConsent: function(e) {
        if (this.config.tcf_enabled && "function" == typeof window.__tcfapi) {
          var o = this;
          window.__tcfapi("addEventListener", 2, (function(t, i) {
            i && (o.tcfData = t, "tcloaded" !== t.eventStatus && "useractioncomplete" !== t.eventStatus || (window.__tcfapi("removeEventListener", 2, (function() {}), t.listenerId), e()))
          }))
        } else e()
      },
      buildUrl: function() {
        var e, o = "https:" !== document.location.protocol && "http:" !== document.location.protocol ? "https:" : document.location.protocol,
          t = top === self ? document.URL : document.referrer,
          i = {
            type: "inline",
            name: "popMagic",
            ver: this.version
          },
          n = "";
        customTargeting && Object.keys(customTargeting).length && ("object" == typeof customTargeting ? Object.keys(customTargeting) : customTargeting).forEach((function(o) {
          "object" == typeof customTargeting ? e = customTargeting[o] : Array.isArray(customTargeting) && (e = scriptEl.getAttribute(o));
          var t = o.replace("data-exo-", "");
          n += "&" + t + "=" + e
        }));
        var r = this.tcfData && this.tcfData.gdprApplies && !0 === this.tcfData.gdprApplies ? 1 : 0;
        this.url = o + "//" + this.config.syndication_host + "/v1/link.php?cat=" + this.config.cat + "&idzone=" + this.config.idzone + "&type=8&p=" + encodeURIComponent(t) + "&sub=" + this.config.sub + ("" !== this.config.sub2 ? "&sub2=" + this.config.sub2 : "") + ("" !== this.config.sub3 ? "&sub3=" + this.config.sub3 : "") + "&block=1&el=" + this.config.el + "&tags=" + this.config.tags + "&scr_info=" + function(e) {
          var o = e.type + "|" + e.name + "|" + e.ver;
          return encodeURIComponent(btoa(o))
        }(i) + n + "&gdpr=" + r + "&cb=" + Math.floor(1e9 * Math.random()), this.tcfData && this.tcfData.tcString ? this.url += "&gdpr_consent=" + encodeURIComponent(this.tcfData.tcString) : this.url += "&cookieconsent=" + this.config.cookieconsent
      },
      addEventToElement: function(e, o, t) {
        e.addEventListener ? e.addEventListener(o, t, !1) : e.attachEvent ? (e["e" + o + t] = t, e[o + t] = function() {
          e["e" + o + t](window.event)
        }, e.attachEvent("on" + o, e[o + t])) : e["on" + o] = e["e" + o + t]
      },
      getTriggerClasses: function() {
        var e, o = []; - 1 === popMagic.config.trigger_class.indexOf(",") ? e = popMagic.config.trigger_class.split(" ") : e = popMagic.config.trigger_class.replace(/s/g, "").split(",");
        for (var t = 0; t < e.length; t++) "" !== e[t] && o.push("." + e[t]);
        return o
      },
      addEvent: function(e, o) {
        var t;
        if ("3" != popMagic.config.trigger_method)
          if ("2" != popMagic.config.trigger_method || "" == popMagic.config.trigger_method)
            if ("4" != popMagic.config.trigger_method || "" == popMagic.config.trigger_method) popMagic.addEventToElement(document, e, o);
            else {
              var n = popMagic.getTriggerClasses();
              popMagic.addEventToElement(document, e, (function(e) {
                n.some((function(o) {
                  return null !== e.target.closest(o)
                })) || o.call(e.target, e)
              }))
            }
        else {
          var r = popMagic.getTriggerClasses();
          for (t = document.querySelectorAll(r.join(", ")), i = 0; i < t.length; i++) popMagic.addEventToElement(t[i], e, o)
        } else
          for (t = document.querySelectorAll("a"), i = 0; i < t.length; i++) popMagic.addEventToElement(t[i], e, o)
      },
      setCookie: function(e, o, t) {
        if (!this.config.cookieconsent) return !1;
        t = parseInt(t, 10);
        var i = new Date;
        i.setMinutes(i.getMinutes() + parseInt(t));
        var n = encodeURIComponent(o) + "; expires=" + i.toUTCString() + "; path=/";
        document.cookie = e + "=" + n
      },
      getCookie: function(e) {
        if (!this.config.cookieconsent) return !1;
        var o, t, i, n = document.cookie.split(";");
        for (o = 0; o < n.length; o++)
          if (t = n[o].substr(0, n[o].indexOf("=")), i = n[o].substr(n[o].indexOf("=") + 1), (t = t.replace(/^s+|s+$/g, "")) === e) return decodeURIComponent(i)
      },
      randStr: function(e, o) {
        for (var t = "", i = o || "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", n = 0; n < e; n++) t += i.charAt(Math.floor(Math.random() * i.length));
        return t
      },
      isValidUserEvent: function(e) {
        return !(!("isTrusted" in e) || !e.isTrusted || "ie" === popMagic.browser.name || "safari" === popMagic.browser.name) || 0 != e.screenX && 0 != e.screenY
      },
      isValidHref: function(e) {
        if (void 0 === e || "" == e) return !1;
        return !/s?javascripts?:/i.test(e)
      },
      findLinkToOpen: function(e) {
        var o = e,
          t = !1;
        try {
          for (var i = 0; i < 20 && !o.getAttribute("href") && o !== document && "html" !== o.nodeName.toLowerCase();) o = o.parentNode, i++;
          var n = o.getAttribute("target");
          n && -1 !== n.indexOf("_blank") || (t = o.getAttribute("href"))
        } catch (e) {}
        return popMagic.isValidHref(t) || (t = !1), t || window.location.href
      },
      getPuId: function() {
        return "ok_" + Math.floor(89999999 * Math.random() + 1e7)
      },
      browserDetector: {
        browserDefinitions: [
          ["firefox", /Firefox/([0-9.]+)(?:s|$)/],
          ["opera", /Opera/([0-9.]+)(?:s|$)/],
          ["opera", /OPR/([0-9.]+)(:?s|$)$/],
          ["edge", /Edg(?:e|)/([0-9._]+)/],
          ["ie", /Trident/7.0.*rv:([0-9.]+)).*Gecko$/],
          ["ie", /MSIEs([0-9.]+);.*Trident/[4-7].0/],
          ["ie", /MSIEs(7.0)/],
          ["safari", /Version/([0-9._]+).*Safari/],
          ["chrome", /(?!Chrom.*Edg(?:e|))Chrom(?:e|ium)/([0-9.]+)(:?s|$)/],
          ["chrome", /(?!Chrom.*OPR)Chrom(?:e|ium)/([0-9.]+)(:?s|$)/],
          ["bb10", /BB10;sTouch.*Version/([0-9.]+)/],
          ["android", /Androids([0-9.]+)/],
          ["ios", /Version/([0-9._]+).*Mobile.*Safari.*/],
          ["yandexbrowser", /YaBrowser/([0-9._]+)/],
          ["crios", /CriOS/([0-9.]+)(:?s|$)/]
        ],
        isChromeOrChromium: function() {
          var e = window.navigator,
            o = (e.userAgent || "").toLowerCase(),
            t = e.vendor || "";
          if (-1 !== o.indexOf("crios")) return !0;
          if (e.userAgentData && Array.isArray(e.userAgentData.brands) && e.userAgentData.brands.length > 0) {
            var i = e.userAgentData.brands,
              n = i.some((function(e) {
                return "Google Chrome" === e.brand
              })),
              r = i.some((function(e) {
                return "Chromium" === e.brand
              })) && 2 === i.length;
            return n || r
          }
          var a = !!window.chrome,
            c = -1 !== o.indexOf("edg"),
            p = !!window.opr || -1 !== o.indexOf("opr"),
            s = !(!e.brave || !e.brave.isBrave),
            g = -1 !== o.indexOf("vivaldi"),
            l = -1 !== o.indexOf("yabrowser"),
            d = -1 !== o.indexOf("samsungbrowser"),
            u = -1 !== o.indexOf("ucbrowser");
          return a && "Google Inc." === t && !c && !p && !s && !g && !l && !d && !u
        },
        getBrowserInfo: function() {
          var e = window.navigator.userAgent,
            o = {
              name: "other",
              version: "1.0",
              versionNumber: 1,
              isChrome: this.isChromeOrChromium(),
              isMobile: !!e.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile|WebOS|Windows Phone/i)
            };
          for (var t in this.browserDefinitions) {
            var i = this.browserDefinitions[t];
            if (i[1].test(e)) {
              var n = i[1].exec(e),
                r = n && n[1].split(/[._]/).slice(0, 3),
                a = Array.prototype.slice.call(r, 1).join("") || "0";
              r && r.length < 3 && Array.prototype.push.apply(r, 1 === r.length ? [0, 0] : [0]), o.name = i[0], o.version = r.join("."), o.versionNumber = parseFloat(r[0] + "." + a);
              break
            }
          }
          return o
        }
      },
      methods: {
        default: function(e) {
          if (!popMagic.shouldShow() || !popMagic.venorShouldShow() || !popMagic.isValidUserEvent(e)) return !0;
          var o = e.target || e.srcElement,
            t = popMagic.findLinkToOpen(o);
          return window.open(t, "_blank"), popMagic.setAsOpened(e), popMagic.top.document.location = popMagic.url, void 0 !== e.preventDefault && (e.preventDefault(), e.stopPropagation()), !0
        },
        chromeTab: function(e) {
          if (!popMagic.shouldShow() || !popMagic.venorShouldShow() || !popMagic.isValidUserEvent(e)) return !0;
          if (void 0 === e.preventDefault) return !0;
          e.preventDefault(), e.stopPropagation();
          var o = top.window.document.createElement("a"),
            t = e.target || e.srcElement;
          o.href = popMagic.findLinkToOpen(t), document.getElementsByTagName("body")[0].appendChild(o);
          var i = new MouseEvent("click", {
            bubbles: !0,
            cancelable: !0,
            view: window,
            screenX: 0,
            screenY: 0,
            clientX: 0,
            clientY: 0,
            ctrlKey: !0,
            altKey: !1,
            shiftKey: !1,
            metaKey: !0,
            button: 0
          });
          i.preventDefault = void 0, o.dispatchEvent(i), o.parentNode.removeChild(o), window.open(popMagic.url, "_self"), popMagic.setAsOpened(e)
        },
        popup: function(e) {
          if (!popMagic.shouldShow() || !popMagic.venorShouldShow() || !popMagic.isValidUserEvent(e)) return !0;
          var o = "";
          if (popMagic.config.popup_fallback && !popMagic.config.popup_force) {
            var t = Math.max(Math.round(.8 * window.innerHeight), 300);
            o = "menubar=1,resizable=1,width=" + Math.max(Math.round(.7 * window.innerWidth), 300) + ",height=" + t + ",top=" + (window.screenY + 100) + ",left=" + (window.screenX + 100)
          }
          var i = document.location.href,
            n = window.open(i, popMagic.getPuId(), o);
          setTimeout((function() {
            n.location.href = popMagic.url
          }), 200), popMagic.setAsOpened(e), void 0 !== e.preventDefault && (e.preventDefault(), e.stopPropagation())
        }
      }
    };
    popMagic.init(adConfig);
  })();

tanstack table selected rows incorrect order after sorting table by col

I have a react.js Table.js file which uses TanStack table. I need it to do three things:

  1. allow drag-and-drop row reordering
  2. allow column sort toggling (ascending/descending)
  3. always retrieve 100% accurate order selected rows

https://codesandbox.io/p/devbox/row-reorder-working-forked-2dm95l?workspaceId=ws_F2QxELJDBKDDSAxdPEPbQt

Currently, 1. and 2. both work, but the selected row order is always incorrect if the table has been sorted by a col header.

Here is a visual example of the working row drag & drop:
enter image description here

But when I click a col header to sort the table as ascending/descending:
enter image description here

Now the ‘selected rows’ output is not accurate
enter image description here

How can I fix my Table.js file from my codeandbox so that I can print an accurate table row order even when a col sort is toggled on?

How to stream PCM audio from AWS Bedrock Nova Sonic to a web browser without noise artifacts?

I’m building a voice assistant application using AWS Bedrock’s Nova Sonic API. I have two implementations:

A Streamlit app that works perfectly using PyAudio to play the PCM audio chunks directly:

async def play_audio(self):
"""Play audio responses."""
p = pyaudio.PyAudio()
stream = p.open(
    format=FORMAT,
    channels=CHANNELS,
    rate=OUTPUT_SAMPLE_RATE,
    output=True
)

try:
    while self.is_active:
        audio_data = await self.audio_queue.get()
        stream.write(audio_data)
except Exception as e:
    print(f"Error playing audio: {e}")
finally:
    stream.stop_stream()
    stream.close()
    p.terminate()

A web application using Flask-SocketIO to stream audio to a browser. Here’s my backend code:

elif 'audioOutput' in json_data['event']:
audio_content = json_data['event']['audioOutput']['content']
pcm_bytes = base64.b64decode(audio_content)

# Convert to WAV with proper headers
wav_buffer = io.BytesIO()
with wave.open(wav_buffer, 'wb') as wf:
    wf.setnchannels(1)
    wf.setsampwidth(2)
    wf.setframerate(24000)
    wf.writeframes(pcm_bytes)

wav_bytes = wav_buffer.getvalue()
converted_audio = base64.b64encode(wav_bytes).decode('utf-8')

socketio.emit('tts_response', {'output': converted_audio,'isLastChunk': False}, namespace='/agent-chat')

And my frontend JavaScript code:

const playText = (data) => {
if (!data?.output || data.output === "[DONE]") return;
if (data.output._placeholder) return;

if (data.format === "pcm") {
  const pcmData = atob(data.output);
  const buffer = audioContextRef.current.createBuffer(
    1,
    pcmData.length / 2,
    24000
  );
  const nowBuffering = buffer.getChannelData(0);

  // Convert PCM data to float32
  for (let i = 0; i < pcmData.length / 2; i++) {
    const sample =
      pcmData.charCodeAt(i * 2) | (pcmData.charCodeAt(i * 2 + 1) << 8);
    // Convert from int16 to float32
    nowBuffering[i] = (sample < 32768 ? sample : sample - 65536) / 32768.0;
  }

  // Play immediately
  const source = audioContextRef.current.createBufferSource();
  source.buffer = buffer;
  source.connect(audioContextRef.current.destination);
  source.start();
  return;
}

let wavBytes;

// Handle different audio formats
if (
  data.output instanceof ArrayBuffer ||
  data.output instanceof Uint8Array
) {
  wavBytes = new Uint8Array(data.output);
} else if (typeof data.output === "string") {
  try {
    const binaryString = atob(data.output);
    wavBytes = new Uint8Array(binaryString.length);
    for (let i = 0; i < binaryString.length; i++) {
      wavBytes[i] = binaryString.charCodeAt(i);
    }
  } catch (error) {
    console.error("Base64 decoding failed:", error);
    return;
  }
} else {
  console.warn("Unhandled data format:", data);
  return;
}

// Check if this is the final complete audio
const isComplete = data.isComplete === true;

// Decode and play audio
audioContextRef.current.decodeAudioData(
  wavBytes.buffer,
  (buffer) => {
    // If this is the complete audio and we have chunks in the queue,
    // we can clear the queue and play the complete audio instead
    if (isComplete && audioBufferQueueRef.current.length > 0) {
      audioBufferQueueRef.current = [];
      if (activeAudioSourceRef.current) {
        activeAudioSourceRef.current.stop();
        activeAudioSourceRef.current = null;
      }
      isPlayingRef.current = false;
    }

    audioBufferQueueRef.current.push(buffer);
    if (!isPlayingRef.current) {
      playNextInQueue();
    }
  },
  (error) => console.error("decodeAudioData failed", error)
);};

The Problem: When streaming audio to the web browser, I hear “tak tak” noise artifacts between audio chunks. I’ve tried several approaches:

  • Converting each PCM chunk to WAV and sending individually
  • Buffering multiple chunks and sending larger chunks
  • Adding crossfade between chunks
  • Sending raw PCM data directly

None of these approaches eliminate the noise. The Streamlit version works perfectly with PyAudio, but I need this to work in a web browser.

Question: How can I stream PCM audio from AWS Bedrock Nova Sonic to a web browser without the noise artifacts, i just wnat to play the streaming audio smoothly witohut any noise?

Trying to Make a Review System in FireStore but having Permission Issues

I’m trying to develop a review system.
However, I’ve been getting a permission error:

Uncaught (in promise) FirebaseError: Missing or Insufficient Permissions error.

These aren’t my full rules, but just the ones about the reviews.
The permission doc is being created, but the review doc isn’t, so I’m not quite sure what’s wrong.

My code:

  onSnapshot(qToMe, snap => {
    snap.forEach(d => { confirmedCache[d.id] = d.data(); });
    renderConfirmed();
    checkForReviewPrompt();
  });
  onSnapshot(qFromMe, snap => {
    snap.forEach(d => { confirmedCache[d.id] = d.data(); });
    renderConfirmed();
    checkForReviewPrompt();
  });

  // ——— Rating Modal Logic ———
  const ratingModal   = document.getElementById('ratingModal');
  const ratingForm    = document.getElementById('ratingForm');
  const ratingCancel  = document.getElementById('ratingCancel');
  const messagesModal = document.getElementById('messagesModal');
  const closeMessages = document.getElementById('closeMessagesModal');
  let pendingReview   = null;
  let reviewQueue     = false;

  // When chat modal closes, trigger review if queued
  closeMessages?.addEventListener('click', () => {
    if (reviewQueue) {
      ratingModal.classList.remove('hidden');
      reviewQueue = false;
    }
  });

  function checkForReviewPrompt() {
    if (!ratingModal) return;
    const today = new Date();
    const yesterday = new Date(today);
    yesterday.setDate(today.getDate() - 1);
    const cutoff = yesterday.toISOString().slice(0,10);

    for (const [meetupId, data] of Object.entries(confirmedCache)) {
      if (data.date > cutoff) continue;
      const otherUid = data.participants.find(uid => uid !== user.uid);
      if (!otherUid) continue;

      const key = `${meetupId}_${user.uid}`;
      window._reviewChecked = window._reviewChecked || {};
      if (window._reviewChecked[key]) continue;
      window._reviewChecked[key] = true;

      promptReviewIfNeeded(meetupId, otherUid);
      return;
    }
  }

  async function promptReviewIfNeeded(meetupId, otherUid) {
    const q = query(
      collection(db, 'meetupReviews'),
      where('meetupId', '==', meetupId),
      where('reviewer', '==', user.uid)
    );
    const res = await getDocs(q);
    if (res.empty && ratingModal) {
      pendingReview = { meetupId, otherUid };

      if (messagesModal && !messagesModal.classList.contains('hidden')) {
        reviewQueue = true;
      } else {
        ratingModal.classList.remove('hidden');
      }
    }
  }

  ratingCancel?.addEventListener('click', () => {
    ratingModal.classList.add('hidden');
    pendingReview = null;
  });

  ratingForm?.addEventListener('submit', async e => {
    e.preventDefault();
    if (!pendingReview) return;

    const form = new FormData(ratingForm);
    const rating = Number(form.get('rating'));
    const comment = document.getElementById('ratingComment').value.trim();
    if (!rating || rating < 1 || rating > 5) {
      return alert('Select 1–5 stars.');
    }

    // 1) Create permission doc
    const permId = `${pendingReview.meetupId}_${user.uid}`;
    await setDoc(doc(db, 'meetupReviewPermissions', permId), {
      meetupId: pendingReview.meetupId,
      reviewer: user.uid,
      reviewee: pendingReview.otherUid,
      created: Timestamp.now()
    });

    // 2) Now create the review
    await addDoc(collection(db, 'meetupReviews'), {
      meetupId: pendingReview.meetupId,
      reviewer: user.uid,
      reviewee: pendingReview.otherUid,
      rating,
      comment,
      timestamp: Timestamp.now()
    });

    ratingModal.classList.add('hidden');
    pendingReview = null;
    alert('Thanks for your feedback!');
  });

});

And here are my Firestore rules:

   rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
    
        // ——— meetupReviewPermissions collection ———
        match /meetupReviewPermissions/{permId} {
          // The client now writes these on acceptance
          allow create: if request.auth != null
                        && request.auth.uid == request.resource.data.reviewer
                        && request.resource.data.reviewer != request.resource.data.reviewee
                        && request.resource.data.keys().hasAll([
                             "meetupId","reviewer","reviewee","created"
                           ])
                        && get(/databases/$(database)/documents/meetupRequests/$(request.resource.data.meetupId)).data.status == "accepted"
                        && request.auth.uid in get(/databases/$(database)/documents/meetupRequests/$(request.resource.data.meetupId)).data.participants;
          allow read: if request.auth != null
                      && (request.auth.uid == resource.data.reviewer
                          || request.auth.uid == resource.data.reviewee);
          allow update, delete: if false;
        }
    
    // ——— meetupReviews collection ———
    match /meetupReviews/{reviewId} {
      allow read: if true;
    
      allow create: if request.auth != null
                    && request.auth.uid == request.resource.data.reviewer
                    && request.resource.data.reviewer != request.resource.data.reviewee
                    && request.resource.data.keys().hasAll([
                         "meetupId","reviewer","reviewee",
                         "rating","comment","timestamp"
                       ])
                    && request.resource.data.rating >= 1
                    && request.resource.data.rating <= 5
                    && exists("meetupReviewPermissions/" + request.resource.data.meetupId + "_" + request.auth.uid);
    
      allow update, delete: if false;
    }
    }
    }

VM1186:5 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘call’) Emscripten

I’ve got a really difficult problem.
I have built libusb with emscripten according to https://web.dev/articles/porting-libusb-to-webusb#build_system_and_the_first_test.
That all works great, with the test program provided, only problem I have now is I am trying to use this library with my own custom code but it is not working.

Very rough code
https://gitlab.com/-/snippets/4844863
I am compiling with this command:

    EMCC_DEBUG=1 emcc main.c ./libusb/build/install-web/lib/libusb-1.0.a 

  -I./libusb/build/install-web/include 
  -L./libusb/build/install-web/lib 
  -s USE_PTHREADS=1 
  -s PTHREAD_POOL_SIZE=4 
  -s PROXY_TO_PTHREAD=1 
  -s ALLOW_MEMORY_GROWTH=1 
  -s ASYNCIFY=1 
  -s ENVIRONMENT=web,worker 
  -sASSERTIONS=2 
  --bind 
  -g3 
  -o main.html

Then I am hosting the file, using

const http = require('http');
const fs = require('fs');
const path = require('path');

http.createServer((req, res) => {
  const filePath = path.join(__dirname, req.url === '/' ? '/main.html' : req.url);

  fs.stat(filePath, (err, stats) => {
    if (err || !stats.isFile()) {
      res.writeHead(404, { 'Content-Type': 'text/plain' });
      res.end('404 Not Found');
      return;
    }

    const ext = path.extname(filePath);
    const contentType =
      ext === '.js' ? 'application/javascript' :
      ext === '.wasm' ? 'application/wasm' :
      ext === '.html' ? 'text/html' :
      'application/octet-stream';

    res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
    res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
    res.writeHead(200, { 'Content-Type': contentType });

    fs.createReadStream(filePath).pipe(res);
  });
}).listen(8080, () => console.log('http://localhost:8080'));

When I visit the site, I get this error in chrome:

Hello, World!
(index):146 Found device 0451:e012
(index):146 Tkaksdf
VM1186:5 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'call')
    at methodCaller<(int) => emscripten::val> (eval at __emval_get_method_caller (http://localhost:8080/main.js:5144:29), <anonymous>:5:17)
    at __emval_call_method (http://localhost:8080/main.js:5015:14)
    at imports.<computed> (http://localhost:8080/main.js:4747:24)
    at main.wasm.emscripten::val emscripten::val::internalCall<(emscripten::internal::EM_METHOD_CALLER_KIND)0, emscripten::val, emscripten::val emscripten::val::call<emscripten::val, int&>(char const*, int&) const::'lambda'(emscripten::internal::_EM_METHOD_CALLER*, emscripten::_EM_VAL*, emscripten::internal::_EM_DESTRUCTORS**, void const*), int&>(emscripten::val emscripten::val::call<emscripten::val, int&>(char const*, int&) const::'lambda'(emscripten::internal::_EM_METHOD_CALLER*, emscripten::_EM_VAL*, emscripten::internal::_EM_DESTRUCTORS**, void const*), int&) const (http://localhost:8080/main.wasm:wasm-function[227]:0x264dd)
    at main.wasm.int (anonymous namespace)::CachedDevice::awaitOnMain<int&>(char const*, int&) const::'lambda'()::operator()() const (http://localhost:8080/main.wasm:wasm-function[116]:0x142a7)
    at main.wasm.(anonymous namespace)::em_set_configuration(libusb_device_handle*, int) (http://localhost:8080/main.wasm:wasm-function[114]:0x13a60)
    at main.wasm.libusb_set_configuration (http://localhost:8080/main.wasm:wasm-function[66]:0x7244)
    at main.wasm.usb_get_device (http://localhost:8080/main.wasm:wasm-function[48]:0x19e1)
    at main.wasm.__original_main (http://localhost:8080/main.wasm:wasm-function[49]:0x29c9)
    at main.wasm.main (http://localhost:8080/main.wasm:wasm-function[50]:0x2d2c)

No sure why, but it stops working in the function libusb_set_configuration
just wondering if anyone has any experience with this or could help guide me on how to debug this type of stuff. Thanks.

How can I play sound with Toast in React?

I need to play a Sound together with a Toast in React. However, the Sound does not play if there is no user interaction in JavaScript. Is there a way to solve this?
This is my code.

const [audioRef] = useState(new Audio("https://firebasestorage.googleapis.com/v0/b/deligo-9f8b3.firebasestorage.app/o/audio%2FOrder_Alert.mp3?alt=media&token=c62014d6-3f2a-4cb9-a4cc-8109a53536d5"));

useEffect(() => {
  audioRef.volume = 0.8;
  audioRef.loop = true;
}, [audioRef]);

const action = () => {
  const button = document.createElement("button");
  button.style.display = "none";
  document.body.appendChild(button);
  button.addEventListener("click", () => {
    audioRef.play().catch(console.error);
  });
  button.click();
  document.body.removeChild(button);

  toast.success("Hi, there. New order just landed!", {
    position: "bottom-right", 
    autoClose: 5000,
    className: "custom-toast",
    progressClassName: "!bg-gradient-to-r from-blue-500 to-purple-500",
    icon: <img src="https://res.cloudinary.com/djjovgwyk/image/upload/v1739515599/photo_2025-02-14_08-37-33_fyib4y.png" />,
  });
}

Loop thru json file for specific data value in NodeJS [duplicate]

I am trying to loop thru a JSON file and only print out a specific value.

This is my example JSON data and I am wanting to print of every market_hash_name

{
"items": [
    { "market_hash_name": "sg-553-danger-close", "exterior": "factory new" },
    { "market_hash_name": "famas-commemoration", "exterior": "field-tested" },
    { "market_hash_name": "sawed-off-spirit-board", "exterior": "well-worn" }
  ]
}

This is my app.js file. I am just stuck on how to print the value I am after.

import { readFile } from 'fs/promises';

const data = JSON.parse(await readFile("item_names.json", "utf8"));

console.log(data)

Expected result

market_has_name: 'sg-553-danger-close'
market_has_name: 'famas-commemoration'
market_has_name: 'sawed-off-spirit-board'

Is there a way to make Google Chrome open links with certain protocols in a new window?

I am using Google Chrome and Google Business suite for my email. I have registered a custom protocol handler for all mailto links in the javascript console from the business suite page using the following code.

navigator.registerProtocolHandler("mailto", 
                                 "https://mail.google.com/mail/u/1/?extsrc=mailto&url=%s", 
                                 "Business Email");

This works just fine as far as the protocol handling is concerned. When a link is clicked, a composition window is opened using the GSuite email.

But, when I click a mailto link, the tab that is currently in use is navigated away from in favor of the composition window. I’d greatly prefer if mailto links opened in a new window and left the tab containing the link unchanged.

Is there a Chrome setting or a piece of code I can run that will force Chrome to always open mailto links in a new window?

I know I can middle click or right click and choose new window, but I’m hoping there’s a solution that makes it automatic.

After five successful POSTs, subsequent requests return 500 with missing CORS headers in production (Vue 2 + Axios + Java/Springboot))

I’m working with Vue 2 and Axios; in production the browser shows “No Access-Control-Allow-Origin” after the sixth or tenth POST request to /api/patients, and the server returns 500 and the user needs to relogging. Locally I fired fifteen consecutive requests—both from the UI and via Postman—without reproducing the error, even with the full 50 kB payload and with a reduced 5 kB version. On the front end I’ve confirmed that headers and tokens are identical on every attempt, there’s no caching or service worker interference, and my Axios interceptor isn’t altering the request. Our backend team has also reviewed their CORS configuration, run stress tests against this same endpoint, and reports everything functioning correctly on their side. Given this, I’m unsure whether the fix should come from my code, from the backend (e.g., ensuring CORS headers are sent even on 500 responses), or if it should be escalated to infrastructure/support

error message when DriveApp.getFolderByID is used

I constantly get an error message when trying to implement DriveApp.getFolderByID. My
partial code is:

'function myFunction() {
var files = DriveApp.getFolderById("https://drive.google.com/drive/folders/1H- 
ZCY71Ej3a7F_cUZ4wmSDc-WIz9gRxl?usp=drive_link
").getFiles()
while (files.hasNext()) {
var file = files.next();'

This is partial code to auto-import a number of google sheets rows at a time to another sheet in the same spreadsheet. However I get this error message. I have searched google
workspace to see if the DriveApp function was still viable and not found to the contary. I get this error message – “Exception: Unexpected error while
getting the method or property getFolderById on object DriveApp.myFunction @ Learning
Auto Import.gs:2” when I run the code. enter code hereHelp Please

How often is a TURN server needed for P2P file transfer?

I am building an app that also has a feature of p2p file transfer. The stack used is react + next.js using socket.io. File transfer works perfectly on home network but if i have 2 devices on 2 networks(regular home network ISPs) the ICE fails. AI keeps telling me i need to use a TURN server. I am hosting one so it wouldn’t be a problem but i just can’t get my mind around having to use a TURN server for each transfer. I can provide logs if needed. Thanks guys!

send page

'use client';

import { useEffect, useRef, useState } from 'react';
import { socket, registerDevice, sendOffer, sendCandidate } from '@/lib/socket';

export default function SendPage() {
    const [receiverId, setReceiverId] = useState('');
    const [status, setStatus] = useState('Waiting...');
    const fileInputRef = useRef<HTMLInputElement>(null);
    const peerConnectionRef = useRef<RTCPeerConnection | null>(null);
    const dataChannelRef = useRef<RTCDataChannel | null>(null);

    const senderDeviceId = 'abc123';

    useEffect(() => {
        registerDevice(senderDeviceId);

        async function createConnection(file: File, receiverDeviceId: string) {
            const peerConnection = new RTCPeerConnection({
                iceServers: [{ urls: "stun:stun.l.google.com:19302" }]
            });

            peerConnectionRef.current = peerConnection;

            const dataChannel = peerConnection.createDataChannel("fileTransfer");
            dataChannelRef.current = dataChannel;

            dataChannel.onopen = () => {
                setStatus("Sending file...");
                sendFile(file);
            };

            peerConnection.onicecandidate = (event) => {
                if (event.candidate) {
                    sendCandidate(receiverDeviceId, event.candidate);
                }
            };

            peerConnection.onicegatheringstatechange = () => {
                if (peerConnection.iceGatheringState === "complete" && peerConnection.localDescription) {
                    sendOffer(senderDeviceId, receiverDeviceId, peerConnection.localDescription);
                    setStatus("Offer sent. Waiting for answer...");
                }
            };

            peerConnection.oniceconnectionstatechange = () => {
                console.log("ICE connection state:", peerConnection.iceConnectionState);
            };

            peerConnection.onconnectionstatechange = () => {
                console.log("Connection state:", peerConnection.connectionState);
            };

            const offer = await peerConnection.createOffer();
            await peerConnection.setLocalDescription(offer);
        }

        function sendFile(file: File) {
            const chunkSize = 16384;
            const reader = new FileReader();
            let offset = 0;

            dataChannelRef.current?.send(JSON.stringify({
                type: "metadata",
                filename: file.name,
                filetype: file.type,
                size: file.size
            }));

            reader.onload = (e) => {
                if (e.target?.readyState !== FileReader.DONE) return;
                if (e.target.result && dataChannelRef.current) {
                    dataChannelRef.current.send(e.target.result as ArrayBuffer);
                    offset += (e.target.result as ArrayBuffer).byteLength;
                    if (offset < file.size) {
                        readSlice(offset);
                    } else {
                        setStatus("File sent successfully!");
                    }
                }
            };

            reader.onerror = () => {
                console.error("Error reading file");
                setStatus("File read error");
            };

            function readSlice(o: number) {
                const slice = file.slice(o, o + chunkSize);
                reader.readAsArrayBuffer(slice);
            }

            readSlice(0);
        }

        const clickHandler = () => {
            const file = fileInputRef.current?.files?.[0];
            if (!file || !receiverId) {
                setStatus("Missing file or device ID");
                return;
            }
            createConnection(file, receiverId);
        };

        document.getElementById("connectBtn")?.addEventListener("click", clickHandler);

        socket.on("receive_answer", async ({ answer }) => {
            const pc = peerConnectionRef.current;
            if (!pc) return;
            if (pc.signalingState === "have-local-offer") {
                await pc.setRemoteDescription(new RTCSessionDescription(answer));
            } else {
                console.warn("Ignoring answer: unexpected signaling state", pc.signalingState);
            }
        });

        socket.on("ice_candidate", ({ candidate }: { candidate: RTCIceCandidateInit }) => {
            if (peerConnectionRef.current) {
                peerConnectionRef.current.addIceCandidate(new RTCIceCandidate(candidate));
            }
        });

        return () => {
            document.getElementById("connectBtn")?.removeEventListener("click", clickHandler);
        };
    }, [receiverId]);

    return (
        <div style={{ fontFamily: 'sans-serif', margin: '2em' }}>
            <h1>Send File</h1>
            <label>
                Receiver Device ID:{' '}
                <input
                    type="text"
                    value={receiverId}
                    onChange={(e) => setReceiverId(e.target.value)}
                />
            </label>
            <br />
            <label>
                Select File: <input type="file" ref={fileInputRef} />
            </label>
            <br />
            <button id="connectBtn">Send File</button>
            <p>{status}</p>
        </div>
    );
}

receive page

'use client';

import { useEffect, useRef, useState } from 'react';
import { socket, registerDevice, sendAnswer, sendCandidate } from '@/lib/socket';

export default function ReceivePage() {
    const [deviceId, setDeviceId] = useState('Loading...');
    const [status, setStatus] = useState('Waiting for offer...');
    const peerConnectionRef = useRef<RTCPeerConnection | null>(null);
    const receivedChunksRef = useRef<Uint8Array[]>([]);
    const receivedSizeRef = useRef(0);
    const metadataRef = useRef<{ name: string; type: string; size: number } | null>(null);

    useEffect(() => {
        function generateRandomId(length = 6): string {
            const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
            return Array.from({ length }, () => chars[Math.floor(Math.random() * chars.length)]).join('');
        }

        const receiverDeviceId = generateRandomId();
        setDeviceId(receiverDeviceId);
        registerDevice(receiverDeviceId);

        socket.on("receive_offer", async ({ sender, offer }: { sender: string; offer: RTCSessionDescriptionInit }) => {
            setStatus("Offer received. Creating answer...");

            const peerConnection = new RTCPeerConnection({
                iceServers: [{ urls: "stun:stun.l.google.com:19302" }]
            });
            peerConnectionRef.current = peerConnection;

            peerConnection.oniceconnectionstatechange = () => {
                console.log("ICE connection state:", peerConnection.iceConnectionState);
            };

            peerConnection.onconnectionstatechange = () => {
                console.log("Connection state:", peerConnection.connectionState);
            };

            peerConnection.ondatachannel = (event) => {
                const channel = event.channel;

                channel.onmessage = async (event) => {
                    if (typeof event.data === "string") {
                        try {
                            const msg = JSON.parse(event.data);
                            if (msg.type === "metadata") {
                                metadataRef.current = {
                                    name: msg.filename,
                                    type: msg.filetype,
                                    size: msg.size
                                };
                                receivedChunksRef.current = [];
                                receivedSizeRef.current = 0;
                                setStatus(`Receiving ${msg.filename} (${msg.size} bytes)`);
                            }
                        } catch (e) {
                            console.warn("Invalid metadata JSON");
                        }
                    } else {
                        const chunk = event.data instanceof Blob
                            ? new Uint8Array(await event.data.arrayBuffer())
                            : new Uint8Array(event.data);
                        receivedChunksRef.current.push(chunk);
                        receivedSizeRef.current += chunk.byteLength;

                        if (metadataRef.current && receivedSizeRef.current >= metadataRef.current.size) {
                            const blob = new Blob(receivedChunksRef.current, { type: metadataRef.current.type });
                            const a = document.createElement("a");
                            a.href = URL.createObjectURL(blob);
                            a.download = metadataRef.current.name;
                            a.click();
                            setStatus("File received and downloaded!");
                        }
                    }
                };

                channel.onopen = () => {
                    setStatus("Data channel open. Receiving file...");
                };
            };

            peerConnection.onicecandidate = (event) => {
                if (event.candidate) {
                    sendCandidate(sender, event.candidate);
                }
            };

            await peerConnection.setRemoteDescription(new RTCSessionDescription(offer));
            const answer = await peerConnection.createAnswer();
            await peerConnection.setLocalDescription(answer);
            sendAnswer(sender, answer);
            setStatus("Answer sent. Waiting for file...");
        });

        socket.on("ice_candidate", ({ candidate }: { candidate: RTCIceCandidateInit }) => {
            if (peerConnectionRef.current) {
                peerConnectionRef.current.addIceCandidate(new RTCIceCandidate(candidate));
            }
        });
    }, []);

    return (
        <div style={{ fontFamily: "sans-serif", margin: "2em" }}>
            <h1>Receive File</h1>
            <p>Your device ID: <strong style={{ color: "#333" }}>{deviceId}</strong></p>
            <p>{status}</p>
        </div>
    );
}

Why is “onload” event triggered early? – GitHub Pages loading screen woes

I’m not a developer and I was not built to write code! I’m using GitHub pages to host a very simple site with a very chunky pdf.

I want the site to land on a loading screen which disappears when the pdf is visible, but the loading screen always disappears almost instantaneously, leaving a blank grey screen on the PDF for about seven seconds before it finally loads.

Here’s the code:

<div id="preloader">
        <div class="loader">
            <Img src="loadingscreentest.png"></Img>
            </div>
    </div>



<div class="content">
    <iframe src="InProgTest5.pdf#toolbar=0&navpanes=0&scrollbar=0&frameBorder=0&view=FitH"  type='application/pdf' onload="killloadscreen()"></iframe> 
</div>



<script>
    function killloadscreen(){
        const preloader = document.getElementById('preloader'); 
        const content = document.getElementById('content');
    preloader.style.display = 'none'; 
    content.style.display = 'block'; 
    }
</script>

I also tried event listeners with window.onload and DOMContentLoaded to hide the loading screen and show the content, but these bore the same results (or worse, with no loading screen showing up at all). I searched around the internet for clues and fixes and tried a few different things to no avail. One insight I found which I fear could be the answer is that there could be interference from the service being used to host the code (Pages, in my case). I’ve been informed that Pages is intended for static websites, so maybe it was always liable to disagree with moving parts like events and scripts? I know very little about this stuff.

Anyway, is there a solvable reason the onload event is triggered before everything is fully loaded? Or is there a way to determine for certain when the contents of the pdf become visible? Or is the code itself wrong? Or perhaps I need a workaround like something that can detect the color of a given pixel behind the loading screen (that seems flimsy to me, but I’m grasping at straws)? If hosting is likely the issue, I’ll absolutely look for a different platform.

Thanks for reading! Any help is appreciated. I am relying on this PDF, and I’m afraid having it blank without a loading screen (or something) is not an option!

Genre paths won’t load in deployed website on Github pages and netlify

When I use my website on github pages it seems to work, but the “genre” paths get me a 404 error from Github. I also used this in netlify and i get the same result. If I click on a genre, it tells me that the page doesn’t exist. And if I press the back button on a 404 page, pages that seem to work also turn into 404 errors. Typing in a link of any page will also give a 404 error, but navigating to those pages (Movies, TV shows, anime) through the site itself seems to work. Everything works as it should if I run it locally using npm run dev/preview, so I’m really lost. Also I want to know if there’s a way to remove /website2/ as the link in github-pages deployments. The website (https://arjunr12345.github.io/website2/) also becomes a blank white screen if I add https://arjunr12345.github.io as homepage in package.json. Even if I try removing “/website2/” from the link manually github just gives me a 404 error again. I tried following the instrucions from here: https://github.com/rafgraph/spa-github-pages, but even after that the problem persists.

Links:
Site: https://arjunr12345.github.io/website2/
Repo: https://github.com/arjunr12345/website2