Is there a way to get a similiar result to this website?

I’m trying to make a website inspired by this website, https://impomu.com. I don’t need it to have everything, like the secret prompt section and the discord advertisement. I’m mostly trying to get these main things working:

  • have a global counter (the total amount of times the button was clicked by every user that visited the site) and a local counter ( the total amount of times the button was clicked by the current user)
  • The website remembers the current count and doesn’t reset back to zero (also updates the total count in real-time)
  • when the button is clicked, a randomly picked audio plays, as well as a completely randomly generated (different scale, rotation, and position it appears on screen) animated image that pops up for a little bit

I’m mostly having a difficult time reading the website code for reference, especially about the javascript code, as I’m kinda new to it. I’m having a hard time understanding what each javascript code is responsible for and which javascript code I need for my website. Especially which javascript code triggers the animated image pop-up. I tried looking for answers to previously asked questions from this site, but the answers given aren’t what I looking for.

I’m asking if anyone can read the website’s code, explain how it works, and how to achieve a similar result.

Before looking through the website code, I thought to get the counter to work; I needed to apply an increment to the button. But now, looking through the website’s code, it doesn’t involve increment, but something else I can’t figure out.

Also, I couldn’t understand how they achieved both audio and image working, especially the image part.

Long Polling with an array php Javascript

Very new to long polling and just got this to work but trying to make it work with an array. I understand the php side of things fairly well but I’m very new to Javascript.

active_calls.php

<?php
class Calls {
  // (A) CONSTRUCTOR - CONNECT TO DATABASE
  protected $pdo = null;
  protected $stmt = null;
  function __construct () {
    $this->pdo = new PDO(
      "mysql:host=".DB_HOST.";dbname=".DB_NAME.";charset=".DB_CHARSET,
      DB_USER, DB_PASSWORD, [
      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
      PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
    ]);
  }

  // (B) DESTRUCTOR - CLOSE CONNECTION
  function __destruct () {
    if ($this->stmt !== null) { $this->stmt = null; }
    if ($this->pdo !== null) { $this->pdo = null; }
  }

  // (C) GET LATEST SCORE
  function getCalls () {
    $this->stmt = $this->pdo->prepare(
      "SELECT *, UNIX_TIMESTAMP(`call_time`) AS `unix`
       FROM `calls` WHERE call_status=1 ORDER BY `call_time` DESC"
    );
    $this->stmt->execute();
    return $this->stmt->fetch();
  }
}

// (D) DATABASE SETTINGS - CHANGE THESE TO YOUR OWN!
define("DB_HOST", "localhost");
define("DB_NAME", "xxxxx");
define("DB_CHARSET", "utf8mb4");
define("DB_USER", "xxxxx");
define("DB_PASSWORD", "xxxxx");

// (E) CHECK FOR SCORE UPDATES
if (isset($_POST["last"])) {
  // (E1) SET TIME LIMIT
  set_time_limit(30); // set an appropriate time limit
  ignore_user_abort(false); // stop when long polling breaks

  // (E2) LOOP UNTIL THERE ARE UPDATES OR TIMEOUT
  $_CALL = new Calls();
  while (true) {
    $call = $_CALL->getCalls();
    if (isset($call["unix"]) && $call["unix"] > $_POST["last"]) {
      echo json_encode($call);
      break;
    }
    sleep(1); // short pause to not break server
  }
}

active_call.html

<html>
<head>
  <link rel="stylesheet" href="style/style.css">
  <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
  <meta http-equiv="Pragma" content="no-cache" />
  <meta http-equiv="Expires" content="0" />
</head>

<table>
  <tr>
    <th>Call Time</th>
    <th>Station IP</th>
    <th>Call Status</th>
    <th>Action</th>
  </tr>
  <tr align='center'>
    <td><div id="Time"></div></td>
    <td><div id="StationIP"></div></td>
    <td><div id="CallStatus"></td>
  </tr>
</table>


<script>
// (B) LAST UPDATED TIMESTAMP
var last = 0;

// (C) AJAX LONG POLL
function GetCurrentUnixTimeStamp() {
  return Math.floor(Date.now() / 1000);
}
function poll () {
  // (C1) FORM DATA
  let data = new FormData();
  data.append("last", last);
  console.log("Fetch run", last);

  // (C2) FETCH UPDATE ON SERVER RESPONSE

  fetch("active_calls.php", { method:"POST", body:data })
  .then(res => res.json())
  .then(data => {
    console.log(data);
    // (C2-1) UPDATE HTML DISPLAY

    document.getElementById("Time").innerHTML = GetCurrentUnixTimeStamp() - data.unix;
    document.getElementById("StationIP").innerHTML = data.station_ip;
    document.getElementById("CallStatus").innerHTML = data.call_status;

    // (C2-2) NEXT ROUND
    last = data.unix;
    poll();
  })

  // (C3) CATCH ERROR - LOOP ON TIMEOUT
  .catch(err => poll());
}

// (D) GO!
window.onload = poll;
</script>
</html>

data sample

call_id call_status call_time station_ip unix
3 1 2023-07-09 11:47:51 192.168.254.200 1688921271
2 1 2023-07-08 21:36:30 192.168.200.201 1688870190

I have tried multiple times to declare as an array and attach values into the array but I’m not even sure how to loop though the array on the Javascript side to pull that data back out once I get it in properly. Seem this should be simple but I’ve been trying for weeks also just getting back into php after a few years so I’m a bit rusty.

How do I accurately click on the bug?

JavaScript beginner here…
I creates this Bug Smasher game with the following feature using HTML5 Canvas.

The bug hops randomly around the game area at a given interval. The player tries to catch the bug by clicking on it. If he succeeds, the score is incremented and the hopping interval is decremented by a number of milliseconds, so it gets harder to catch the bug.
If the game becomes too challenging, the payer can reset the speed to the initial hopping interval by clicking the Reset Speed button.
If the player wants, he can start again by resetting the score by clicking the Reset Score button.

I got everything figured out except how to click exactly on the bug. Right now the the score is recorded when I click areas that are outside but closed to the bug. I compares the click event coordinator with the bug’s coordinator and it seems off. I don’t know how to fix it.

Also, I don’t know why it doesn’t work, when I add methods to the onlick events of resetSpeedBut and resetScoreBut. However, it works, when I add the add methods to the onclick events to the button above in their HTML file.

JavaScript File

//Create the canvas
var canvas = document.createElement("canvas");

var ctx = canvas.getContext("2d");
canvas.width = 512;
canvas.height = 480;
canvas.style ="border:1px solid #000000"
document.body.appendChild(canvas);

//Background images
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function () {
    bgReady = true;
};
bgImage.src = "autumnleaves.jpg";

//Bug image
var bugReady = false;
var bugImage = new Image();
bugImage.onload = function () {
    bugReady = true;
};
bugImage.src = "ladybug.png";

//Game objects
var bug = {
    width:32,
    height:32,
};
var bugCaught = 0;
var intervalTime = 3000;

// Spawn the bug at coordinator (bug.x, bug.y) somewhere on the screen randomly
function spawnBug () {
    bug.x = 32 + (Math.random() * (canvas.width - 64));
    bug.y = 32 + (Math.random() * (canvas.height - 64));
}
spawnBug();
var reset = setInterval(function() {spawnBug()}, intervalTime);

//Canvas Click Event
canvas.addEventListener("mousedown", click, false)
function click(e) {
    e.preventDefault();
    //Mouse location when clicked
    mouseXinCanvas = e.clientX;
    mouseYinCanvas = e.clientY;
    //Compare clicked mouse location with the bug location
    if(mouseXinCanvas > bug.x 
        && mouseXinCanvas < bug.x + 50
        && mouseYinCanvas > bug.y 
        && mouseYinCanvas < bug.y + 170){
    
            //Add score when bug is clicked
            bugCaught++;
            //Increase the speed of the bug
            clearInterval(reset);
            intervalTime -= 500;
            //Update the intervalTime in the setInterval function
            reset = setInterval(function() {spawnBug()}, intervalTime);
            //Set limit for intervalTime
            if(intervalTime < 500){
                window.alert("You win! The game will be reset now.");
                //Reset interval when limit is hit
                resetScore();
            }
    }
}

//Reset speed function
function resetSpeed (){
    clearInterval(reset);
    intervalTime = 3000;
    spawnBug();
    reset = setInterval(function() {spawnBug()}, intervalTime);
}

//Add reset speed function to Reset Speed Button
let resetSpeedBut = document.getElementById("resetSpeedBut");
resetSpeedBut.onclick = resetSpeed;

//Reset Score
function resetScore() {
    bugCaught = 0;
    resetSpeed();
}

//Add reset score function to Reset Score Button
let resetScoreBut = document.getElementById("resetScoreBut");
resetScoreBut.onlick = resetScore;

//Draw everything
function render(){
    if(bgReady){
        ctx.drawImage(bgImage, 0, 0);
    }

    if(bugReady){
        ctx.drawImage(bugImage, bug.x, bug.y);
    }

    //Display the score
    ctx.fillStyle = "rgb(250, 250, 250)";
    ctx.font = "24px Helvetica";
    ctx.textAlign = "left";
    ctx.textBaseline = "top";
    ctx.fillText("Score: " + bugCaught, 30, 30);
}

// The main game loop
function main () {
    render();
    // Request to do this again ASAP
    requestAnimationFrame(main);
};

// Cross-browser support for requestAnimationFrame
var w = window;
requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;

// Let's play this game!
main();

HTML File

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>BugSmasher</title>
        <link rel="stylesheet" href="assig3.css">
        
    </head>
    <body>
        <h1>BugSmasher</h1>
        <script src="assig3jsfile.js" defer></script>
       <div>
            <input type="button" value="Reset Score" id="resetScoreBut" class="Header" onclick="resetScore()">
            <input type="button" value="Reset Speed" id="resetSpeedBut" class="Header" onclick="resetSpeed()">
        </div>
        
    </body>
</html>

TYIA for all your helps!

Step to make a project with Google sheet api to map in realtime

Can someone walk me through how I can do this project?
I have to get a list of the jobs, job progress, and addresses from a Google sheet file and show it on a map.
A couple of things to mention:
The map has to be updated once the job status has changed and new jobs have been added.
The Google sheet should not be shared with a publicly accessible link.
They want to add new google sheets in the future without any coding knowledge.
Later, they want different spreadsheet access based on the role of the person logged in.

useEffect() hook is not triggered?

There is a problem I’m currently experiencing with. The keysType state value is set to null because it’s being used for displaying other keyboard types. The thing is I want it to display the current keyboard on the first load by using useEffect() hook to append the keysArray variable. I am expecting that its value will be keysArray but it keeps the default value which is null. So that’s why the browser throws the error:

TypeError: null is not an object (evaluating 'keysType.map')

Does our community has a solution to this problem?

import { useEffect, useState } from "react";
import { BsArrowReturnLeft, BsGlobe2, BsShift, BsShiftFill } from "react-icons/bs";
import { GoSmiley } from "react-icons/go";
import { IoBackspaceOutline } from "react-icons/io5";
import { twMerge } from "tailwind-merge";

export default function Keyboard(){
    const keysArray = [
        // ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
        // ['-', '/', ':', ';', '(', ')', '$', '&', '@', '"'],
        // ['#+=', '.', ',', '?', '!', ''', 'backspace'],
        ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'],
        ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'],
        ['caps', 'z', 'x', 'c', 'v', 'b', 'n', 'm', 'backspace'],
        ['num', 'lang', 'emoji', 'space', 'return']
    ];

    const [keysType, setKeysType] = useState(null);
    const [caps, setCaps] = useState(false);
    const [num, setNum] = useState(false);

    useEffect(() => {
        setKeysType(keysArray);
    }, []);

    const Key = ({ children, className }) => {
        return (
            <div className={twMerge('flex justify-center items-center w-10 bg-gray-800/30 py-3 px-1 rounded-md m-[3px] text-gray-100 transition-all duration-200 active:bg-gray-700/40 active:transition-none', className)}>
                {children}
            </div>
        )
    }

    function generate(key){
        switch(key){
            case 'backspace':
                return (
                    <Key className='w-[54px]'>
                        <IoBackspaceOutline/>
                    </Key>
                )
            case 'caps':
                return (
                    <Key className='w-[54px]'>
                        {caps ? <BsShiftFill/> : <BsShift/>}
                    </Key>
                )
            case 'num':
                return (
                    <Key className='text-sm w-9'>
                        <p>{num ? 'ABC' : '123'}</p>
                    </Key>
                )
            case 'emoji':
                return (
                    <Key className='w-8'>
                        <GoSmiley/>
                    </Key>
                )
            case 'lang':
                return (
                    <Key className='w-8'>
                        <BsGlobe2/>
                    </Key>
                )
            case 'space':
                return (
                    <Key className='w-52'></Key>
                )
            case 'return':
                return (
                    <Key className='w-28'>
                        <BsArrowReturnLeft/>
                    </Key>
                )
        }
    }

    return (
        <div className='absolute bottom-0 z-10 bg-gray-900/90 backdrop-blur p-1 pb-12 w-full'>
            <div className="flex flex-col">
                {keysType.map(keys => (
                    <div className="flex justify-center w-full">
                        {keys.map(key => (
                            <>
                                {generate(key)}
                            </>
                        ))}
                    </div>
                ))}
            </div>
        </div>
    )
}

Switch case failing to call recursively another function

I am trying to call recursively another function “cityname()” with switch case#1 and I am getting
“TypeError: cityname is not a function”
the purpose is to give users option to enter the City name again and again if the user requests.

Note: I have excluded the other cases which are working fine.

import axios from "axios";
import readlineSync from "readline-sync";

cityname()

function cityname(){
const apiKey = 'xyz';
var name = readlineSync.question(`Enter City Name:n`);
return getWeatherData(name,apiKey)
})


function getWeatherData(cityname, apiKey) {
    axios.get(`https://api.openweathermap.org/data/2.5/weather?q=${cityname}&appid=${apiKey}`)
    .then((res)=>{
        let data = res.data
        var options = readlineSync.questionInt(`Select an option below for ${cityname}n
        1. Change Cityn
        0. Exitn`)

        switch(options)
        {
        
        case 1: cityname();
        case 0: console.log('Exiting the program...');
        break;
        default:
        console.log('Invalid option. Please try again.');
        break;
         }
    })
}

Puppeteer scraping nextPage

I can’t seem to make my Puppeteer script scrape one new page at a time. It seems to scrape page2 and 3 several times. Can someone help me fix this?

Right now my Code is this:

   import puppeteer from 'puppeteer';
   
   
   (async () => {
     const browser = await puppeteer.launch({
       headless: false,
     });
     const page = await browser.newPage();
   
   
     // Go to the initial page
     await page.goto('https://clerk.house.gov/Votes');
   
     let hasNextPage = true;
   
     while (hasNextPage) {
       const nextButton = await page.waitForSelector('a[aria-label="Next"] span[class~="fa"]', { timeout: 5000 }).catch(() => null);
       if (nextButton) {
         console.log('Processing page:', page.url());
   
         // Place your code to extract data or perform actions on the current page here
   
         await nextButton;
         await nextButton.click('a[aria-label="Next"] span[class~="fa"]');
         await page.waitForNavigation();
       } else {
         hasNextPage = false;
       }
     }
   
     await browser.close();
   })();

And the results are:

And the results look like this:

Processing page: https://clerk.house.gov/Votes
Processing page: https://clerk.house.gov/Votes#
Processing page: https://clerk.house.gov/Votes?page=2
Processing page: https://clerk.house.gov/Votes?page=2#
Processing page: https://clerk.house.gov/Votes?page=2#
Processing page: https://clerk.house.gov/Votes?page=3
Processing page: https://clerk.house.gov/Votes?page=3#
Processing page: https://clerk.house.gov/Votes?page=3#
Processing page: https://clerk.house.gov/Votes?page=3
Processing page: https://clerk.house.gov/Votes?page=3#
Processing page: https://clerk.house.gov/Votes?page=3#
Processing page: https://clerk.house.gov/Votes?page=3
file:///Users/amitkumar/Desktop/Puppeteer_project/node_modules/puppeteer-core/lib/esm/puppeteer/api/ElementHandle.js:577
throw new Error(error);

How can I properly upload Next.js build files using FileZilla without exposing server files and directories?

I have executed the command npm run build, which triggers the Next.js build process and generates a .next folder containing various files and directories. When I attempt to upload these files using FileZilla to my server, the browser displays all the files and directories instead of serving the application.

Here’s an example of the file structure that is visible in the browser after uploading:
enter image description here

How can I properly configure FileZilla or take appropriate steps to upload only the necessary files from the .next folder, while preventing the exposure of sensitive server files and directories?

While loop to update game engine blocks node event loop

I am building a multiplayer game using Node.js. To continuously update the state of all games, I do the following

while (true) {
  for (const game of games) {
    game.update()
  }
}

This apparently results in the node event loop being blocked. What is the proper technique here?

The game is real-time and so needs to be continuously updated.

How can I create a sticky horizontal scrollbar for a div with content taller than the viewport?

I’d like to create a div with no scrollbars vertically, but scroll bars if needed horizontally, which are sticky with respect to the viewport. I don’t want to the user to have to scroll to the bottom of the page to scroll horizontally.

GitHub does this for any file such as CREDITS.

middle of the viewport

Bottom of the viewport:

bottom of the viewport

This question look promising, but I have no jQuery.

How to upload files to Firebase Storage and get the URL to save in mongoDB database

I am creating a Post based application where a user can post pictures and text.
I want to save the images on Firebase Storage bucket and get the image link immediately and store the image and the photo description text to my database

I am using Node, Express and Mongo DB
.
Below is my Code

import ModalStyles from "./_createpost.module.scss";
import {
    ref,
    uploadBytes,
    getDownloadURL
} from "firebase/storage";
import { storage } from "../../../config/firebaseConfig";
import { faCamera, faPhotoFilm } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useContext, useEffect, useState } from "react";
import UserContext from "../../../context/userContext";
import { uuid } from "uuidv4";
import { v4 } from "uuid";
import axios from "axios";



interface IModalProps {
}

const Modal = ({ }: IModalProps) => {
    const user = useContext(UserContext)
    const [imageUpload, setImageUpload] = useState<FileList | null>({} as FileList);
    const [postDesc, setPostDesc] = useState<string>('');
    const [imageUrls, setImageUrls] = useState<Array<string>>([]);


    const convertToBlob = (file: File): Promise<Blob> => {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onloadend = () => {
                const blob = new Blob([reader.result as ArrayBuffer], { type: file.type });
                resolve(blob);
            };
            reader.onerror = reject;
            reader.readAsArrayBuffer(file);
        });
    };

    const uploadImages = async () => {

        if (!imageUpload) return;

        let promises: string[] = [];

        for (let index = 0; index < imageUpload.length; index++) {
            /* 
            const { name, type } = imageUpload[index];
            const file = new File([name], name, { type: type });
            const blob = await convertToBlob(file); 
            */
            const blob = await convertToBlob(imageUpload[index]);

            const imageRef = ref(storage, `images/${imageUpload[index].name + v4()}`);

            uploadBytes(imageRef, blob).then((snapshot) => {
                getDownloadURL(snapshot.ref).then((urls) => {
                    console.log(urls);
                    
                    promises.push(urls)
                    setImageUrls(prev => [...prev, urls]);
                });
            }).catch(err => console.log('An Error Occured!', err))
        }

        return promises;
    };

    const uploadFile = async (e: React.FormEvent) => {
        e.preventDefault();

        const imgs = uploadImages();
        console.log(imgs);
    
        if (!imgs) return;
           try {
               const response = await axios.post(`http://localhost:5000/post/create`, { creator_id: "64af540d576b8737651135a4", post_description: postDesc, photos: imgs });
               if (response.data) console.log('image uploaded successfully');
     
           } catch (error) {
               console.log('An Error occured while uploading the post');
     
           } 

    }
    const onchange = (event: React.ChangeEvent<HTMLInputElement>) => {
        const files = event.target.files;
        setImageUpload(files);

    }


    return <div className={ModalStyles.modal__container}>
        <h4 className={ModalStyles.modal__title}>Create Post</h4>
        <div className={`divider ${ModalStyles.modal__divider}`}></div>

        <div>
            <div className={`${ModalStyles.post__post_header} mt-1`}>
                <img src={user.profilePixs} className={ModalStyles.post__user_pixs} alt={user.firstname} />
                <div className={ModalStyles.post__post_info}>
                    <p className={ModalStyles.post__user_name}>{user.firstname} {user.lastname}</p>
                    <p>Public</p>
                </div>
            </div>
            <form className={ModalStyles.modal__post_inputField} onSubmit={uploadFile}>
                <textarea name="post_desc" id="post_desc" className={ModalStyles.modal__description} value={postDesc} onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setPostDesc(e.target.value)}></textarea>
                <div className={`divider ${ModalStyles.modal__divider}`}></div>
                <p className={ModalStyles.modal__addPhotoText}>
                    <span>  Add to your Post</span>

                    <FontAwesomeIcon icon={faPhotoFilm} size="2xl" className={ModalStyles.modal__addPhotoIcon} />
                    <input type="file" name="photo" id="photo" multiple onChange={onchange} accept="image/png, image/jpeg" className={ModalStyles.modal__addPhotoIcon} />

                </p>
                <input type="submit" value="Post" className={ModalStyles.modal__submitBtn} />
            </form>
        </div>
    </div>;
};

export default Modal;

It always return an empty ARRAY of the images from the Promise.

Then after sending and EMPTY ARRAY to my DB, the urls are return. I know its due to Async function but I cant figure how to make it fininsh the first request before the next one as I want the urls to be available before making the next move

Tried the above code but no way forward

Getting unusual error whilst trying to get an iframe element by id

Hello,

I have been trying to figure out why my program is not working. What I am trying to do is grab an id from an iframe but it just doesn’t seem to work. I have tried multiple methods in attempt to fix this bug but to my suprise keep getting an error that says ####.js:27 Uncaught (in promise) TypeError: Cannot read properties of null (reading 'style'). Here is my code:

function.js


    (() => {
        var iframe = document.createElement('iframe');
                   iframe.style.position = 'absolute';
                   iframe.style.top = '20%';
                   iframe.style.right = '40%';
                   iframe.style.width = '440px';
                   iframe.style.height = '490px';
                   iframe.style.borderRadius = '1rem';
                   iframe.style.border = 'none';
                   iframe.style.boxShadow = '0 .5rem 1rem rgba(0,0,0,.15)';
                   iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(`<p id="hello"></p>`);

                   document.body.append(iframe);

                   var iFrameContent = iframe.contentWindow.document.getElementById('hello');
                   iFrameContent.style.display = 'none';
                   console.log('iframe.contentWindow =', iframe.contentWindow);
    })();

index.html

<script src="function.js">

???

Regular expression getting two words from a sentence

With regular expressions how would I get two phrases from a sentence with this kind of structure

“change my pain level to 3

be able to build a system so it detects a pattern “change my” – and provides suitable hints from an array – let fieldNameArray = [“pain level”, “swelling”, “wound opening”]

then depending on the found first word(s) predict suitable values from another array
“change my pain level to ” let fieldOptions = [“1”, “2”, “3”, “4”, “5”]

in finding the two phrases from this pattern create a json object

let obj = {“name”: “pain level”, “value”: “3”}


my current script looks like this

  textAnalysis(text){
    console.log("text", text);
    var fieldNames = ["pain level", "swelling", "wound opening"];
    let matchNames = fieldNames.join("|");
    console.log("matchNames", matchNames);

    let regEx = "(?:b|')("+matchNames+")(?:b|')";


    console.log("regEx", regEx)
  }

im getting user not found when trying to send an OTP email on the frontend, but it works on Insomnia

I am creating an OTP function to reset password which works via insomnia, when trying to connect this to the frontend its not working, i keep getting the error user not found from the verifyuser function. I think its because it queries the email and the email has a %40 instead of the @ sign in the query. I’m not sure if thats the case but wondering if there’s a way to get around this. I am verifying the user so the OTP is tied to their account.

Below are my functions, I haven’t even tested the verifyotp and resetpassword on the client side yet since i hit a roadblock on the generateotp part

Another thing, for some reason my email address doesn’t seem to work via the .env file but every other env variable does

export const verifyUser = async (req, res, next) => {
    try { 
        const { email } = req.method == "GET" ? req.query : req.body;

        // check the user existance
        const exist = await User.findOne({ email });
        if(!exist) return res.status(404).send({ error : "Can't find User!"});
        next();

    } catch (error) {
        return res.status(404).send({ error: "Authentication Error"});
    }
}


export const generateOTP = async (req, res) => {
    const {email} = req.body
    try {
    req.app.locals.OTP = await otpGenerator.generate(6, {lowerCaseAlphabets: false, upperCaseAlphabets: false, specialChars: false})
    const ACCESS_TOKEN = await oAuth2Client.getAccessToken();
    let config =  {
    service: 'gmail',
    auth: {
    type: "OAuth2",
    user: '[email protected]',
    pass: process.env.PASS,
    clientId: process.env.CLIENT_ID,
    clientSecret: process.env.CLIENT_SECRET,
    refreshToken: process.env.REFRESH_TOKEN,
    accessToken: ACCESS_TOKEN,
    }
}

    let transporter = nodemailer.createTransport(config)

    let message = {
        from: process.env.USER,
        to: email,
        subject: "Reset your password",
        text: `Your OTP is ${req.app.locals.OTP}`,
        html: `<b>Your OTP is ${req.app.locals.OTP}</b>`
    };

    transporter.sendMail(message).then(
        (info)=> {return res.status(201).json({
        msg: 'Message sent successfully!', 
        info: info.messageId, 
        preview: nodemailer.getTestMessageUrl(info)})}
        );      
    } catch (error) {
        res.status(500).send(error)
    }
}

export const verifyOTP = async (req, res) => {
    const {code} = req.query;
    if(parseInt(req.app.locals.OTP) === parseInt(code)){
        req.app.locals.OTP = null // reset otp value
        req.app.locals.resetSession = true // start session for reset password
        return res.status(201).send({msg: 'Verified OTP'})
    }
    return res.status(400).send({error: 'Invalid OTP'})
}

export const createResetSession = async (req,res) =>{
    if (req.app.locals.resetSession){
        req.app.locals.resetSession = false // allow access to this route only once
        return res.status(201).send({msg:'Access granted'})
    }
    return res.status(440).send({error: 'Session expired'})
}

export async function resetPassword(req,res){
    try {       
        if(!req.app.locals.resetSession) return res.status(440).send({error : "Session expired!"});
        const { email, password } = req.body;
        const user = await User.findOne({email})
        if (!user) {return res.status(404).send({error : "User not Found"})}
        const hashedPassword = bcrypt.hashSync(password, 5)
        await User.updateOne({ email:user.email },{ $set: {password: hashedPassword}})
                return res.status(201).send({ msg : "Password Updated...!"})
    } catch (error) {
        return res.status(500).send({ error })
    }
}

here are my routes

router.post("/login", login)
router.post("/logout", logout)
router.get('/generateOTP',verifyUser,localVariables, generateOTP)
router.get('/verifyOTP',verifyUser,verifyOTP)
router.get('/createResetSession',createResetSession)
router.put('/resetPassword',verifyUser, resetPassword)