Can’t logout from app that uses Passport.js, passport-google-oauth20

I’ve tried different approaches but none of them worked. My current logout function looks like this:

authRouter.post('/logout', (req, res, next) => {
  res.clearCookie('connect.sid'); 
    req.logout(function(err) {
        req.session.destroy(function (err) { 
            res.send();
        });
    });
});

The requests for this endpoint go through, but they are not effective in actually logging out the user

I have to note that this function:

  • does not remove/change the row in the sqlite db that stores the session
  • does not remove/change the cookie stored by the browser
  • does not stop the user from using secured endpoints, I use this function to check if the user should be able to access endpoints:
const isAuth = (req, res, next) => {
  if (req.user) next();
  else {
    res.json({ loggedIn: false });
  }
};

For the record, this is how I make the request on my frontend:

await axios.post('/auth/logout', { withCredentials: true });

I’ve seen posts online claiming that this is intentional but that doesn’t seem right to me. I understand the logic that a google user should remain logged in on my app as long as they are logged in to their google account anywhere else on the browser but it should still be possible to exclusively be logged out of my app. If a user has to specifically log into my app they should be able to log out. I definitely don’t want to use a method where my user has to log out of every google app. It seems silly to document logging out of google oauth if it’s not possible (https://www.passportjs.org/tutorials/google/logout/)

Mongodb atlas failing to connect with Node Js (‘ERR_SSL_TLSV1_ALERT_INTERNAL_ERROR’)

I am trying to build a project using MONGO DB ATLAS, but as i’m trying to connect to the database i keep getting this error
return new error_1.MongoNetworkError(error_1.MongoError.buildErrorMessage(err), { cause: err });
^

MongoNetworkError: 640B0000:error:0A000438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error:c:wsdepsopensslopensslsslrecordrec_layer_s3.c:1586:SSL alert number 80

at connectionFailureError (C:UsersACER USERDesktopworkcodeFRED_APP_AI_SERVERnode_modulesmongoosenode_modulesmongodblibcmapconnect.js:379:20) 
at TLSSocket.<anonymous> (C:UsersACER USERDesktopworkcodeFRED_APP_AI_SERVERnode_modulesmongoosenode_modulesmongodblibcmapconnect.js:285:22)  
at Object.onceWrapper (node:events:629:26)
at TLSSocket.emit (node:events:514:28)
at emitErrorNT (node:internal/streams/destroy:151:8)
at emitErrorCloseNT (node:internal/streams/destroy:116:3)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {

connectionGeneration: 6,
[Symbol(errorLabels)]: Set(1) { ‘ResetPool’ },
[cause]: [Error: 640B0000:error:0A000438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error:c:wsdepsopensslopensslsslrecordrec_layer_s3.c:1586:SSL alert number 80
] {
library: ‘SSL routines’,
reason: ‘tlsv1 alert internal error’,
code: ‘ERR_SSL_TLSV1_ALERT_INTERNAL_ERROR’
}
}

  1. I’ve tried Whitelisting my ip address, it still doesn’t work
    2.I’ve crosschecked my MongoDb uri, it’s correct

  2. I’ve tried Whitelisting my ip address, it still doesn’t work
    2.I’ve crosschecked my MongoDb uri, it’s correct but it’s still not working

Sending postmessage() to iframe instantly as the iframe loads in Angular

I have a system where the outside project where the iframe is integrated is in angular, and the iframe code is also in angular. The iframe has certain query parameters like login id, password that get read instantly as the iframe loads, and works fine. A have to send another set of data that also need to be read instantly, what that i came across postmessage() and used it.

Outside project code:

      <iframe #challanFlowIframe
      src="http://url/query?username=&password="
      style="height: 600px; width: 1000px;"
      frameborder="50"
      (load)="validateAdminRole()"
      >
      </iframe>
  validateAdminRole(){
    const iframeWindow = this.challanFlowIframe.nativeElement.contentWindow;
    iframeWindow.postMessage('ADMIN', '*');
  }

the validateAdminRole() function is written inside the same component where the html template is present.

Iframe code:

In the main.ts of the iframe project i try to read the data, this is a standalone component project

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

import { UtilService } from './app/shared/util.service'

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.error(err));


  window.addEventListener('message', (event) => {
    if (event.data) {
      let utilService = new UtilService()
      utilService.saveRoleOfCaller(event.data)
    }
  })

What i find is that despite the code written in main.ts, the constructor and ngOnInit() runs before this function to read the message. Inside the ngOnInit() the code to read the query parameters is present, with the same i also want to read the role sent using postmessage()

in this way i make the standalone app

  ngDoBootstrap() {
    const element = createCustomElement(GenerateChallanDetailsComponent, {
      injector: this.injector,
    });
    customElements.define('app-generate-challan-details', element);
  }

Using: Angular 17

The problem is why does the postmessage() takes a while like 2-3 seconds to read the message. And is there a better way if not solution of this to get the role instantly.

Thanks for the help, i hope was able to explain the problem.

I read post from MDN and a couple of medium, tried to listen to the message from the component generatechallan (from the constructor, ngOnInit(), and event outside the class ie with plain javascript to find the time it takes to read the message) but didnt find any significant change. It sill takes around 2-3 second to read it.

who you can used the phone on good way?

leg
charging
display
heating

the phone will be not leg the phone will be not heat and the phone will be charged in better that things I am expecting and I love the iPhone and I accepted that it will be not heat in comings new iPhone

Pathway from root to a given node

I have an m-ary or n-ary tree printed out like this
A
B C
D E F G H
I J

I want to create a function in Java like helper(String node, LinkedList<> list) where node is the alphabet typed in, if we input F so the function return the list of:[A,B,F] and I am only able to access the root and its subnode as provided code from the professor

I have tried this but unsuccessful, please help meee :<

private LinkedList280 helper(String skillName, LinkedList280 res) {

        if (Rootnode == null) return res;

        if(Rootnode.item().getSkillName().equals(skillName)){
            res.insert(Rootnode.item());
            return res;
        }

        BasicMAryTree280<Skill> temp = this.clone();

        System.out.println(rootNode.subnode(1).item());
        while (!res.isEmpty()){
            for (int i = 1; i < lastChildIndex; i++) {
                res.insert(Rootnode.subnode(i).item());
                crossTree(skillName,res,rootNode.subnode(i));
            }
        }

        return res;

}

Explained above
Professor wants me to implement a recursive helper function

client X, Y not giving the correct position of a mouse

im currently working on a project and im trying to make a component to move exactly as where the mouse move and it doesnt returns different place everytime it moves, heres my code:

window.addEventListener('mousemove', (event) => {
        const mousePos = { x: event.clientX, y: event.clientY };
        const infoElement = document.getElementById('info');
        infoElement.style.top = mousePos.y + "px";
        infoElement.style.left = mousePos.x + "px";
      });

heres what happen:
enter image description here

is there any fix to this?

Youtube space invaders tutorial array collision issue

Hi there I hope everyone’s well.

I have this game tutorial here I have nearly completed from a Mr. Chris Jones on youtube.
This is the tutorial here https://www.youtube.com/watch?v=MCVU0w73uKI

I have virtually everything done that he has listed off as tasks in the video,
there’s just one issue it seems where in the collision detection,
when the particle hits the invader grid,
it erases the whole grid.

I don’t believe it actually removes the grid array either as sometimes a shot will come out of an invisible grid.

Help to understand where I have mistaken something would be great but I’m also just trying to reach out and get some sound advice as the people I live and work with don’t really like talking about math and programming work so it’s tough to keep motivated.

I didn’t find much info on op’s tutorial written by others so I was hoping this would also create a paper trail for following along as I had some trouble writing the thing out, only going by what he said. I don’t mind it being used as reference but if it’s too much than please remove the question.

Anyways, much love and thanks.

const scoreCounter = document.querySelector('#scoreCounter')
const canvas = document.querySelector("canvas");
const c = canvas.getContext("2d");
canvas.width = 1024;
canvas.height = 576;
//Player class to be made for 
//abstraction purposes
//keep function titles simple so they make sense in usage
//Example: Player.draw() as you know it will obviously draw the player
class Particle {
  constructor({position, velocity, radius, color, fades}) {
    this.position = position
    this.velocity = velocity
    this.radius = radius
    this.color = color
    this.opacity = 1
    this.fades = fades
  }
  draw() {
    c.save()
    c.globalAlpha = this.opacity
    c.beginPath()
    c.arc(this.position.x, this.position.y, this.radius, 0, Math.PI * 2)
    c.fillStyle = this.color
    c.fill()
    c.closePath()
    c.restore()    
  }
  update() {
    this.draw()
    this.position.x += this.velocity.x
    this.position.y += this.velocity.y
    if(this.fades)
    this.opacity -= 0.01
  }
}//end of projectile class
class projectile{
  constructor({position, velocity}) {
    this.position = position
    this.velocity = velocity
    this.radius = 4
  }
  draw() {
    c.beginPath()
    c.arc(this.position.x, this.position.y, this.radius, 0, Math.PI * 2)
    c.fillStyle = 'red'
    c.fill()
    c.closePath()    
  }
  update() {
    this.draw()
    this.position.x += this.velocity.x
    this.position.y += this.velocity.y
  }
}//end of projectile class
class Player {
  constructor() {    
    this.velocity = {
      x: 0,
      y: 0,
    }
    this.rotation = 0
    this.opacity = 1
    const image = new Image();
    image.src ='./img/spaceship.png';
    image.onload = () => {
      const scale = 0.15
      this.image = image
      this.width = image.width*scale
      this.height = image.height*scale
      this.position = {
        x: canvas.width / 2 - this.width / 2,
        y: canvas.height - this.height - 20       
      }      
    }    
  }//end of construct
  rotateImage() { // separating math functionally so it's easier to read
    c.translate(
      player.position.x + player.width / 2, 
      player.position.y + player.height / 2
    )
    c.rotate(this.rotation)
    c.translate(
      -player.position.x - player.width / 2, 
      -player.position.y - player.height / 2)
  }
  draw() {
    //c.fillStyle = "red";
    //c.fillRect(this.position.x, this.position.y, this.width, this.height);
    c.save()
    c.globalAlpha = this.opacity
    this.rotateImage()
    c.drawImage(
      this.image, 
      this.position.x, 
      this.position.y,
      this.width,
      this.height)  
    c.restore()    
  }  
  updateLocation() {
    if(this.image){
    this.draw()
    this.position.x += this.velocity.x
    }    
  }
}//End of player class
class invaderProjectile{
  constructor({position, velocity}) {
    this.position = position
    this.velocity = velocity
    this.width = 3
    this.height = 10
  }
  draw() {
    c.fillStyle = 'orange'
    c.fillRect(this.position.x, this.position.y, this.width, this.height)  
     
  }
  update() {
    this.draw()
    this.position.x += this.velocity.x
    this.position.y += this.velocity.y
  }
}//end of invaderProjectile class
/*
This is the start of the Invader class.
*/
class Invader {
  constructor({position}) {    
    this.velocity = {
      x: 0,
      y: 0,
    }
    this.rotation = 0
    const image = new Image();
    image.src ='./img/invader.png';
    image.onload = () => {
      const scale = 1
      this.image = image
      this.width = image.width*scale
      this.height = image.height*scale
      this.position = {
        x: position.x,
        y: position.y       
      }      
    }    
  }//end of construct
  rotateImage() { // separating math functionally so it's easier to read
    c.translate(
      player.position.x + player.width / 2, 
      player.position.y + player.height / 2
    )
    c.rotate(this.rotation)
    c.translate(
      -player.position.x - player.width / 2, 
      -player.position.y - player.height / 2)
  }
  draw() {
    //c.fillStyle = "red";
    //c.fillRect(this.position.x, this.position.y, this.width, this.height);
    c.save()
    this.rotateImage()
    c.drawImage(
      this.image, 
      this.position.x, 
      this.position.y,
      this.width,
      this.height)  
    c.restore()    
  }  
  updateLocation({velocity}) {
    if(this.image){
    this.draw()
    this.position.x += velocity.x,
    this.position.y += velocity.y
    }    
  }
  shoot(invaderProjectiles) {
    invaderProjectiles.push(
      new invaderProjectile({
      position: {
        x: this.position.x + this.width / 2,
        y: this.position.y + this.height
      }, 
      velocity: {
        x: 0,
        y: 5        
      }
    }))    
  }
}//End of invader class

/*
Start of the grid class
this grid defines the space in which the invaders form together
*/
class Grid {
  constructor(){
    this.position = {
      x:0,
      y:0
    }    
    this.velocity = {
      x:3,
      y:0
    } 
    this.invaders = []
    const columns = Math.floor((Math.random() * 10) + 5)
    const rows = Math.floor((Math.random() * 5) + 2)
    //variable helps bounce grid to left side
    this.width = columns * 30
    for(let x=0; x<columns;x++){
      for(let y=0;y<rows;y++) {
        this.invaders.push(new Invader({position: {
          x: x*30,
          y: y*30
        }        
        }))        
      }
    }
    console.log('this.invaders:=>',this.invaders)
  } 
  updateLocation() {
    this.position.x += this.velocity.x
    this.position.y += this.velocity.y
    this.velocity.y = 0
    if (
      this.position.x + this.width >= canvas.width ||
      this.position.x <= 0) { //<= bounces grid back right
      this.velocity.x = -this.velocity.x
      this.velocity.y = 30 //brings grid down by 1 increment every bounce
    }
  }
}//end of grid class

/*
This is where we initiate the new objects
for the animate functions to use
*/
const player = new Player()
const projectiles = []
const grids = []
const invaderProjectiles = []
const particles = []
//defines the keys for input
const keys = {
  a: {pressed:false},  
  d: {pressed:false},  
  space: {pressed:false}} 

//if statement that allows user to move player left or right
function moveLeftOrRight() {
  if (keys.a.pressed && player.position.x >= 0) {
    player.velocity.x = -7 
    player.rotation = -0.15
  }
  else if (
    keys.d.pressed && 
    player.position.x +player.width <= canvas.width
  ) {
    player.velocity.x = 7 
    player.rotation = 0.15
  }
  else {player.velocity.x = 0, player.rotation = 0}
}

//refreshes the player projectile sprite so it moves across the screen
function shootProjectile() {  
  projectiles.forEach((projectile, index) => {
    if(projectile.position.y + projectile.radius <= 0){
      setTimeout(() => {
        projectiles.splice(index, 1)
      }, 0)      
    } else {
      projectile.update()
    }    
  })
}

function enemyShoot(grid) {
  invaderProjectiles.forEach((invaderProjectile, index) => {
    if(invaderProjectile.position.y + 
      invaderProjectile.height >= 
      canvas.height) {
      setTimeout(() => {
        invaderProjectiles.splice(index, 1)
      },0)
    } else{
      invaderProjectile.update()
    }    
    if(
      invaderProjectile.position.y + 
      invaderProjectile.height >=
      player.position.y &&
      invaderProjectile.position.x +
      invaderProjectile.width >=
      player.position.x &&
      invaderProjectile.position.x <= player.position.x +
      player.width
      ) {
        setTimeout(() => {
          invaderProjectiles.splice(index, 1)
          player.opacity = 0
          game.over = true
        },0)
        setTimeout(() => {          
          game.active = false
        },2000)
        createParticles({
          object: player,
          color: 'white',
          fades:true
        })
        console.log('youloselol')}    
  })
  if (frames % 100 === 0 && grid.invaders.length > 0) {
    grid.invaders[
                  Math.floor(Math.random() * grid.invaders.length
                  )].shoot(invaderProjectiles)
  }  
}//end of enemy shoot
function animateInvaderGrid() {  
  grids.forEach((grid, gridIndex) => {
    grid.updateLocation()         
    //enemie projectiles
    enemyShoot(grid)
    shootProjectile()
    // I imagine enemy collision detection is next    
    grid.invaders.forEach((invader, i) => {
      //updates the invaders location in a grid across screen
      invader.updateLocation({velocity: grid.velocity})      
      //tracking projectile for collision detection      
      projectiles.forEach((projectile, j) => {
        if (
          //if top side of projectile touches an invaders top 
          projectile.position.y - projectile.radius <= 
          invader.position.y + invader.height && 
          //and the left side touches 
          projectile.position.x + projectile.radius >= 
          invader.position.x - invader.height&& 
          projectile.position.x - projectile.radius <= 
          invader.position.x + invader.width &&
          projectile.position.y + projectile.radius >= 
          invader.position.y
          ){          
          //this whole thing is the collision detection
            setTimeout(() => {
              const invaderFound = grid.invaders.find(
                invaderLocated => 
                {return invaderLocated === invader})
              const projectileFound = projectiles.find(
                projectileLocated => projectileLocated === projectile)                
              if (invaderFound && projectileFound){
                //add the store here as well
                score += 100;
                console.log('Score:   =>',score)
                scoreCounter.innerHTML = score
                //calling the animation for explosions here
                createParticles({
                  object: invader,
                  fades:true
                })
                grid.invaders.splice(i, 1)
                projectiles.splice(j,1)
                if (grid.invaders.length > 0) {
                  const firstInvader = grid.invaders[0]
                  const lastInvader = grid.invaders[
                    grid.invaders.length - 1]
                  grid.width = 
                  lastInvader.position.x - 
                  firstInvader.position.x +
                  lastInvader.width
                  grid.position.x = firstInvader.position.x
                }
              } else  {
                grids.splice(gridIndex, 1)
              }             
            }, 0)//end setTimeout
        }
      })
    })
  })
}
//messes with it if these aren't global
let frames = 0
let randomIntervals = Math.floor((Math.random() * 500) + 500)
let game = {
  over:false,
  active: true
}
let score = 0
function spawnEnemy() {
  //if statement contained as function for readability  
  if (frames % randomIntervals ===0) {
    //console.log("randomIntervals=", randomIntervals)
    grids.push(new Grid())    
    randomIntervals = Math.floor(((Math.random() * 500) + 500))
    console.log('Random Intervals=>',randomIntervals)
    frames = 0
  }  
}
function createParticles({object,color, fades}) {
  for (let i=0;i<15;i++) {
    particles.push(
      new Particle({
        position: {
          x: object.position.x + object.width / 2,
          y: object.position.y + object.height / 2
        },
        velocity: {
          x: ((Math.random() - 0.5)*2),
          y: ((Math.random() - 0.5)*2)
        },
        radius: Math.random() * 3,
        color: color || '#BAA0DE',
        fades
      })
    )
  }   
}
function animateStars() {
  for (let i=0;i<100;i++) {
    particles.push(
      new Particle({
        position: {
          x: Math.random() * canvas.width,
          y: Math.random() * canvas.height
        },
        velocity: {
          x: 0,
          y: 0.3
        },
        radius: Math.random() * 3,
        color:'white'
      })
    )
    setTimeout(() => {
      particles.splice(i,1)        
    }, 0); 
  }     
}

function animateParticles() {
  particles.forEach(((particle, i) => {
    if(particle.position.y - particle.radius >=
      canvas.height){
        particle.position.x = Math.random() * canvas.width
        particle.position.y = -particle.radius
      }
    if(particle.opacity <= 0){
      setTimeout(() => {
        particles.splice(i,1)        
      }, 0);      
    }else {
      particle.update()
    }    
  }))
}
//animates the player sprite
function animate() {
  if(!game.active) return
  //initiate canvas  
  requestAnimationFrame(animate);
  c.fillStyle = 'black'
  c.fillRect(0,0, canvas.width, canvas.height)  
  player.updateLocation()
  
  
  animateInvaderGrid()
  animateParticles()
  
  //console.log(particles)
  //functions for gameplay  
  
  moveLeftOrRight()
  //console.log(frames) 
  spawnEnemy()  
  frames++
}
//runs the game
animate();
animateStars()
/**
 * Event listeners used for keyboard inputs
 */
addEventListener('keydown', ({key}) => {
  if (game.over) return
  switch (key) {
    case 'a': //left
    keys.a.pressed = true
    console.log('leftdown')
      break;     
    case 'd': //right
      keys.d.pressed = true  
      console.log('rightdown')
      break;     
    case ' ':  //space     
    keys.space.pressed = true
    console.log('spacedown')
    projectiles.push(
      new projectile({
        position: {
          x:player.position.x + player.width/2,
          y:player.position.y
        },
        velocity: {
          x:0,
          y:-10
        }
      })
    )
      break;      
  }}) 
addEventListener('keyup', ({key}) => {
  switch (key) {
    case 'a': //left
    keys.a.pressed = false
      break;      
    case 'd': //right
      keys.d.pressed = false   
      break;     
    case ' ':  //space  
    keys.space.pressed = false    
      break;      
  }})

I have written the program out as best I can.

I tried changing positions in the collision detection section in the if statement starting at line 335 but it still seems to target the grid when two invaders are hit at the same time.

Unlocking a field based on a security role in CRM Dynamics via TypeScript?

I’m very new to Typescript. Below I’m creating a function for Dynamics CRM 365. I want to achieve the following unlock a field when the user role is equal to or has role of Business Advisor

or if their is a easier way to do this please point me towards the right direction to, maybe it might not be a good idea to do foreach loops. Please see logic below

let formContext: Xrm.FormContext = null;
let isBusinessAdvisorRole = null;

export function checkBusinessAdvisorRole() {

var businessAdvisorRole = "Business Advisor role";
isBusinessAdvisorRole = false;

    //Store Security Roles
    var userRoles = Xrm.Utility.getGlobalContext().userSettings.roles;
    var hasRole = false;

    //I want to do a foreach here over user roles
    //Then do
    //if user role = "Business Advisor role"
    //formContext.getControl<Xrm.Controls.StringControl>("fsdyn_name").setDisabled(false);}

I am using puppeteer. I wanna create multiple pages and each page should click on a specific selector and open something

The idea that I wanna apply here is that I have a group of buttons of courses and I wanna click each one of them and go back to the other one to check the details of the course but this will too take too much time if I do it on a single page. so I decided that when I reach the page where the courses are there, I will duplicate the page where the courses are to the number of courses and each page should open a course and close it but seems that doesn’t work well with me.

This is where I am trying to apply the idea

import { ElementHandle, Page as PuppeterrPage } from "puppeteer";
import puppeteer, { Browser } from "puppeteer";
import { Page } from "../Pages/Page";
import { grabData } from "./CoursesInfo";

async function wait(duration: number) {
  return new Promise<void>((resolve) => {
    setTimeout(() => resolve(), duration);
  });
}

export async function openCourse(pages: PuppeterrPage[], browser: Browser) {
  const courseBtn =
    'a.base-navigation-button-content.themed-background-primary-alt-fill-only.theme-border-left-active[analytics-id="courses.base.navigation.handleBase.link"]';

  const courseOption: ElementHandle<HTMLAnchorElement> | null =
    await pages[0].waitForSelector(courseBtn); // Assuming the first page in the array is the one to be used for interaction

  await courseOption?.click();
  await pages[0].waitForNavigation();

  const coursesSection = 'section[id="course-columns-current"]';
  await pages[0].waitForSelector(coursesSection);

  await loadElements(pages[0]);

  await wait(1000);
  const courses = await pages[0].$$(
    'article[ng-if="!membership.course.ui.isExternal"]'
  );
  const numCourses = courses.length;

  const promises = [];

  for (let i = 1; i < numCourses; i++) {
    const newPagePromise = (async () => {
      const newPage = await new Page(browser).createPage();
      await newPage.goto(pages[0].url());
      await loadElements(Page.pages[i]);
      
    })();
    
    promises.push(newPagePromise);
  }

  await Promise.all(promises);


  await wait(5000);
  const clickPromises = [];

  for (let i = 1; i < numCourses; i++) {
    
    
    const clickPromise = (async (pageIndex) => {
      
      const coursesOnNewPage = await Page.pages[pageIndex].$$(
        'article[ng-if="!membership.course.ui.isExternal"]'
      );
      // Assuming you want to click on the course corresponding to the current index i
      const courseToClick = coursesOnNewPage[i - 1];
      await courseToClick.click();
    })(i);

    clickPromises.push(clickPromise);
  }

  // Wait for all click actions to complete
  await Promise.all(clickPromises);
  // await Promise.all(promisesClickEvents);
  console.log(Page.pages);
  console.log("Number of courses: ", numCourses);
}

async function loadElements(page: PuppeterrPage) {
  if (!page) {
    await wait(1500);
    await loadElements(page)
    return;
  }
  await page.evaluate(() => {
    const table: NodeListOf<ChildNode> | undefined = document.querySelector(
      "#course-columns-current > div"
    )?.childNodes;
    let lastDiv;
    if (table) {
      for (let i = 0; i < table.length; i++) {
        if (table[i].nodeName == "DIV") {
          lastDiv = table[i];
        }
      }
    }
    lastDiv?.scrollIntoView();
  });
}

this is where the grabData function created:

import puppeteer, { Browser, Page as PuppeterrPage } from "puppeteer";

export async function grabData(page: PuppeterrPage) {
  await page.waitForSelector("#course-instructors-panel > ul");
  const button = "#view-all-button";

  const viewAllButton = await page.$(button);
  if (viewAllButton) {
    await viewAllButton.click();
    console.log("There are more than two instructors");
  } else {
    console.log("There are less than two instructors");
  }

  const instructors = await page.$$(
    "#course-instructors-panel > ul > li span.primary-text"
  );
  for (let i = 0; i < instructors.length; i++) {
    const instructor = await page.evaluate(
      (instructor) => instructor.textContent,
      instructors[i]
    );
    console.log("Instructor " + (i + 1) + ": " + instructor);
  }
}

This is the page class that I am using:

import puppeteer, {Browser, Page as PuppeterrPage} from "puppeteer";

export class Page {
    private browser: Browser;
    public static pages: PuppeterrPage[];

    constructor(browser: Browser) {
        this.browser = browser;
        Page.pages = [];
    }

    async createPage() {
        const page = await this.browser.newPage();
        Page.pages.push(page);
        return page;
    }

    async closePage(index: number): Promise<void> {
        if(index >= 0 && index < Page.pages.length) {
            await Page.pages[index].close();
            Page.pages.splice(index, 1);
        } else {
            throw new Error("Invalid index");
        }
    }

    async closeAllPages(): Promise<void> {
        await Promise.all(Page.pages.map(page => page.close()));
        Page.pages = [];
    }
}


Let me just explain some of the parts of the first part of code :

for (let i = 1; i < numCourses; i++) {
    const newPagePromise = (async () => {
      const newPage = await new Page(browser).createPage();
      await newPage.goto(pages[0].url());
      await loadElements(Page.pages[i]);
      
    })();
    
    promises.push(newPagePromise);
  }

  await Promise.all(promises);

in here , I tried to ducplicate the pages to the number of courses that should happend all at once and it worked

  const clickPromises = [];

  for (let i = 1; i < numCourses; i++) {
    
    
    const clickPromise = (async (pageIndex) => {
      
      const coursesOnNewPage = await Page.pages[pageIndex].$$(
        'article[ng-if="!membership.course.ui.isExternal"]'
      );
      // Assuming you want to click on the course corresponding to the current index i
      const courseToClick = coursesOnNewPage[i - 1];
      await courseToClick.click();
    })(i);

    clickPromises.push(clickPromise);
  }

  // Wait for all click actions to complete
  await Promise.all(clickPromises);

In here I tried to open once course in each page but that didn’t work well with me I hope someone helps me

I tried it using many approached as I explained but I end having several problems like some of my pages are not loaded fully although I used this function:

async function loadElements(page: PuppeterrPage) {
  if (!page) {
    await wait(1500);
    await loadElements(page)
    return;
  }
  await page.evaluate(() => {
    const table: NodeListOf<ChildNode> | undefined = document.querySelector(
      "#course-columns-current > div"
    )?.childNodes;
    let lastDiv;
    if (table) {
      for (let i = 0; i < table.length; i++) {
        if (table[i].nodeName == "DIV") {
          lastDiv = table[i];
        }
      }
    }
    lastDiv?.scrollIntoView();
  });
}

even it does , it doesn’t open the courses . I am expecting to find a solution for that so that I am able to open one course in each page

UI Not Displaying Properly in Quarkus App with OptaPlanner Integration

I’m working on a project based on a tutorial from an OptaPlanner video, where I’m building a Quarkus application with OptaPlanner integration. I’ve copied the code from their Git repository, but I’m encountering an issue where the UI is not displaying properly. Specifically, only the data is being shown, but the UI components are not rendering correctly. I’ve checked the dependencies, configurations, and code for errors, but I’m still unable to resolve the issue. Can someone provide guidance on how to troubleshoot and fix this problem to ensure that the UI displays properly in my Quarkus application with OptaPlanner integration? Any insights or suggestions would be greatly appreciated.

I’ve tried to match the dependencies gievn to thier git files only for UI and Java file which I used for backend that I wrote it on my own but there’s not showing any kind of error only the problem is that, that the UI is not working and expect it to show the data which I input shows.

Cheerio is so slow, inside a for loop, makes requests wait in between,

The operation below takes around 5-10 mins.

for(let k = 50; k > 0; k--){
  request("http://example.come/?user=" + k, function(error, response, body){
    console.log(response.statusCode);
    let $ = cheerio.load(body);
    const theUsername = $('div.username').html()
    //do more stuff with http data
    console.log('resolved');
  })

}

I have a website path, which I want to loop through the first 50 users info.
Everything works fine, except the cheerio makes it so slow. I thought my server was the problem, but later I commented out the cheerio code block, and it worked so fast.

The cheerio, made it wait at least 5 MINS… for 50 requests… which is SOOOO slow…

The operation below takes 10 seconds.

for(let k = 50; k > 0; k--){
  request("http://example.com/?user=" + k, function(error, response, body){
    console.log(response.statusCode);
    console.log('resolved');
  })

}

So I experienced that cheerio is slow, and it is really not want I want to use. I want to be able to parse html, and read the document using javascript/jquery, yet cheerio’s performance couldn’t be any worse(never thought it would be.)

I do not want to read plain http data, I want to use javascript/jquery to dissect the elements of the DOM. Any advice or alternative to cheerio that can make this operation way faster?

Additional Note About cheerio

the logs look like this, perfectly resolved right after 200 each time.

200
resolved
200
resolved
200
resolved
200
resolved
200
resolved
200
resolved
200
resolved
200
resolved
200
resolved
200
resolved
200
resolved
200
resolved
200

Which means cheerio causes a synchronous behaviour, none of the requests can move forward and log resolved until the previous one finishes…

How to send email using nodemailer and gmail

I have created a contact form to send emails to client when form submitted but i keep getting credentials error when i submit the form. I am using react for this project. My sendemail.js file and server file are in the root directory along with .env file. although contact form is in component directory. The actual credentials are in env file.

const nodemailer = require('nodemailer');

const sendEmail = async (formData) => {
  // Create a transporter using your email service provider's settings
  const transporter = nodemailer.createTransport({
    service: 'gmail',
    auth: {
      user: process.env.REACT_APP_SMTP_USER, // Ensure these are set in your .env
      pass: process.env.REACT_APP_SMTP_PASSWORD, // App-Specific Password for Gmail
    }
  });

  // Setup email data
  const mailOptions = {
    from: process.env.REACT_APP_SMTP_USER, // Match this with the SMTP_USER
    to: formData.email,
    subject: formData.subject,
    text: `Name: ${formData.name}nEmail: ${formData.email}nMessage: ${formData.message}`,
  };

  // Attempt to send the email
  try {
    const info = await transporter.sendMail(mailOptions);
    console.log('Email sent: ' + info.response);
  } catch (error) {
    console.error('Error sending email:', error);
    throw error; // Consider handling this more gracefully
  }
};

module.exports = sendEmail;
`

const express = require('express');
const sendEmail = require('./sendEmail');

const app = express();
const cors = require('cors');
const port = process.env.PORT || 3001;

const allowedOrigins = ['https://lashesbyjess.net', 'http://localhost:3000'];

app.use(cors({
  origin: function (origin, callback) {
    if (!origin || allowedOrigins.indexOf(origin) !== -1) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  }
}));


app.use(express.json());



app.post('/api/send-email', async (req, res) => {
  const formData = req.body;

  try {

    await sendEmail(formData);
    res.status(200).send('Email sent successfully');
  } catch (error) {
    console.error('Error sending email:', error);
    res.status(500).send('Internal Server Error');
  }
});

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

what I have tried:

  1. changing credentials
  2. using app authenticator code from google.
  3. disabling 2factor authentication code and using password instead in .env file.

originally the code worked before I ran the build. realized i needed to refactor code so it could be connected to any server not just local and thats when everything started to change.

Please any help would be greatly appreciated thanks in advance!