Doing some Encryption and Decryption and encounter “System.Security.Cryptography.CryptographicException: ‘Padding is invalid and cannot be removed.'”

This is the view. Upon submit, the data is encrypted. No problem.:

<form asp-controller="Permit" asp-action="Encryptori" method="post">
<div class="form-group">
    <label for="Name">Name:</label>
    <input type="text" id="Name" name="Name" value="Roberto" class="form-control" />
</div>
<div class="form-group">
    <label for="Address">Address:</label>
    <input type="text" id="Address" name="Address" value="Viale Manfredo Fanti, 4 (50137) Firenze" class="form-control" />
</div>
<br />
<button type="submit" class="btn btn-primary" onclick="encryptAndSubmit()">Encrypt and Submit</button>
<br /><br />
@ViewBag.Display
<input type="hidden" id="Key" name="Key" value="@ViewBag.Key" />
<input type="hidden" id="IV" name="IV" value="@ViewBag.IV" />

This is the script in the View:

<script src="https://cdn.jsdelivr.net/npm/[email protected]/crypto-js.min.js"></script>
<script>
function encryptAndSubmit() {
    var name = document.getElementById("Name").value;
    var address = document.getElementById("Address").value;
    var key = "@ViewBag.Key";
    var iv = "@ViewBag.IV";

    var encryptedName = encrypt(name, key, iv);
    var encryptedAddress = encrypt(address, key, iv);

    document.getElementById("Name").value = encryptedName;
    document.getElementById("Address").value = encryptedAddress;
}

function encrypt(plainText, key, iv) {
    var keyBytes = CryptoJS.enc.Utf8.parse(key);
    var ivBytes = CryptoJS.enc.Utf8.parse(iv);
    var encrypted = CryptoJS.AES.encrypt(plainText, keyBytes, {
        iv: ivBytes,
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
    });

    return encrypted.toString();
}

And the controller.:

    private readonly byte[] _key;
    private readonly byte[] _iv;

    public PermitController()
    {
        var rng = new RNGCryptoServiceProvider();

        _key = new byte[32];
        rng.GetBytes(_key);
      
        _iv = new byte[16];
        rng.GetBytes(_iv);
    }

        public async Task<IActionResult> Encryptori()
    {
        ViewBag.Display = "";
        ViewBag.Key = Convert.ToBase64String(_key);
        ViewBag.IV = Convert.ToBase64String(_iv);
        ApplicationUser user = await _userManager.GetUserAsync(User);
        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Encryptori(IFormCollection collection)
    {
        string TheKey = collection["Key"];
        string TheIv = collection["IV"];
        var keyBytes = Convert.FromBase64String(TheKey);
        var ivBytes = Convert.FromBase64String(TheIv);

        string encryptedName = collection["Name"];
        string encryptedAddress = collection["Address"];

        var decryptedName = Decrypt(encryptedName, TheKey, TheIv);
        var decryptedAddress = Decrypt(encryptedAddress, TheKey, TheIv);


        // Store the decrypted data in the ViewBag
        ViewBag.Display = encryptedName + "  and  " + encryptedAddress;

        ApplicationUser user = await _userManager.GetUserAsync(User);
        return View();
    }

private string Decrypt(string encryptedText, string key, string iv)
{
try
{
    var keyBytes = Convert.FromBase64String(key);
    var ivBytes = Convert.FromBase64String(iv);

    using (var aes = Aes.Create())
    {
        aes.Key = keyBytes;
        aes.IV = ivBytes;
        aes.Padding = PaddingMode.PKCS7;
        aes.Mode = CipherMode.ECB;

        var decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
        using (var ms = new MemoryStream())
        {
            using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
            {
                var encryptedBytes = Convert.FromBase64String(encryptedText);
                cs.Write(encryptedBytes, 0, encryptedBytes.Length);
            }
            ms.Position = 0;
            var decryptedBytes = new byte[ms.Length];
            ms.Read(decryptedBytes, 0, decryptedBytes.Length);
            return Encoding.UTF8.GetString(decryptedBytes);
        }
    }
}
catch (CryptographicException ex)
{
    Console.WriteLine("Decryption failed: " + ex.Message);
    return null;
}
}

I tried changing different padding mode, but still the same. Still encounter the System.Security.Cryptography.CryptographicException: ‘Padding is invalid and cannot be removed. Need help.

Add error to context with nested schemas using Zod validation

I have a Typescript application that is using Zod to validate data. The schema includes several schemas that have slightly different values with nested fields represented by other schemas as they can be reused in other places.

There is a nested object that when any object under a certain level will add an additional error to the Zod context. An example such as this

{
  a: {
    b: { // d or e should both add another error
      d: "1",
      e: "3",
    },
  },
}

So, if d failed validation I want there to be the standard Zod validation error and a custom error added to the context as well. Reading it would seem as though I would want to use superRefine to do this. However, if I add superRefine it does not seem to trigger if the validation failure happens in a nested schema.

Code: https://github.com/rlperez/so-demo-zod

If I had a schema such as this:

const BazSchema = z.string();

const BarSchema = z.object({
  baz: BazSchema
});

const FooSchema = z.object({
  bar: BarSchema
});

When I call FooSchema.parse(obj) that fails for BazSchema does not trigger superRefine if it is written like this:

const FirstSuperRefinedFooSchema = FooSchema.superRefine((data, ctx) => {
  if(!BarSchema.safeParse(data).success) {
    ctx.addIssue({
      code: 'custom',
      message: 'first super refined custom message',
    });
  }
});

and is called like this

  let parseResult = FooSchema.safeParse(wrongTypeBaz);

Output

> [email protected] dev
> npx tsc -t 'es2017' && node ./src/main.js

stupid demo

FirstSuperRefinedFoo
mapping invalid_type
{"error":[{"code":"invalid_type","expected":"object","received":"undefined","path":["bar"],"message":"Required"}]}

The expectation is that it would also have the custom error. I’ve added print statements to make sure it is not reaching superRefine. It’s as if it doesn’t raise the event any further than where it happened. I would need to manually add this to each schema? That seems like a lot of copy and paste across this schema to do that.

How does one do this?

(JavaScript) How to set a weekday as the starter and ender of a countdown instead of using an specific/static date?

So, I have this personal project that I’m trying to do more for studying purposes. It would be two timers to monitor two different events in a week, in which one would countdown the remain time of a occuring event (how much days/hours until the event ends) and the other would countdown the remaining time until the next event begins. then they would switch when it marks 0 (the current one would turn into the next and vice-versa).

Exemple: Event A would start on Friday 8PM and end on Monday 2PM, Event B would be Tuesday from 6PM until 7PM. Timer 1 (Current Event) would calculate the duration of Event A and show the countdown of the remaining time until it reaches the end in days and/or hours, while Timer 2 (Next Event) would do the same, but countingdown to show how long until it’s time for Event B to begin, on the same format (dd/hh:min:s). The moment Event A ends, Timer 1 should freeze at 00 00:00 and stays like that while Time 2 goes until the end, and only then the events would switch id’s so Event B is now Current Event and Event A is Next Event (they are weekly and will loop indefinitely).

My major struggle now is to figure how I could set the timers to start and end on given weekdays, with a specific time, and not static days, since the events have fixed weekdays to happen.

I’ve looked up the Date() method but couldn’t figure how to use it since it requests specific dates as parameters.

I’d like to keep the code as simple as possible, but any tips, suggestions, advices or possible solutions are very welcomed even if they involve more advanced ways. JavaScript is not my forte, but I think I can manage to do the loops and all the other stuff on my own – just need to figure this out to have a kickstart.

react state that is initalized by props does not update when component recieves new props [duplicate]

I am using Next.js with a component that is first skeleton-loaded while the website waits for the data (using tanstack react query):

if (isPending) {
    return <MyComponent
        name={"Loading...."}
        hobbies={[]}
    />
}

return <MyComponent name={data.name} hobbies={data.hobbies}

Inside of this component I have a state for the hobbies so that the user can mutate the hobbies list locally before sending it to the database.

function onSubmit() { // update to server }

function MyComponent(props) {
    const [hobbies, setHobbies] = useState(props.hobbies);
    
    return (
        <form>
           <h1 key={name}>{name}</h1>
           <MyList hobbies={hobbies} />
           <div>
               <input />
               <button type="button" onClick={() => {}}>add</button>
           </div>
           <button>submit</button>
        </form>
    )
}

However once the data loads, while the other data (the name) updates, the hobbies variable does not, and it stays as an empty list. This is because of the key argument I have on the h1, but when I add the key to MyList, it does not re-render. I have to go to another url then come back for it to reload the hobbies argument.

I assume this is because I am initially setting the state of the hobbies as empty, and then once the data loads, it doesn’t reupdate the state, but how do I fix this?

Trying to create “auto-generating” component

So I’m trying to build this page in a very barebones geocities style server.
It lets me use some JS, so I was trying to build some component to do this idea I had, I have built this “blog” page, and inside the directory there is a posts folder I created so I could put the posts inside as .txt files.
My idea was to save time by while building the posts component it would run through the files on this folder and inject the each text into a post:

    class Posts extends HTMLElement {
    constructor() {
      super();
    }
  
    connectedCallback() {

      this.innerHTML += `
        <div class="card">
          <h2>TEST POST</h2>
          <h5>Title description, Dec 7, 2017</h5>
          <object data="posts/test.txt">
        </div>
      `;
    }
  }
 
  customElements.define('posts-component', Posts);

Is that possible in more vanilla JS?
If so, how?

Before anyone asks, I’m just doing this for fun, for a little “challenge”.

How do I prevent my header from changing when the screen gets smaller?

I’ve installed a WordPress theme where the menu items of the headers go onto multiple lines when the screen size gets smaller. Only when the screen gets too small, it goes to the (mobile) hamburger menu (see image 3). Firstly it goes onto 2 lines and then 3 lines. Does someone know how to fix this issue? I only want it to stay onto 1 line or that the hamburger menu appears when it doesn’t fit on 1 line.

How it is on a big screen

How it gets on a smaller screen

How it gets on a smaller screen (hamburger menu)

Thanks in advance!

I don’t really know how to fix this.

My js script saves the progress file okay, but does not load it again properly

I created an online form with several fields, and I want the ability to save the progress and load it again later.

When I save it, it seems to work okay (all the info is in the json file) but when I load the saved file, not all the data is added back into the online form. Specifically the values for “regions” and “borders” are not loaded.

Can anyone see what I’m missing? Thanks.

/**
 * Saves the progress of the form inputs to a JSON file.
 */
function saveProgress() {
    const settingsForm = document.getElementById('settingsForm');
    const regionsForm = document.getElementById('regionsForm');
    const bordersForm = document.getElementById('bordersForm');
    const commandsForm = document.getElementById('commandsForm');

    const settingsData = new FormData(settingsForm);
    const regionsData = new FormData(regionsForm);
    const bordersData = new FormData(bordersForm);
    const commandsData = new FormData(commandsForm);

    let jsonObject = {};
    settingsData.forEach((value, key) => {
        if (key === 'deployments') {
            jsonObject[key] = value;
        } else if (key === 'size' || key === 'difficulty') {
            jsonObject[key] = document.querySelector(`input[name="${key}"]:checked`).value;
        } else {
            jsonObject[key] = value;
        }
    });
    regionsData.forEach((value, key) => {
        jsonObject[key] = value;
    });
    bordersData.forEach((value, key) => {
        jsonObject[key] = value;
    });
    commandsData.forEach((value, key) => {
        jsonObject[key] = value;
    });

    jsonObject["regions"] = document.getElementById('regions').value;
    jsonObject["borders"] = document.getElementById('borders').value;

    const jsonString = JSON.stringify(jsonObject, null, 2);
    const blob = new Blob([jsonString], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const downloadLink = document.createElement('a');
    downloadLink.href = url;
    downloadLink.download = 'progress.json';
    downloadLink.click();
    URL.revokeObjectURL(url);
}

/**
 * Loads the progress from a JSON file and populates the form inputs.
 */
function loadProgress() {
    const fileInput = document.createElement('input');
    fileInput.type = 'file';
    fileInput.accept = 'application/json';
    fileInput.onchange = (event) => {
        const file = event.target.files[0];
        if (file) {
            const reader = new FileReader();
            reader.onload = (e) => {
                const jsonObject = JSON.parse(e.target.result);
                document.getElementById('engine').value = jsonObject.engine || '1';
                document.getElementById('version').value = jsonObject.version || '1';
                document.getElementById('title').value = jsonObject.title || '';
                document.getElementById('key').value = jsonObject.key || '';
                document.querySelector(`input[name="size"][value="${jsonObject.size}"]`).checked = true;
                document.querySelector(`input[name="difficulty"][value="${jsonObject.difficulty}"]`).checked = true;
                document.getElementById('players').value = jsonObject.players || '2,3,4,5,6,7,8,9,10,12,14,15,16,18,20,21,22,24';
                document.getElementById('objectives').value = jsonObject.objectives || 'Standard, Assassin, Mercenary';
                document.getElementById('reserves').value = jsonObject.reserves || 'Escalate, Escalite, FlatRate(6)';
                document.getElementById('reinforcements').value = jsonObject.reinforcements || 'Border, Path, Anywhere';
                document.getElementById('initialTroops').value = jsonObject.initialTroops || '3';
                document.getElementById('kind').value = jsonObject.kind || '';
                document.getElementById('deployments').value = jsonObject.deployments || '';
                document.getElementById('regions').value = jsonObject.regions || '';
                document.getElementById('borders').value = jsonObject.borders || '';
                document.getElementById('command').value = jsonObject.command || '';
            };
            reader.readAsText(file);
        }
    };
    fileInput.click();
}

This is what the saved json file looks like

{
  "engine": "1",
  "version": "1",
  "title": "test-new",
  "key": "test-new",
  "size": "Medium",
  "difficulty": "Intermediate",
  "players": "2,3,4,5,6,7,8,9,10,12,14,15,16,18,20,21,22,24",
  "objectives": "Standard, Assassin, Mercenary",
  "reserves": "Escalate, Escalite, FlatRate(6)",
  "reinforcements": "Border, Path, Anywhere",
  "initialTroops": "3",
  "regions": "region1nr2",
  "borders": "r1,r2nr2,r3",
  "command": ""
}

But the regions and borders won’t load into the form again.

How to display scored questions qualtrics with display logic

I am making a quiz that times out after 90 mins. I used display logic on each question (if blockTimeFlag = 0) to skip to the end after the 90 mins is up but now the scores aren’t displaying at the end. It was displaying before I added the display logic. How do I get the scores to show up again without removing the display logic. I have embedded data set as blockTimeFlag = 0
Here is the code.

var headerCont = document.createElement("div");  
 headerCont.className = "header-cont";  
 headerCont.id = "header_container";  
 var header = document.createElement("div");  
 header.className = "header"  
 header.id = "header_1";  
 var timer = document.createElement("div");  
 timer.className = "timer";  
 timer.id = "timer_1";  
 timer.innerHTML =  "<span id='time'>90:00</span>";  
 headerCont.appendChild(header);  
 header.appendChild(timer);  
 document.body.insertBefore(headerCont, document.body.firstChild);
function startTimer(duration, display) {  
  var timer = duration, minutes, seconds;  
  var myTimer = setInterval(function() {  
   minutes = parseInt(timer / 60, 10)  
   seconds = parseInt(timer % 60, 10);  
   minutes = minutes < 10 ? "0" + minutes : minutes;  
   seconds = seconds < 10 ? "0" + seconds : seconds;  
   var text = ('innerText' in display)? 'innerText' : 'textContent';
   display[text] = minutes + ":" + seconds;  
   if (--timer < 0) {  
    clearInterval(myTimer);  
    timeOver();  
   }  
  }, 1000);  
 }  
 var timerSeconds = 5400,  
 display = document.querySelector('#time');  
 startTimer(timerSeconds, display);  
 var timeOver = function() {  
     document.getElementById("timer_1").innerHTML = "Time is up!";
Qualtrics.SurveyEngine.setEmbeddedData("blockTimeFlag", "1");    
$('NextButton').click();
}

How to test that a function returned without doing anything

I’m writing a suite of Jest tests, and the following question came up. How can I test that a function simply returns if it receives an invalid argument? For example, I would like to test that the function changeAge below returns immediately if it receives a newAge or id that is not a whole number.

function changeAge (id, newAge) {
  const isWholeNumber = num => Number.isInteger(newAge) && newAge >= 0
  if (!isWholeNumber(id) || !isWholeNumber(newAge)) {
    return
  } 

  const person = getPerson(id)
  person.age = newAge
}

In this example, there’s no way in the test to retrieve the person data to verify whether the age property was changed.

Cannot display image with JavaScript from Django Base

I am attempting to get a customer logo to load when a user signs into my app. To do that I am using the views function below to generate the logo url:

Views:

def view_company_logo(request):

print("GETTING LOGO")

client = Client.objects.get(user=request.user)
logo = ""
try:
    logo = client.customer.first().logo.logo.url
    print("GOT LOGO")
    return JsonResponse({"logo": logo, "media_url": settings.MEDIA_URL}, safe=False)

except Exception as e:
    print(e)
    print(f'ERROR FOR LOGO {e}')

    return JsonResponse({"logo": logo}, safe=False)

The function is attached the url below:

url(r"^get/company_logo/$", views.view_company_logo),

This is called in the base.html file in order to show the

  $(document).ready(function () {
  function get_company_logo() {
    console.log('HERE SEAN!!!!!!!');
    log('TEST');

    $.ajax({
      url: '/get/company_logo/',
      method: 'GET',
      success: function (data) {
        return create_image(data['logo'])





      },
      error: function () {
        console.log('HERE IS THE ERROR!!!')
        log('HERE IS THE ERROR!!!')
      },
    
    })
  }

  function create_image(logo) {
    document.getElementById("logo").src = logo;

  }


  get_company_logo()

Which connects to the source of this image that gets generated when the pages loads:

      <img class="img-square center" id="logo" alt="logo" style="opacity: 1" height="45" width="125">

Could someone tell me why the image is not loading? It seems like the function is never called and I am not sure why.

HTTPS link in HTML Form being converted to HTTP with 443 port on load inside Iframe

Good afternoon everyone. I am working to embed reports in our application with the report service provider of Domo. I have created the following component.

import React from 'react';

const generateFormHtml = (actionUrl, embedToken) => (
    `
    <!DOCTYPE html>
    <html>
        <body>
            <form id="embedForm" action="${actionUrl}" method="post">
                <input type="hidden" name="embedToken" value="${embedToken}" />
            </form>
            <script>
                        document.getElementById("embedForm").submit();
            </script>
        </body>
    </html>
    `
);

const generateDataUri = (html) => `data:text/html;charset=utf-8,${encodeURI(html)}`;

const ReportEmbedder = ({ actionUrl, embedToken }) => {
    const htmlContent = generateFormHtml(actionUrl, embedToken);
    const formDataUri = generateDataUri(htmlContent);

    return (
        <iframe
            className="panel embed-panel"
            src={formDataUri}
            title="Embedded Form"
            allowtransparency="false"
        />
    );
};

export default ReportEmbedder;

That component is being called inside the main page inside the html

        /// actionUrl = 'https://public.domo.com/embed/pages/XXXXX'
        /// embedToken = 'full_length_embed_token'

            <div className="panel-container">
                    <ReportEmbedder
                            actionUrl={actionUrl}
                            embedToken={embedToken}
                        />
            </div>

My problem is that when the form renders, it seems to be converting the https url to http with a port associated.

HTTP ERROR 403 Access Denied
URI: http://public.domo.com:443/embed/pages/XXXXXX
STATUS: 403
MESSAGE: Access Denied

Does anyone have any idea how this could be happening or where to look? I have a feeling it is just a configuration issue that I have overlooked but I have yet to find it.

I have worked with debugging to ensure that the URI states https through the entire process. I have confirmed that in the generateDataUri step, the encoding is not over-riding the https setting. I have had a few other engineers peer review but they have been just as confused as myself.

I am expecting the https link to continue so that the iframe loads the report from the endpoint.

What language would you reccommend for building a UI to access and manipulate large SQL databases? (Why? Benefits/Drawbacks?)) [closed]

I’m fairly new to coding and have been learning and building a personal archival database using SQL over the past few months. However, I would also like to develop a simple (at first) UI to use for viewing and interacting with the stored data. Think along the lines of a library or museum’s digital catalogue where you have a list of entries you can scroll through, each showing basic info, but then can click on any one entry to see more in-depth (linked) data.

What language would you suggest using for this? In preliminary searching, it seems like either JavaScript or a C language would be good options, but I don’t have enough experience to feel confident in fully deciding without additional input. What would you say are the benefits and drawbacks of different possibilities?

For greater detail:

  • I’m planning on using PostgresSQL because (afaik) it’s better at handling complex data relations and large data sets, which is ideal for my goals.

  • Most of my experience is in data collection, table creation, data manipulation/interpretation, and similar areas. While this is a personal project, I am hoping to learn some functional skills that could be applicable to a career in archival work (such as with a library, archive, museum, historical records, etc) and anthropology/archaeology, which is what I’m going to school for.

  • I have basic background knowledge of general programming principles, as well as previous beginner courses in JavaScript and Python, so no matter what I’ll be learning a language (or two) from a beginner level.

css custom music player range

please am having issue creating a rounded custom image indicator around album image, the dot indicator is breaking out on page load but when i press play it move back to the circle , html, i want to create custom music player, any suggestion we do

const img = document.querySelector("#img");
const playPause = document.querySelector("#playpause");
const playPauseBtn = document.querySelector("#playpause-btn");
const audio = document.querySelector("#audio");
const title = document.querySelector("#title");
const prevBtn = document.querySelector("#prevbtn");
const nextBtn = document.querySelector("#nextbtn");
const progress = document.querySelector("#progress");
const progressIndicator = document.querySelector(".progress-indicator");
const repeatBtn = document.querySelector("#repeat");

const songs = [{
    path: 'https://raw.githubusercontent.com/ustabasiibrahim/music-player/master/assets/music/1.mp3',
    displayName: 'Yıldız Tozu',
    artist: 'Ozbi',
    cover: "https://images.genius.com/ee202c6f724ffd4cf61bd01a205eeb47.1000x1000x1.jpg",
  },
  {
    path: 'https://raw.githubusercontent.com/ustabasiibrahim/music-player/master/assets/music/2.mp3',
    displayName: 'You're Somebody Else',
    artist: 'flora cash',
    cover: "https://pbs.twimg.com/media/D2NZH-2U4AAL9Xs.jpg",
  },

];

let songIndex = 2;
let isPlaying = false;

function playSong() {
  isPlaying = true;
  playPauseBtn.classList.replace("fa-play", "fa-pause");
  audio.play();
}

function pauseSong() {
  isPlaying = false;
  playPauseBtn.classList.replace("fa-pause", "fa-play");
  audio.pause();
}

function loadSong(song) {
  img.src = song.cover;
  title.textContent = song.displayName;
  audio.src = song.path;
}

function prevSong() {
  songIndex--;
  if (songIndex < 0) {
    songIndex = songs.length - 1;
  }
  loadSong(songs[songIndex]);
  playSong();
}

function nextSong() {
  songIndex++;
  if (songIndex > songs.length - 1) {
    songIndex = 0;
  }
  loadSong(songs[songIndex]);
  playSong();
}

function updateProgress(e) {
  if (isPlaying) {
    const {
      duration,
      currentTime
    } = e.target;
    const progressPercent = (currentTime / duration) * 100;
    progress.value = progressPercent;
    const indicatorAngle = (progressPercent / 100) * 360;
    const indicatorX = Math.cos((indicatorAngle - 90) * (Math.PI / 180)) * 160 + 160;
    const indicatorY = Math.sin((indicatorAngle - 90) * (Math.PI / 180)) * 160 + 160;
    progressIndicator.style.transform = `translate(${indicatorX}px, ${indicatorY}px)`;
  }
}

function progressSlide(e) {
  const {
    value
  } = e.target;
  const progressTime = Math.ceil((audio.duration / 100) * value);
  audio.currentTime = progressTime;
  if (!isPlaying) {
    const indicatorAngle = (value / 100) * 360;
    const indicatorX = Math.cos((indicatorAngle - 90) * (Math.PI / 180)) * 160 + 160;
    const indicatorY = Math.sin((indicatorAngle - 90) * (Math.PI / 180)) * 160 + 160;
    progressIndicator.style.transform = `translate(${indicatorX}px, ${indicatorY}px)`;
  }
}

function repeat() {
  repeatBtn.classList.toggle('color');
  if (repeatBtn.classList.contains("color")) {
    audio.loop = true;
  } else {
    audio.loop = false;
  }
}

playPause.addEventListener("click", () => (isPlaying ? pauseSong() : playSong()));
prevBtn.addEventListener("click", prevSong);
nextBtn.addEventListener("click", nextSong);
audio.addEventListener("timeupdate", updateProgress);
progress.addEventListener("input", progressSlide);
repeatBtn.addEventListener("click", repeat);

loadSong(songs[songIndex]);
.music-player-unique {
  max-width: 350px;
  margin: auto;
}

.disc-container-unique {
  position: relative;
  width: 300px;
  height: 300px;
  margin: auto;
}

.disc-image-unique {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  border: 5px solid #343a40;
}

.progress-container-unique {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 320px;
  height: 320px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  border: 4px solid black;
  box-shadow: 0 17px 33px rgb(189 190 193 / 1);
  display: flex;
  justify-content: center;
  align-items: center;
}

.progress-unique {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100%;
  height: 2px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  opacity: 0;
  cursor: pointer;
}

.progress-indicator {
  position: absolute;
  width: 16px;
  height: 16px;
  background-color: #007bff;
  border-radius: 50%;
  top: -8px;
  left: -8px;
  transform: translateX(0);
}

.song-title-unique {
  font-size: 18px;
  font-weight: bold;
  color: #343a40;
}

.controls-unique {
  display: flex;
  justify-content: center;
  align-items: center;
}

.controls-unique .btn-unique {
  background-color: transparent;
  border: none;
  font-size: 32px;
  color: #343a40;
  margin: 0 10px;
}

.controls-unique .btn-unique:hover {
  color: #007bff;
}
<div class="container text-center mt-5">
  <div class="music-player-unique">
    <div class="disc-container-unique">
      <img id="img" src="/src/images/music-1.jpg" alt="Music Disc" class="disc-image-unique">
      <div class="progress-container-unique">
        <input type="range" id="progress" value="0" class="progress-unique">
        <div class="progress-indicator"></div>
      </div>
    </div>
    <div class="song-title-unique mt-3" id="title">Song Title</div>
    <div class="controls-unique mt-4">
      <button id="repeat" class="btn-unique"><i class="fa-regular fa-repeat"></i></button>
      <button id="prevbtn" class="btn-unique"><i class="fa-regular fa-backward"></i></button>
      <button id="playpause" class="btn-unique"><i id="playpause-btn" class="fa-regular fa-play"></i></button>
      <button id="nextbtn" class="btn-unique"><i class="fa-regular fa-forward"></i></button>
      <button id="list" class="btn-unique"><i class="fa-regular fa-list"></i></button>
    </div>
    <audio id="audio"></audio>
  </div>
</div>

i have tried my best to make it work but seem not working, the dot not working well

How can I use a browser extension’s API within a standard website?

I’m curious about the feasibility of using the browser extension’s API directly from a standard website. Specifically, I want to understand if there’s a way to interact with the browser API from my web page’s JavaScript while complying with all security measures. I have some background in developing extensions, so I’m familiar with content scripts, background scripts, and message passing. Still, I’m unsure if it’s possible and how to apply these concepts in this context. It should be impossible, but asking is better than giving up.

Here are some aspects I’m curious about:

  1. Is it possible for a web page to call a browser API?
  2. Ensure that such interaction complies with browser security policies and respects user privacy. In extensions, this is the role of the manifest.json. Is there any other similar tool for websites?

From my understanding, content scripts might play a role, but I am unclear on how to set this up securely. Can anyone provide insights, examples or prototypes? I’m super curious about them.

To be clear, I’m currently developing an extension, not a website, but I want to explore, go crazy, and see all the possibilities and constraints. Any pointers to relevant, meaningful documentation or information would be greatly appreciated! They should be related to websites, not extensions.