Blob download saves as .bin with a random filename instead of .webm

I’m developing a Tampermonkey userscript to capture audio from a webpage using the MediaRecorder API. The script successfully records audio and creates a Blob with the MIME type audio/webm;codecs=opus. However, when I attempt to download the generated audio file, it’s saved with a .bin extension and a random 9-digit filename (e.g. 1298453815.bin) instead of the intended recording.webm.

This is the relevant code snippet.

// Media recorder handling above
const audioBlob = new Blob(audioChunks, { type: 'audio/webm;codecs=opus' });
const audioUrl = URL.createObjectURL(audioBlob);

const link = document.createElement('a');
link.href = audioUrl;
link.download = 'recording.webm';
link.click();

I’ve tried various methods to enforce the correct filename and extension, including explicitly setting the download attribute of the anchor tag and setting the type attribute. Trying GM_download on blob URL, using FileReader to convert the blob to a data URL. I’ve also tested with simple text files created from blobs, and the issue persists. I also inspected the network tab and it shows that the request headers are set with the correct MIME types.

Crucially, I know this is possible and not a browser limitation due to the fact that this site https://editor.audio/ uses blobs for export and the “Save as” window appears with the correct filename and extension.

Could anyone clarify what I’m missing? Is there a proper way to ensure that the downloaded file has the correct filename and extension when using blobs in a Tampermonkey userscript? I’m particularly interested in understanding why the download attribute and GM_download are not working as expected in this context, and how the website I linked manages to achieve the desired behavior.

Not able to setCurrentUser while fetching it from localstorage

const [currentUser, setCurrentUser] = useState(undefined)

useEffect(() => {
    async function fetchdata() {
        const storedUser = localStorage.getItem("chat-app-user");
        if (!storedUser) {
            navigate("/login");
        } else {
            const user = await JSON.parse(storedUser);
            console.log("Fetched user from localStorage:", user);
            setCurrentUser(user); 
        }
    }
    fetchdata();
}, [navigate]);

I am trying to setCurrentUser. I am getting an user from local storage but while setting it to setCurrentUser it is not getting set and currentUser is remaining undefined

Netflix slider card hover owlcarousel tailwind

I want to recreate the netflix slider using tailwind and owlcarousel. It’s almost done as I want but I’m facing a problem when I hover the card I apply a scaling up to the card to display details but I actually can’t click on them. Also I do not have the same height on the items.

Does anyone can help me with this ?

HTML structure

<section class="mx-auto w-screen relative flex flex-col gap-4 px-5 mb-16">
    <div class="owl-carousel owl-theme">
        <div class="item group transition-all sm:hover:absolute sm:hover:scale-125 border border-red-600">
            <div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
                <div>
                    <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQKSRTtOrtjLaagEC2gTK6VsPq4NEFk_72hhg&s"
                        alt="">
                </div>
                <div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
                    <div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
                        <span class="">
                            MOVIE TITLE
                        </span>
                    </div>
                    <a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
                        try to click me you can't
                    </a>
                </div>
            </div>
        </div>
        <div class="item group transition-all sm:hover:absolute sm:hover:scale-125 border border-red-600 overflow-hidden">
            <div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
                <div>
                    <img src="https://occ-0-6613-7435.1.nflxso.net/dnm/api/v6/Qs00mKCpRvrkl3HZAN5KwEL1kpE/AAAABQquP3MObc4Xmx8fS1E0EtFypAJFcNs8U73s6OHL2GjPOuIRbKkknfytMjCRkky6eDIe_8LHwBndef1-gQiN3IMX5NEqFRShrIi9MKSOMGvoTalZ2GRya1eswfUOXrTJ6Nnflg.webp?r=bb3"
                        alt="">
                </div>
                <div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
                    <div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
                        <span class="">
                            MOVIE TITLE
                        </span>
                    </div>
                    <a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
                        try to click me you can't
                    </a>
                </div>
            </div>
        </div>
        <div class="item group transition-all sm:hover:absolute sm:hover:scale-125 border border-red-600">
            <div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
                <div>
                    <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQKSRTtOrtjLaagEC2gTK6VsPq4NEFk_72hhg&s"
                        alt="">
                </div>
                <div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
                    <div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
                        <span class="">
                            MOVIE TITLE
                        </span>
                    </div>
                    <a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
                        try to click me you can't
                    </a>
                </div>
            </div>
        </div>
        <div class="item group transition-all sm:hover:absolute sm:hover:scale-125 border border-red-600">
            <div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
                <div>
                    <img src="https://placecats.com/340/192" alt="">
                </div>
                <div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
                    <div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
                        <span class="">
                            MOVIE TITLE
                        </span>
                    </div>
                    <a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
                        try to click me you can't
                    </a>
                </div>
            </div>
        </div>
        <div class="item group transition-all sm:hover:absolute sm:hover:scale-125 border border-red-600">
            <div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
                <div>
                    <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQKSRTtOrtjLaagEC2gTK6VsPq4NEFk_72hhg&s"
                        alt="">
                </div>
                <div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
                    <div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
                        <span class="">
                            MOVIE TITLE
                        </span>
                    </div>
                    <a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
                        try to click me you can't
                    </a>
                </div>
            </div>
        </div>
        <div class="item group transition-all sm:hover:absolute sm:hover:scale-125 border border-red-600">
            <div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
                <div>
                    <img src="https://occ-0-6613-7435.1.nflxso.net/dnm/api/v6/Qs00mKCpRvrkl3HZAN5KwEL1kpE/AAAABQquP3MObc4Xmx8fS1E0EtFypAJFcNs8U73s6OHL2GjPOuIRbKkknfytMjCRkky6eDIe_8LHwBndef1-gQiN3IMX5NEqFRShrIi9MKSOMGvoTalZ2GRya1eswfUOXrTJ6Nnflg.webp?r=bb3"
                        alt="">
                </div>
                <div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
                    <div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
                        <span class="">
                            MOVIE TITLE
                        </span>
                    </div>
                    <a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
                        try to click me you can't
                    </a>
                </div>
            </div>
        </div>
        <div class="item group transition-all sm:hover:absolute sm:hover:scale-125 border border-red-600">
            <div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
                <div>
                    <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQKSRTtOrtjLaagEC2gTK6VsPq4NEFk_72hhg&s"
                        alt="">
                </div>
                <div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
                    <div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
                        <span class="">
                            MOVIE TITLE
                        </span>
                    </div>
                    <a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
                        try to click me you can't
                    </a>
                </div>
            </div>
        </div>
    </div>
</section>

Javascript

const addHoverClasses = (event) => {
  const owlitemHovered = event.currentTarget
  owlitemHovered.classList.add("!z-10")
  owlitemHovered.classList.remove("!z-0")
}

const removeHoverClasses = (event) => {
  const owlitemHovered = event.currentTarget
  owlitemHovered.classList.remove("!z-10")
  owlitemHovered.classList.add("!z-0")
}

const getOwlcarouselResponsiveMaxItems = (event) => {
  const owlInstance = event.relatedTarget
  const currentBreakpoint = owlInstance._breakpoint
  const breakpoints = owlInstance.options.responsive

  return breakpoints[currentBreakpoint].items
}

const applyTransformOrigin = (event) => {
  const owlCarousel = event.target
  const owlItems = owlCarousel.querySelectorAll(".owl-item")
  let owlItemActiveCounter = 1
  owlItems.forEach((owlItem, index) => {
    owlItem.classList.add("!z-0")
    owlItem.firstChild.classList.remove(
      "origin-[left_center]",
      "origin-[right_center]",
      "origin-center",
    )
    if (owlItem?.classList.contains("active")) {
      if (owlItemActiveCounter === 1) {
        owlItem.firstChild.classList.add("origin-[left_center]")
      } else if (
        owlItemActiveCounter === getOwlcarouselResponsiveMaxItems(event)
      ) {
        owlItem.firstChild.classList.add("origin-[right_center]")
      } else {
        owlItem.firstChild.classList.add("origin-center")
      }
      owlItemActiveCounter++
    }
  })
}

const applyOwlStyles = (event) => {
  const owlCarousel = event.target
  const owlItems = owlCarousel.querySelectorAll(".owl-item")

  owlCarousel.classList.add("relative")
  owlCarousel
    .querySelector(".owl-stage-outer")
    ?.classList.add("!overflow-visible", "!overflow-x-clip")

  owlItems.forEach((owlItem, index) => {
    owlItem.addEventListener("mouseover", addHoverClasses, false)
    owlItem.addEventListener("mouseout", removeHoverClasses, false)
  })

  const owldotsContainer = owlCarousel.querySelector(".owl-dots")
  owldotsContainer?.classList.add(
    "absolute",
    "!-top-4",
    "right-0",
    "-translate-y-full",
    "!flex",
    "!gap-2",
    "!items-center",
  )

  const owldots = owldotsContainer?.querySelectorAll(".owl-dot") ?? []
  owldots.forEach((olwDot) => {
    const span = olwDot.querySelector("span")
    span.classList.add("!m-0", "!rounded-none", "!w-4", "!h-1")
    span.classList.remove("!bg-primary-600")
    if (olwDot.classList.contains("active")) {
      span.classList.add("!bg-primary-600")
    }
  })

  const owlNav = owlCarousel?.querySelector(".owl-nav")
  owlNav?.classList.add("!m-0", "!top-0", "!bottom-0", "!w-full")

  const owlPrev = owlNav?.querySelector(".owl-prev")
  const owlNext = owlNav?.querySelector(".owl-next")

  owlPrev?.classList.add(
    "!absolute",
    "!h-full",
    "!m-0",
    "!bg-black",
    "!bg-opacity-60",
    "!text-white",
    "!text-6xl",
    "!font-opensans",
    "!left-0",
    "!w-[40px]",
    "!rounded-none",
    "!rounded-r-md",
    "-translate-y-full",
  )
  owlNext?.classList.add(
    "!absolute",
    "!h-full",
    "!m-0",
    "!bg-black",
    "!bg-opacity-60",
    "!text-white",
    "!text-6xl",
    "!font-opensans",
    "!right-0",
    "!w-[40px]",
    "!rounded-none",
    "!rounded-l-md",
    "-translate-y-full",
  )

  owlPrev?.querySelector("span").classList.add("align-super")
  owlNext?.querySelector("span").classList.add("align-super")
}

jQuery(".owl-carousel").owlCarousel({
  loop: true,
  margin: 10,
  stagePadding: 50,
  nav: true,
  responsive: {
    0: {
      items: 1,
    },
    600: {
      items: 3,
    },
    1000: {
      items: 5,
    },
  },
  onInitialized: (event) => {
    applyOwlStyles(event)
    applyTransformOrigin(event)
  },
  onTranslated: (event) => {
    applyTransformOrigin(event)
  },
  onResized: (event) => {
    applyOwlStyles(event)
    applyTransformOrigin(event)
  },
})

Not able to publish application on play store?

I created one small application using flutter only then I created new account in google play console and try to publish my application, but my application is 3 times rejected, reason is showing only “Your app requires more testing to access Google Play production” but same application I published in App Store , it is successfully published but ion play store it is not. So please provide me correct solution how I resolve this issue.

Laravel Set-Cookie Response Header Problem With Cloudflare Cache Mechanism

We have a website built with Laravel 10 (upgraded from Laravel 5.6 to 9, and then to version 10). For this website, we use a load balancer on Cloudflare. However, since we are using the StartSession (IlluminateSessionMiddlewareStartSession) and VerifyCsrfToken (AppHttpMiddlewareVerifyCsrfToken) middleware, the response headers for every page include two Set-Cookie headers. Because of the Set-Cookie headers in the response, Cloudflare prevents the page from being cached and directly serving from the Cloudflare cache for subsequent requests.

How can we resolve this issue to allow Cloudflare to cache the pages while still using the necessary middleware in Laravel?

Cloudflare documentation: https://developers.cloudflare.com/cache/concepts/cache-control/#conditions

Cloudflare documentation page

Our website response header:
Our web site response headers

how can I Deploying multiple projects to the same repository

How can I trigger the deployment of a vercel project only when code changes are made in a subdirectory?

I have a repository with three subdirectories of that corresponds to vercel’s three projects, now every time I push the code will trigger the deployment of the three projects, I want to in which subdirectory there is a change in the code, the corresponding project repository before triggering the deployment, what should I do?

when i try the Ignored Build Step feature, it tell me:

Configuration Settings in the current Production deployment differ from your current Project Settings.

Stop WordPress from stripping out custom element

I am using the Tatsu page builder and using their Code module to insert dotlottie code, such as:

<dotlottie-player src="https://lottie.host/******************.lottie" background="transparent" speed="1"  loop autoplay></dotlottie-player>

This works fine; however when I use the usual WordPress Update button for other reasons not related to the page builder, WordPress strips out this code.

I have tried adding the below code to functions.php, but it still got stripped.

function allow_lottie_tags($tags, $context) {
    // Add for all contexts
    $allowed_atts = array(
        'src' => true,
        'background' => true,
        'speed' => true,
        'loop' => true,
        'autoplay' => true,
        'class' => true,
        'id' => true,
        'style' => true
    );

    // Apply to both default and 'post' context
    if ($context === 'post' || $context === 'default') {
        $tags['dotlottie-player'] = $allowed_atts;
    }

    return $tags;
}

// Apply to multiple filters to catch different contexts
add_filter('wp_kses_allowed_html', 'allow_lottie_tags', 999, 2);
add_filter('post_allowed_html', 'allow_lottie_tags', 999, 2);

I then tried adding this, with no luck.

// Also try to force it globally
function hook_lottie_early() {
    global $allowedposttags, $allowedtags;

    $allowed_atts = array(
        'src' => true,
        'background' => true,
        'speed' => true,
        'loop' => true,
        'autoplay' => true,
        'class' => true,
        'id' => true,
        'style' => true
    );

    $allowedposttags['dotlottie-player'] = $allowed_atts;
    $allowedtags['dotlottie-player'] = $allowed_atts;
}
add_action('init', 'hook_lottie_early', 1);

What am I doing wrong? Should I go to a dynamic shortcode instead, or is there another way to handle this?

PHP multiple Object creation from DB

Hi I am very new to PHP and Objects and have become very confused on the best way to create a collection of objects created from a database. Below is an example of what is working for me but its a single object with array properties. Is this the best options or do I create multiple objects for each book and if I create multiple objects how do I loop through to display on my grid.

<?php
declare(strict_types=1); // FAIL FAST
//##############################################
class Books {
// Properties
    protected $id_type=array();
    protected $title=array();
    protected $brief=array();
//==============================================    
function set_books($id, $mysqli)
    {
        //DB Query 
        $result = $stm->get_result();
        $stm->close();

        while ($rows = $result->fetch_assoc()) {
        $this-title[] = $rows['title'];
        $this->brief[] = $rows['brief'];
        }
    }
//==============================================
function get_title()
    {
        return $this->title;
    }
//==============================================
}
$books = new Books();
$books->set_books(4, $mysqli);
$book_count = count($books->get_title());
$i=0;
while ($i < $book_count) {
    
echo "<h1>".$books->get_title()[$i]."</h1>";    

$i++;
}
?>

I have google and cannot find the exact answer I am looking for most examples show a single object like displaying a single book not a list of books.

Making an Enigma Machine in React

I am making the plugboard functionality for an enigma machine in React. I currently have a keyboard layout displayed on the screen (a, b, c, d, …) not qwerty. Regardless, my idea was that a user could hold the control key to activate the plugboard functionality, then click on a letter (or key) to connect a plug there, then the next click, while still holding the control key, would connect the other end of the plug. These plug connections would be shown through color coding, changing the background color of the key of the two connected letters. When an already active key was clicked, it and its connected key, would be deactivated. The issues I’ve run into are limiting the amount of connections to only two letters. Here is my code so far…

import { useState, useContext } from "react";

const colors = [
    "#FF69B480",
    "#66330080",
    "#FFC10780",
    "#8E24AA80",
    "#00BFFF80",
    "#3B3F5480",
    "#FF980080",
    "#0097A780",
    "#E91E6380",
    "#F7DC6F80",
    "#4B008280",
    "#32CD3280",
    "#7081f080",
];

const Letter = ({ letter, ctrlPressed, setCtrlPressed }) => {
    const [activeConnections, setActiveConnections] = useState({});
    const [currentColorIndex, setCurrentColorIndex] = useState(0);
    const [clickCount, setClickCount] = useState(0);

    const handleClick = () => {
        if (ctrlPressed) {
            if (activeConnections[letter]) {
                // Deactivate the connection
                const connectedLetter = Object.keys(activeConnections).find(
                    (key) =>
                        activeConnections[key] === activeConnections[letter] &&
                        key !== letter
                );
                setActiveConnections((prevConnections) => {
                    const newConnections = { ...prevConnections };
                    delete newConnections[letter];
                    delete newConnections[connectedLetter];
                    return newConnections;
                });
            } else {
                // Activate a new connection
                const currentColor =
                    colors[Math.floor(clickCount / 2) % colors.length];
                setActiveConnections((prevConnections) => ({
                    ...prevConnections,
                    [letter]: currentColor,
                }));
                setClickCount(clickCount + 1);
            }
        }
    };

    return (
        <span
            className='letter'
            style={{
                backgroundColor: activeConnections[letter] || "#444",
            }}
            onClick={handleClick}
        >
            {letter}
        </span>
    );
};

export default Letter;

I’ve had ideas that maybe left click for activation and right click for deactivation, or left for one end of the plug and right click for the other end of the plug? Not sure that that quite solves all of my current issues.

FYI: the ctrlPressed state is global and being used as a prop from the parent App component (yes, I know it is not performance best practice, but easy for a personal development project). My array of letters is also being generated and imported from the parent Keyboard component.

App with plugboard toggled OFF

App with plugboard toggled ON

Is there any way to execute simple JavaScript expressions in Java 21 without any manual installations?

For example, I have version 21 installed and as far as I understand, I can’t use Nashorn engine anymore.

But maybe GraalVM is available for me?

I have installed all the necessary dependencies:

    <dependency>
        <groupId>org.graalvm.js</groupId>
        <artifactId>js</artifactId>
        <version>21.1.0</version>
    </dependency>
    <dependency>
        <groupId>org.graalvm.js</groupId>
        <artifactId>js-scriptengine</artifactId>
        <version>21.1.0</version>
    </dependency>

And here’s a simple example that I’m trying to execute:

public static void main(String[] args) throws ScriptException {
    try (Context context = Context.newBuilder("js")
            .allowAllAccess(true)
            .build()) {
        // Evaluate JavaScript code
        String jsCode = "console.log('Hello, GraalVM!');";
        context.eval("js", jsCode);
    } catch (Exception e) {
        throw new ScriptException("Script execution failed: " + e.getMessage());
    }
}

However, I get an error:

Exception in thread “main” javax.script.ScriptException: Script
execution failed: A language with id ‘js’ is not installed. Installed
languages are: []. at org.example.Main.main(Main.java:23)

I also tried something like this:

public static void main(String[] args) throws ScriptException {
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine  = manager.getEngineByName("JavaScript");
    engine.eval("print('HI');");
}

But I got another error:

Exception in thread “main” java.lang.NullPointerException: Cannot
invoke “javax.script.ScriptEngine.eval(String)” because “engine” is
null at org.example.Main.main(Main.java:20)

The problem is that manual installation of any components is impossible for some reason. I just need to some dependencies and make everything works. Something “out of the box”. Is there any workaround for this problem? Maybe there are any other available engines?

Thanks everyone.

Why doesn’t web3 gun library work well together with Angular v18.2?

I’m trying to incorporate gun web3 library into my Angular app, but I’m running into the following error:

[vite] Internal server error: Cannot find module ‘./lib/text-encoding’
Require stack:

I’m using Angular v18.2 so Vite is incorporated into the pipeline, but it is not included in package.json nor the tsconfig.json nor the angular.json.

Everyting seemed to work fine until I decided to move my login logic into seperate component from the main app.component.ts

async ConnectMetaMask(){
    await this.MetaMaskSDK.request({ method: 'eth_requestAccounts' }).then((accounts : any) => {    
      this.UserAccount = accounts[0];
    });

    if(this.UserAccount != null){
      const gun = Gun();
      this.accountConnected = true;

      gun.get(`~@${this.UserAccount + "STF"}`).once(data => {
        console.log(data);
        if (data) {
          this.loginNeeded = true;
        } else {
          this.registerNeeded = true;
        }
      });
    }
  }

  async Login(){
    const gun = Gun();
    const user = gun.user();
    const SEA = Gun.SEA;
    
    if(this.loginNeeded){
      user.auth(this.UserAccount + "STF", this.myForm.get('password')?.value, (ack) =>{
        if ('err' in ack) {
          // Niepoprawne hasło
        } else {
          console.log("zalogowano");
          this.loggeduserData.loggedUserWalletAddress = this.UserAccount;
          this.loggeduserData.loggedUserWalletAddressSTF = this.UserAccount + "STF";
          this.routerAN.navigate(['/dashboard']);
        }
      });
    }
    else{
      user.create(this.UserAccount + "STF", this.myForm.get('password')?.value, ack => {
        if (ack) {
          console.log('Error:', ack);
        } else {
          console.log('User created successfully:', ack);
        }
      });
    }
  }

I generated a new component, moved my logic there and the error popped. These are my imports from the new component with login:

import { Component, OnInit } from '@angular/core';
import { PinataSDK } from "pinata-web3";
import { Router, RouterLink, RouterModule, RouterOutlet } from '@angular/router';
import { CommonModule } from '@angular/common';
import { FormBuilder, FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MetaMaskSDK } from "@metamask/sdk";
import Gun from 'gun';
import 'gun/sea';
import { LoggedUserDataService } from '../../../resources/LoggedUserDataService/logged-user-data.service';
import { env } from '../../../env';

Developer seems to give a sort of solution to this problem (https://gun.eco/docs/Vite), but it requires a change too be made inside
vite.config.js which is not available in Angular v18.2.

I would appreciate any help

Scrapping an image from webview and return it as base64

I am trying to convert an image img/tab_25/05/38/37/bl1005194/chapter_1/1-1728176695-o.webp from a webview to base64.

The issue is that the image is protected So I am unable to fetch the image on the serverside.

So I thought about injecting the fetching and converting code to the webview, I thought that as it is from the same orgin I wont get an issue downloading it and converting it to base64.

Here is that code I am using

const getImage = async function (img) {
     let src = img.getAttribute("src")
       return new Promise(
        async (onSuccess, onError) => {
          try {
            const response = await fetch(src, {
              mode: 'no-cors',
              referer:"https://chapmanganato.to/",
              accept: "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8",
              "accept-encoding":"gzip, deflate, br, zstd",
              "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
            });
            const blob = await response.blob();
            const reader = new FileReader();
            reader.onerror = function (e) {
              console.error(e);
              alert(e)
              onSuccess("");
            }
            reader.onload = function () {
              if (reader.result)
                onSuccess("data:image/jpg;base64,"+reader.result.toString().split(",")[1]);
              else onSuccess("");
            };
            reader.readAsDataURL(blob);
          } catch (e) {
            console.error(e);
            alert(e)
            onSuccess("");
          }
        }
      );
    }

    const getImages = async function () {
        try{
        let imgArray = [];
        let imgs = [...document.querySelectorAll("${parser?.selector}")];
        for (let img of imgs) {
            let src = await getImage(img);
            if (src && src.length>10)
            imgArray.push(src)
        }

        var payload = {
            name: "images",
            url: "${currentUrl}",
            data: imgArray
        };
        window.ReactNativeWebView.postMessage(JSON.stringify(payload));
    }catch(e) {alert(e)}
    }

The above code return data:image/jpg;base64, as result will be empty.

I am assuming that the issue is with .webp

Here is the site I am trying to scrap images from https://manganato.com/

And for those that want a repredusable code, it is not possible as this code has to be run from inside a webview so no need to ask.

Here is the whole react-native component


import WebView from "react-native-webview";
import { Html } from "../native";
import * as React from "react";

export default () => {
  const state = buildState({
    loading: context.parser.find(context.player.novel.parserName)?.protectedChapter == true
  }).build();

  const webview = useRef();

  context.useEffect(() => {
    processData();
  }, "player.currentChapter")

  useEffect(() => {
    processData();
  }, []);

  let parser = context.parser.find(
    context.player.book.parserName
  );

  let processData = () => {
    parser = context.parser.find(
      context.player.book.parserName
    );
    if (context.parser.find(context.player.novel.parserName)?.protectedChapter != true)
      return;


    if (parser?.protectedChapter !== true || state.loading)
      return;

    if (context.player.currentChapter?.content?.has()) {
      return;
    }

    state.loading = true;
  }
  let currentUrl = context.player.currentChapter?.url;

  const script = `
       try {
    const getImage = async function (img) {
     let src = img.getAttribute("src")
       return new Promise(
        async (onSuccess, onError) => {
          try {
            const response = await fetch(src, {
              mode: 'no-cors',
              referer:"https://chapmanganato.to/",
              accept: "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8",
              "accept-encoding":"gzip, deflate, br, zstd",
              "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
            });
            const blob = await response.blob();
            const reader = new FileReader();
            reader.onerror = function (e) {
              console.error(e);
              alert(e)
              onSuccess("");
            }
            reader.onload = function () {
              if (reader.result)
                onSuccess("data:image/jpg;base64,"+reader.result);
              else onSuccess("");
            };
            reader.readAsDataURL(blob);
          } catch (e) {
            console.error(e);
            alert(e)
            onSuccess("");
          }
        }
      );
    }

    const getImages = async function () {
        try{
        let imgArray = [];
        let imgs = [...document.querySelectorAll("${parser?.selector}")];
        for (let img of imgs) {
            let src = await getImage(img);
            if (src && src.length>10)
            imgArray.push(src)
        }

        var payload = {
            name: "images",
            url: "${currentUrl}",
            data: imgArray
        };
        window.ReactNativeWebView.postMessage(JSON.stringify(payload));
    }catch(e) {alert(e)}
    }
    
    const getHtml = async function () {
        var payload = {
            name: "html",
            url: "${currentUrl}",
            data: document.querySelector("${parser?.selector}").outerHTML
        };
        window.ReactNativeWebView.postMessage(JSON.stringify(payload));

    }

    const parse = function () {
        if ("${parser.type}" == "Manga")
           getImages();  
        else  getHtml();
    }
    
    if (document.readyState === "loading") {
        document.addEventListener("DOMContentLoaded", (event) => {
            parse();
        });
    } else {
        parse()
    }
} catch (e) {
    alert(e)
}true;`;


  let web = (state.loading && context.parser.find(context.player.novel.parserName)?.protectedChapter == true ? (
    <WebView
      ref={(r) => webview.current = r}
      injectedJavaScript={script}
      nestedScrollEnabled={true}
      cacheEnabled={true}
      source={{
        uri: currentUrl,
        baseUrl: ""
      }}
      onMessage={async ({ nativeEvent }) => {
        let data = JSON.parse(nativeEvent.data);

        //console.warn(data.url, currentUrl)
        if (data.name === "images") {
          console.log(data.data[0])
          data.data = data.data.map(x => `<img src="${x}" />`).join("n");

        }
        if (currentUrl === data.url) {
          context.player.currentChapter.content = data.data;
          //console.warn(context.player.novel.type)
          await context.player.getChapterContent("hhvh");

          state.loading = false;
        }
      }}
      contentMode="mobile"
      scalesPageToFit={true}
      originWhitelist={["*"]}
      scrollEnabled={true}
      userAgent="Mozilla/5.0 (Linux; Android 4.1.1; Galaxy Nexus Build/JRO03C) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19"
      setSupportMultipleWindows={false}
      style={[
        {
          flexGrow: 1,
          zIndex: 70,
          flex: 1
        }
      ]}
      allowFileAccess={true}
      allowFileAccessFromFileURLs={true}
      allowUniversalAccessFromFileURLs={
        true
      }
      javaScriptEnabled={true}
    />
  ) : null);

  return { loading: state.loading, web };
}

Why does my website keep redirecting me to the spotify authentication page?

Im using the spotify PKCE authentication for my website. However, no matter if I press agree or cancel, it just keeps redirecting back to the authentication page. I am trying to make a website that will recommend music based on certain criteria and play said music, should I even be using the PKCE authentication or a different one? I’m very new to this stuff.

const clientId = '';
const code = undefined;
if (!code) {
  redirectToAuthCodeFlow(clientId);
} else {
  const accessToken =  getAccessToken(clientId, code);
  const profile =  fetchProfile(accessToken);
  populateUI(profile);
}

async function redirectToAuthCodeFlow(clientId) {
  // TODO: Redirect to Spotify authorization page
  const verifier = generateCodeVerifier(128);
  const challenge = await generateCodeChallenge(verifier);

  localStorage.setItem("verifier", verifier);

  const params = new URLSearchParams();
  params.append("client_id", clientId);
  params.append("response_type", "code");
  params.append("redirect_uri", "http://127.0.0.1:3000/index.html");
  params.append("scope", "user-read-private user-read-email");
  params.append("code_challenge_method", "S256");
  params.append("code_challenge", challenge);

  document.location = `https://accounts.spotify.com/authorize?${params.toString()}`;
}

function generateCodeVerifier(length) {
  let text = '';
  let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

  for (let i = 0; i < length; i++) {
      text += possible.charAt(Math.floor(Math.random() * possible.length));
  }
  return text;
}

async function generateCodeChallenge(codeVerifier) {
  const data = new TextEncoder().encode(codeVerifier);
  const digest = await window.crypto.subtle.digest('SHA-256', data);
  return btoa(String.fromCharCode.apply(null, [...new Uint8Array(digest)]))
      .replace(/+/g, '-')
      .replace(///g, '_')
      .replace(/=+$/, '');
}


async function getAccessToken(clientId, code) {
  // TODO: Get access token for code
  const verifier = localStorage.getItem("verifier");

    const params = new URLSearchParams();
    params.append("client_id", clientId);
    params.append("grant_type", "authorization_code");
    params.append("code", code);
    params.append("redirect_uri", "http://localhost:5173/callback");
    params.append("code_verifier", verifier);

    const result = await fetch("https://accounts.spotify.com/api/token", {
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
        body: params
    });

    const { access_token } = await result.json();
    return access_token;
    console.log(access_token);

}

Most of the code is copied from spotify’s website.

Read or count pages of a digital signed pdf document using php or javascript

I am trying to read a pdf which is digitally signed. I tried using different php libraries and also js libraries, each of them works well with a normal pdf document but if the document is digitally signed then it cant read it. Tried libraries mpdf, setassign/fpdi etc. I even tried to remove the digital signature and make a copy of it and then count the pages of the document using ghostscript but not working, but it can’t remove the sign, Is there any way around to do it ? any idea would be appreciated.

How to make trigger change work in Select2?

There is a piece of code that is responsible for updating the QR code during events [‘paste’, ‘keyup’, ‘change’], but for some reason the Select2 list does not work and accordingly, does not transmit data.

my part of code

let apply_reload_qr_code_event_listeners = () => {
        document.querySelectorAll('[data-reload-qr-code]').forEach(element => {
            let events = ['paste', 'keyup', 'change'];
            events.forEach(event_type => {
                element.removeEventListener(event_type, reload_qr_code_event_listener);
                element.addEventListener(event_type, reload_qr_code_event_listener);
            })
        });
    }

Even though data-reload-qr-code is added to input Select2, it does not work, but all other fields work without problems.