Owl Carousel 2 – slider showing part of next image on active slide

I am using Owl Carousel 2 for my slider, but am encountering a slight bug.
At screen widths below 768px one slide is shown. Above 768px 3 slides are shown. For some reason if the screen is refreshed or if the user increases the screen width above 768px part of the 4th slide encroaches into view –
4th slide encroaching into view

Strangely, adjusting the screen size again removes this issue but it is again present on refresh.

Here is my markup –
HTML

<div class="owl-carousel">
    <div class="item"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Test-Logo.svg/783px-Test-Logo.svg.png"></div>
    <div class="item"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/28/JPG_Test.jpg/154px-JPG_Test.jpg"></div>
    <div class="item"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Test-Logo.svg/783px-Test-Logo.svg.png"></div>
    <div class="item"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/28/JPG_Test.jpg/154px-JPG_Test.jpg"></div>
    <div class="item"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Test-Logo.svg/783px-Test-Logo.svg.png"></div>
    <div class="item"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/28/JPG_Test.jpg/154px-JPG_Test.jpg"></div>  
</div>

JS

$(document).ready(function(){
    $('.owl-carousel').owlCarousel({
        loop:true,
        nav:true,
        responsive: {
            0: { items: 1 },  // No overlap on small screens
            768: { items: 3 }
        },
    })
});

I have removed any CSS in an attempt to strip everything back to solve the issue but no luck.

Any ideas anyone?

HighCharts Incorrect locale information provided

Since a week or so my Charts are not functioning.
My chart code works well on jsfiddle
https://jsfiddle.net/80nedgt6/1/
but it’s not rendering on my php code.
So I suspect it is something wrong with Jquery or the way I call the highcharts

<script type="text/javascript" src="/javascript/jquery-3.3.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script> 
<script src="https://code.highcharts.com/highcharts-more.js"></script>
 <script src="https://code.highcharts.com/highcharts-3d.js"></script>
 <script src="https://code.highcharts.com/modules/stock.js"></script>   

I hope someone can help me on this.
Thanks!

Is there a way to prevent React from obscuring error messages in production?

I’m working on a [email protected] connected to Rollbar for error logging. We are getting “An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.” from time to time and even though we can look at the logs, it would be nice to see the stack trace directly in Rollbar.

Is there a way to prevent React from obscuring the error messages?

I tried creating a ServerError class and replacing every throw new Error instance in our code, but that won’t work for any unhandled exceptions or exceptions thrown in third party packages.

Which way is better to code and execute my programming language? [closed]

I’m currently working on my own programming language. It is based on JavaScript, the syntax would be similar, but I would try to make it suitable not only for web development and server-side programming.

Which one do you think is the better idea?
Inventing my own keywords and write a lexer, a parser, a runtime and a transpiler for it, or should I use JavaScript to write a completely other language (I mean unique syntax and so on)?

How do you record a bidirectional stream in Twilio?

I created a phone agent that uses bidirectional streaming in Twilio and now I want to record all incoming calls.

The issue is that there is no documentation on how to do this with bidirectional media streams. I am using the twilio-media-stream-save-audio-file npm package which lets me save audio from a media stream to a wav file but as the documentation points out:

With bidirectional Media Streams, you can only receive the inbound track.

So, when I set up my recorder to save all media type messages received by my Twilio websocket, it only records the caller’s audio and not the audio my server sends back to Twilio (I am using Eleven Labs to generate audio).

Code:

Record Caller Audio:

sendAudio(audio: string): void {
      const audioInput = {
        encodedAudioData: audio,
      };
      this.sendMessage("audio_input", audioInput);

      // Record caller audio
      if (this.callerSpeaking) {
        this.mediaStreamSaver.twilioStreamMedia(audio);
      }
   
  }

Record AI Audio:

async sendAudioToTwilio(audioBase64: string, twilioConnection: TwilioSocket) {

    const twilioMediaMessage = {
      event: "media",
      streamSid: twilioConnection.streamSid,
      media: {
        payload: audioBase64,
      },
    };

    if (twilioConnection.ws.readyState === 1) {
      // Record AI audio
      if (this.aiSpeaking && !this.callerSpeaking) {
        this.mediaStreamSaver.twilioStreamMedia(audioBase64);
      }

      twilioConnection.ws.send(JSON.stringify(twilioMediaMessage));
    } else {
      console.error(
        "Twilio WebSocket is not open. Current state:",
        twilioConnection.ws.readyState
      );
    }
  }

My current approach is to record each stream manually as shown above but this leads to the difficult problems of handling overlapping audio and trimming the outbound audio when I use the clear message. In the end, the recording is 80% representative of the phone call but I’d prefer a way to record the exact audio that was heard.

Things That Don’t Work

  • Record Verb: Basically records a voicemail, is not compatible with media streams
  • Dial Verb with record attribute: This is used to record a normal call, not one that involves media streams

Diffirent responses on very similar headers chrome extension

I’m writing chrome extension (last chrome version) on manifest v3 with js.

All queries and functions works correctly, but only one in my queries giving response status code 500. My query was sniffed from another query (so «another query» is original query on site, «my query» – means that i replacing another query with my query, because i need to push specific data in query), but it`s giving status code 200.

Both queries are haven`t context and prepares, so where can be difference?

I copied quieries with Chrome » Devtools » right click on query » Copy » Copy as fetch.

My query, which giving 500`s server response:

fetch('https://www.server.com/spt/betslips/betslip/toggleitem?betslipId=value here', {
  'headers': {
    'accept': 'application/json, text/plain, */*',
    'accept-language': 'fr,ru;q=0.9,ru-RU;q=0.8,en;q=0.7',
    'betslipid': 'value here',
    'cache-control': 'no-cache',
    'content-type': 'application/json',
    'pragma': 'no-cache',
    'priority': 'u=1, i',
    'sec-ch-ua': '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
    'sec-ch-ua-arch': '"x86"',
    'sec-ch-ua-bitness': '"64"',
    'sec-ch-ua-full-version': '"131.0.6778.86"',
    'sec-ch-ua-full-version-list': '"Google Chrome";v="131.0.6778.86", "Chromium";v="131.0.6778.86", "Not_A Brand";v="24.0.0.0"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-model': '""',
    'sec-ch-ua-platform': '"Windows"',
    'sec-ch-ua-platform-version': '"10.0.0"',
    'sec-fetch-dest': 'empty',
    'sec-fetch-mode': 'cors',
    'sec-fetch-site': 'same-origin',
    'x-gw-application-name': 'NoviIE',
    'x-gw-betslipid': '1314396104817811456',
    'x-gw-channel': 'WebPC',
    'x-gw-client-timezone': 'Europe/Moscow',
    'x-gw-cms-key': '_IE',
    'x-gw-country-sysname': 'IE',
    'x-gw-currency-sysname': 'EUR',
    'x-gw-domain-key': '_IE',
    'x-gw-language-sysname': 'en-IE',
    'x-gw-odds-representation': 'Fractional',
    'x-gw-state-sysname': '',
    'Referer': 'https://www.server.com/live-betting/value here',
    'Referrer-Policy': 'strict-origin-when-cross-origin',

  },
  'body': '{"betContextId":38188719,"betInstanceId":38188719,"marketInstanceId":1207665657,"price":2.5}',
  'method': 'POST',
});

Another query, is responsing OK 200:

fetch('https://www.server.com/spt/betslips/betslip/toggleitem?betslipId=value here', {
  'headers': {
    'accept': 'application/json, text/plain, */*',
    'accept-language': 'fr,ru;q=0.9,ru-RU;q=0.8,en;q=0.7',
    'cache-control': 'no-cache',
    'content-type': 'application/json',
    'pragma': 'no-cache',
    'priority': 'u=1, i',
    'sec-ch-ua': '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
    'sec-ch-ua-arch': '"x86"',
    'sec-ch-ua-bitness': '"64"',
    'sec-ch-ua-full-version': '"131.0.6778.86"',
    'sec-ch-ua-full-version-list': '"Google Chrome";v="131.0.6778.86", "Chromium";v="131.0.6778.86", "Not_A Brand";v="24.0.0.0"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-model': '""',
    'sec-ch-ua-platform': '"Windows"',
    'sec-ch-ua-platform-version': '"10.0.0"',
    'sec-fetch-dest': 'empty',
    'sec-fetch-mode': 'cors',
    'sec-fetch-site': 'same-origin',
    'x-gw-application-name': 'NoviIE',
    'x-gw-betslipid': 'value here',
    'x-gw-channel': 'WebPC',
    'x-gw-client-timezone': 'Europe/Moscow',
    'x-gw-cms-key': '_IE',
    'x-gw-country-sysname': 'IE',
    'x-gw-currency-sysname': 'EUR',
    'x-gw-domain-key': '_IE',
    'x-gw-language-sysname': 'en-IE',
    'x-gw-odds-representation': 'Fractional',
    'x-gw-state-sysname': '',
    'Referer': 'https://www.server.com/live-betting',
    'Referrer-Policy': 'strict-origin-when-cross-origin',

  },
  'body': '{"betContextId":value here,"betInstanceId":value here,"marketInstanceId":value here,"price":1.2}',
  'method': 'POST',
});

I tried to make a similar request using Postman and other debug tools with the same headers and body and didn’t get any errors, so I’m starting to think that it’s a chrome bug and some headers it doesn’t perceive.

Binance tr api invalid api-key

I use binance tr api; i want to make buy order.
But i get this error:

 data: { code: 3700, msg: 'Invalid API-key', timestamp: 1733491789482 }

İf i use this , works:

var apikey="EfA925057351A2f91Fc458ce784c92A2U1xmmH4M3XBuCFmFaWtTN7uqGvxiBVqO";
var secretkey="355D6701C75CC418D874664AF0698f4CYhiOeSVrIV0RfoQLCIxd8gc8l8tlrl2A";
var headers = {
    'X-MBX-APIKEY': apikey,
}
var payload_ana={
        "timestamp":Date.now()
    }
    
axios
    .get("https://www.binance.tr/open/v1/account/spot ",{params:payload_ana,headers:headers})....

But i want to make buy order doesnt work.

var payload={
    "symbol":x,
    "side":0,
    "type":2,
    "quantity":(Number(deger)*50/100/Number(y)).toString(),
//deger=my total balance and y=coin value
    "timestamp":Date.now(),
}   
var sonuc=crypto.createHmac('sha256', secretkey).update("symbol="+payload.symbol+"&side="+payload.side+"&type="+payload.type+"&quantity="+payload.quantity+"&timestamp="+payload.timestamp).digest('hex');      
payload.signature=sonuc;
axios
    .post("https://www.binance.tr/open/v1/orders ",{params:payload,headers:headers})

How to have ESLint check for only one rule without config file?

For a legacy project, running ESLint is not yet meaningful as there are way too many errors.

Yet, as a first step for improvement, I want to check for one rule and one rule only, e.g. no-console.

ESLint is installed globally, and now I want a single-line command to check my codebase only for errors of that one rule.

I don’t want to create any config file, nor should anything else be installed/added in that project.

npm init @eslint/config@latest creates a config file with way too many rules applied, and it also installs packages in the current project.

The repository shall remain completely unaware that eslint exists, so I don’t want these files and folders:

  • eslint.config.mjs
  • node_modules/
  • package-lock.json
  • package.json

I thought that:

eslint --no-config-lookup --rule "no-console: error"  ./my_js_folder/

would do what I wanted, yet I see other errors for other rules as well, e.g.:

  • es/no-global-this
  • unicorn/no-typeof-undefined
  • valid-jsdoc

Even some warnings pop up, like:

35628:25  warning  Unused eslint-disable directive (no problems were reported from 'no-new')

I was expecting only errors for usage of console.log, console.warn, console.error, etc.

How do I achieve that?

EPIPE Error while running frontend code in local machine

I am getting this error while running the frontend application in my local machine, i am using default port:4200.
I have looked upon the internet for the solutions, and tried few of the mas well, I tried updating the packages version. Also tried increasing the memory given to WSL, as i am using WSL. But nothing came to help.
Looking forward to some guidance as this is causing a lot of delay in my work.

Error: write EPIPE
    at target._send (node:internal/child_process:879:20)
    at target.send (node:internal/child_process:752:19)
    at /home/abhinav/Projects/App-Frontend/altius-nx/node_modules/fork-ts-checker-webpack-plugin/lib/rpc/expose-rpc.js:27:31
    at new Promise (<anonymous>)
    at sendMessage (/home/abhinav/Projects/App-Frontend/altius-nx/node_modules/fork-ts-checker-webpack-plugin/lib/rpc/expose-rpc.js:19:38)
    at /home/abhinav/Projects/App-Frontend/altius-nx/node_modules/fork-ts-checker-webpack-plugin/lib/rpc/expose-rpc.js:60:27
    at Generator.next (<anonymous>)
    at fulfilled (/home/abhinav/Projects/App-Frontend/altius-nx/node_modules/fork-ts-checker-webpack-plugin/lib/rpc/expose-rpc.js:5:58)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  errno: -32,
  code: 'EPIPE',
  syscall: 'write'
}

Is `(input)=”true”` idiomatic for Angular OnPush components?

I want to disable button if no files selected.
I have the following template in OnPush component (Angular v19):

Events
<div>
    @for (item of [1, 2, 3, 4]; track $index) {
    <input (input)="true" #file type="file" />
    <button type="button" [disabled]="!file.files!.length" (click)="onAdd2($index, file.files!)">E{{$index}}</button>
    }
</div>

I added (input)="true" to trigger change detection, but this doesn’t feel idiomatic.
But alternative using signals doesn’t work as expected (buttons are not initially disabled) and feel even less idiomatic and requires more code.

Signals
<div>
    @for (item of [1, 2, 3, 4]; track $index) {
    <input (input)="getSignal($index).set(!file.files!.length)" #file type="file" />
    <button type="button" [disabled]="getSignal($index)()" (click)="onAdd2($index, file.files!)">S{{$index}}</button>
    }
</div>
@Component({
  selector: 'app-results',
  standalone: true,
  imports: [],
  templateUrl: './results.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ResultsComponent {
  readonly signals: WritableSignal<boolean>[] = [];

  getSignal(i: number): WritableSignal<boolean> {
    return this.signals[i] ??= signal(false);
  }

  onAdd2(i: number, arg0: FileList) {
    console.log(i, Array.prototype.map.call(arg0, x => x.name));
  }
}

What would you suggest?

How to replace a pixel in a webGL canvas with javascript

I want to change the color of one pixel for a webGL canvas by first getting the current value and then replace it with a new slightly modified color. For a 2d canvas context this was easy, but I quickly get lost trying to do the same for a webGl canvas context.

Here is my attempt at first reading the pixel color and then drawing it back with changed color. I would prefer just getting an array, change one value and then putting it back instead of drawing, but I found no way to do this either.

var gl = canvas.getContext('webgl');
const out = new Uint8Array(4);
gl.readPixels(98, 122, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, out);
out[0] = 255;
var float32Data = new Float32Array(out)
var vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, float32Data, gl.DYNAMIC_DRAW);
gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.POINTS, 0, float32Data.length / 3);

MongoDB unable to store token in session

I am working on a project that can fetch posts from Facebook using meta API. The facebook callback function returns the token, however I am having trouble to save it in the session. The session seems to be created, but it does not add the access token.

export const facebookCallback = async (req, res) => {
    const { code } = req.query;

    if (!code) {
        console.error("Authorization code missing in callback");
        return res.status(400).json({ message: "Authorization code not provided" });
    }

    try {
        // Step 1: Get short-lived token
        const tokenResponse = await axios.get(
            `https://graph.facebook.com/v15.0/oauth/access_token`,
            {
                params: {
                    client_id: process.env.FACEBOOK_APP_ID,
                    redirect_uri: process.env.FACEBOOK_REDIRECT_URL,
                    client_secret: process.env.FACEBOOK_APP_SECRET,
                    code,
                },
            }
        );

        const shortLivedToken = tokenResponse.data.access_token;

        if (!shortLivedToken) {
            console.error("Failed to retrieve short-lived access token");
            return res.status(500).json({ message: "Failed to retrieve short-lived access token" });
        }

        // Step 2: Exchange for long-lived token
        const longLivedToken = await exchangeForLongLivedToken(shortLivedToken);
        console.log('Long lived token:', longLivedToken);

        // Step 3: Save token in session and set the cookie explicitly
        req.session.accessToken = longLivedToken;
        console.log('Session accessToken set:', req.session.accessToken); // Explicitly log session token

        // Ensure the cookie is set properly
        req.session.cookie.maxAge = 3600000; // Optional: ensure session is valid for 1 hour
        req.session.cookie.httpOnly = true; // To prevent client-side access
        req.session.cookie.secure = process.env.ENVIRONMENT === "production"; // Set secure flag for production

        // Save session
        req.session.save((err) => {
            if (err) {
                console.error('Error saving session:', err);
                return res.status(500).json({ message: 'Failed to save session' });
            }

            console.log('Session saved successfully:', req.session);

            // Send the cookie with the response
            res.cookie('connect.sid', req.sessionID, {
                httpOnly: true,
                secure: process.env.ENVIRONMENT === "production", // Use secure cookies in production
                sameSite: 'lax',
                maxAge: 3600000, // 1 hour cookie
            });

            // Redirect to client-side
            const clientUrl =
                process.env.ENVIRONMENT === 'production'
                    ? process.env.PRODUCTION_CLIENT_URL
                    : process.env.LOCAL_CLIENT_URL;

            return res.redirect(`${clientUrl}/admin/projects/new/facebook`);
        });

    } catch (error) {
        console.error('Error during Facebook callback:', error.response?.data || error.message);
        return res.status(500).json({ message: 'Failed to complete Facebook login' });
    }
};

Here is how the session is set up:

app.use(
    session({
        name: "connect.sid", // Default session cookie name
        secret: process.env.JWT_SECRET,
        resave: true, // Allow the session to be re-saved even if it was not modified
        saveUninitialized: false, // Do not save empty sessions
        cookie: {
            httpOnly: true,
            secure: process.env.ENVIRONMENT === "production", // Set secure cookies in production
            sameSite: "lax", // Helps prevent CSRF
            maxAge: 3600000, // 1 hour
        },
        store: MongoStore.create({
            mongoUrl: process.env.MONGO_URI, // MongoDB URI for storing sessions
            ttl: 14 * 24 * 60 * 60, // 14 days TTL for session
            autoRemove: "native", // Automatically clean up expired sessions
        }),
    })
);

So when I make request from the front-end to fetch facebook pages it cannot extract the token from the session.

    fetchFacebookPages: async () => {
        try {
            console.log("Fetching Facebook pages...");
            const response = await http.get("/admin/facebook/pages");
            console.log("Pages fetched:", response.data.pages);
            return response.data.pages;
        } catch (error) {
            console.error("Error fetching pages:", error.response?.data || error.message);
            throw error;
        }
    },

here are my logs:

Session saved successfully: Session {
  cookie: {
    path: '/',
    _expires: 2024-12-06T13:12:33.062Z,
    originalMaxAge: 3600000,
    httpOnly: true,
    secure: false,
    sameSite: 'lax'
  },
  accessToken: '********'

Validating token: 
Session in Middleware: Session {
  cookie: {
    path: '/',
    _expires: 2024-12-06T13:12:34.096Z,
    originalMaxAge: 3600000,
    httpOnly: true,
    secure: false,
    sameSite: 'lax'
  }
}

}

Access token missing from session


My http interceptor:


import axios from "axios";

// Function to fetch the client's public IP address
async function fetchIPAddress() {
    try {
        const response = await axios.get('https://api.ipify.org?format=json');
        return response.data.ip;
    } catch (error) {
        console.error('Failed to fetch IP address:', error);
        return null;
    }
}

// Create an Axios instance
const http = axios.create({
    baseURL: process.env.REACT_APP_API_URL
        ? `${process.env.REACT_APP_API_URL}/api`
        : "http://localhost:3001/api", // Default to localhost if environment variable is not set
    headers: {
        "Content-Type": "application/json",
    },
    withCredentials: true, // Send cookies with requests
});

// Request interceptor to add additional headers
http.interceptors.request.use(
    async (config) => {
        const ipAddress = await fetchIPAddress(); // Fetch public IP
        if (ipAddress) {
            config.headers['X-Client-IP'] = ipAddress; // Add IP to request headers
        }
        console.log("Request Headers:", config.headers); // Log headers for debugging
        return config;
    },
    (error) => {
        console.error("Request Error:", error);
        return Promise.reject(error);
    }
);

// Response interceptor to handle success and error responses
http.interceptors.response.use(
    (response) => {
        console.log("Response Data:", response.data); // Log response data
        return response;
    },
    (error) => {
        console.error("Response Error:", error.response?.data || error.message);
        return Promise.reject(error); // Pass error to the calling function
    }
);

export default http;

And this is the component that is supposed to fetch pages:

import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router";
import adminServices from "../../../API/adminServices";
import styles from "./FacebookFetch.module.css";
import arrow from "../../../Assets/arrow.svg";
import AdminLoader from "../../../Shared/AdminLoader/AdminLoader";

const FacebookFetch = ({ setDescription, setLinks }) => {
    const [pages, setPages] = useState([]);
    const [posts, setPosts] = useState({});
    const [activePageId, setActivePageId] = useState(null);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState(null);
    const navigate = useNavigate();

    useEffect(() => {
        if (window.location.hash === "#_=_") {
            window.history.replaceState({}, document.title, window.location.pathname);
        }

        const autoLoginAndFetchPages = async () => {
            setLoading(true);
            setError(null);
            try {
                const fetchedPages = await adminServices.fetchFacebookPages();
                setPages(fetchedPages);
            } catch (err) {
                if (err.response?.status === 401 && !localStorage.getItem("facebookRetry")) {
                    console.log("No valid token found, redirecting to Facebook login...");
                    localStorage.setItem("facebookRetry", "true");
                    handleFacebookLogin();
                } else {
                    console.error("Error fetching pages:", err.message);
                    setError(err);
                }
            } finally {
                setLoading(false);
            }
        };

        autoLoginAndFetchPages();
    }, []);

    const fetchPages = async () => {
        setLoading(true);
        setError(null);
        try {
            const fetchedPages = await adminServices.fetchFacebookPages();
            setPages(fetchedPages);
        } catch (err) {
            console.error("Error fetching Facebook pages:", err.message);
            setError(err);
        } finally {
            setLoading(false);
        }
    };

    const fetchPosts = async (pageId) => {
        setLoading(true);
        setError(null);

        try {
            setPosts({});
            setActivePageId(null);

            const selectedPage = pages.find((page) => page.id === pageId);
            const fetchedPosts = await adminServices.fetchFacebookPagePosts(
                pageId,
                selectedPage.access_token
            );

            setPosts({
                [pageId]: fetchedPosts,
            });
            setActivePageId(pageId);
        } catch (err) {
            console.error("Error fetching posts:", err.message);
            setError(err);
        } finally {
            setLoading(false);
        }
    };

    const handleFacebookLogin = () => {
        adminServices.redirectToFacebookLogin();
    };

    const selectPost = async (post) => {
        setLoading(true);
        setError(null);

        try {
            const selectedPage = pages.find((page) => page.id === activePageId);
            if (!selectedPage?.access_token) {
                throw new Error("Page access token is missing.");
            }

            if (!post.message && !post.attachments) {
                setError("This post has no content to fetch.");
                return;
            }

            const postData = await adminServices.downloadPostMedia(post.id, selectedPage.access_token);

            const description = postData.description || "";

            // Extract only non-media links from the description
            const linkRegex = /(https?://[^s]+)/g;
            const extractedLinks = description.match(linkRegex) || [];
            const cleanedDescription = description.replace(linkRegex, "").trim();

            // Combine API links and extracted non-media links
            const combinedLinks = [...(postData.links || []), ...extractedLinks].filter(
                (link) => !postData.media.includes(link) // Exclude media URLs
            );

            // Set description and cleaned links
            setDescription(cleanedDescription);
            setLinks(combinedLinks);

            // Navigate and pass the appropriate data
            navigate("/admin/projects/new", {
                state: {
                    description: cleanedDescription,
                    links: combinedLinks,
                    media: postData.media, // Separate field for media
                },
            });
        } catch (err) {
            console.error("Error selecting post:", err.message);
            setError(err.message);
        } finally {
            setLoading(false);
        }
    };

    return (
        <div className={styles.container}>
            {loading && <AdminLoader />} {/* Show loader during loading */}
            <h1 className={styles.title}>
                Fetch From <span className={styles.facebook}>Facebook</span>
            </h1>
            <div className={styles.actions}>
                <button className={`primary__btn`} onClick={handleFacebookLogin}>
                    Configure
                </button>
                <button className="primary__btn" onClick={fetchPages}>
                    Refresh Pages
                </button>
            </div>
            {error && <p className={styles.error}>Error: {error.message || "Unknown error"}</p>}
            <div className={styles.content}>
                <div className={styles.pages}>
                    <h2>Pages</h2>
                    {pages.length > 0 ? (
                        <ul className={styles.pageList}>
                            {pages.map((page) => (
                                <li key={page.id} className={styles.pageItem}>
                                    <button className={styles.pageButton} onClick={() => fetchPosts(page.id)}>
                                        {page.name}
                                        <img className={styles.arrow} src={arrow} alt="arrow" />
                                    </button>
                                </li>
                            ))}
                        </ul>
                    ) : (
                        <p>No pages found or not logged in.</p>
                    )}
                </div>
                <div className={styles.posts}>
                    <h2>Posts</h2>
                    {Object.keys(posts).length > 0 ? (
                        Object.entries(posts).map(([pageId, pagePosts]) => (
                            <div className={styles.posts__list} key={pageId}>
                                {pagePosts.map((post, index) => (
                                    <div key={index} className={styles.post}>
                                        <div className={styles.wrapper}>
                                            <p className={styles.postMessage}>
                                                {post.message || "No message or content provided."}
                                            </p>
                                            {post.message && post.message.match(/https?://[^s]+/g) && (
                                                <div className={styles.postLinks}>
                                                    <strong>Links:</strong>
                                                    {post.message
                                                        .match(/https?://[^s]+/g)
                                                        .map((link, i) => (
                                                            <a
                                                                href={link}
                                                                key={i}
                                                                target="_blank"
                                                                rel="noopener noreferrer"
                                                                className={styles.link}
                                                            >
                                                                {link}
                                                            </a>
                                                        ))}
                                                </div>
                                            )}
                                            <button
                                                className={`${styles.selectPostButton}`}
                                                onClick={() => selectPost(post)}
                                            >
                                                Select Post
                                            </button>
                                        </div>
                                        {post.full_picture && (
                                            <img
                                                src={post.full_picture}
                                                alt="Post content"
                                                className={styles.postImage}
                                            />
                                        )}
                                    </div>
                                ))}
                            </div>
                        ))
                    ) : (
                        <p>Select a page to view posts.</p>
                    )}
                </div>
            </div>
        </div>
    );
};

export default FacebookFetch;

Here are the back-end routes:

// Facebook routes
router.get("/facebook/login", facebookLogin);
router.get("/facebook/login/callback", facebookCallback);
router.get("/facebook/pages", ensureValidAccessToken, getUserPages);
router.get("/facebook/posts/:pageId", ensureValidAccessToken, getPagePosts);
router.post('/facebook/post/download', ensureValidAccessToken, downloadPostMedia);

This is the validation function that throws the error

export const ensureValidAccessToken = async (req, res, next) => {
    console.log("Session in Middleware:", req.session);
    if (!req.session.accessToken) {
        console.error("Access token missing from session");
        return res.status(401).json({ message: "No token provided!" });
    }
    next();
};

I tried debugging a lot, but I cannot find out why it is not saving the token.

Getting rid of sticky bar in puppeteer screenshot

So I am working on a project that requires me to take a screenshot of a Pinterest board, I kind of fixed my previous issues like lazy loading and the infinite scroll. I limited how many scrolls the program does to avoid it going on forever. But now my problem is that the navbar is showing up in the middle of the screenshot, and not matter what I use, it still shows up in the program. I’ve tried deleting the property through xpath, not sure if I did it correctly.

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: true });
  const page = await browser.newPage();
  
  // Navigate to the Pinterest board (or your target page)
  await page.goto('https://www.pinterest.com/NoMyCheesy/f-l-o-w-e-r-s/');
  
  // Wait for the sticky bar element using XPath
  const xpath = 'html/body/div[1]/div/div[1]/div/div[1]/div[2]/div/div/div[2]/div/div';
  
  // Wait for the element using XPath, page.$x returns an array of elements
  const elements = await page.waitForSelector(xpath);

  // Check if any elements were found
  if (elements.length > 0) {
      const element = elements[0]; // Get the first matched element
      await element.evaluate(el => el.remove()); // Remove it from the DOM
  } else {
      console.log("Element not found");
  }
    // Zoom out (e.g., 50% zoom)
    await page.evaluate(() => {
        document.body.style.zoom = '0.5'; // Zoom out to 50%
    });

    // Scroll to load more pins
    await autoScroll(page, 15);  // Limit to 15 scrolls

    // Wait for images and network to stabilize
    await page.waitForFunction(() => {
        return document.readyState === 'complete' && window.performance.getEntriesByType('resource').every(e => e.initiatorType !== 'img' || e.responseEnd < performance.now() - 2000);
    }, { timeout: 20000 });

    // Take a full-page screenshot
    await page.screenshot({
        path: 'yoursite.png',
        fullPage: true
    });

    await browser.close();
    console.log('Screenshot saved as yoursite.png');
})();

// Function to scroll down the page
async function autoScroll(page, maxScrolls) {
    await page.evaluate(async (maxScrolls) => {
        await new Promise((resolve) => {
            let totalHeight = 0;
            let distance = 100;
            let scrolls = 0;  // Scrolls counter
            let timer = setInterval(() => {
                let scrollHeight = document.body.scrollHeight;
                window.scrollBy(0, distance);
                totalHeight += distance;
                scrolls++;  // Increment counter

                // Stop scrolling if reached the end or the max number of scrolls
                if (totalHeight >= scrollHeight - window.innerHeight || scrolls >= maxScrolls) {
                    clearInterval(timer);
                    resolve();
                }
            }, 3500);  // Scroll every 3.5 seconds
        });
    }, maxScrolls);  // Pass maxScrolls to the function
}

Can I catch a CypressError (test failure) to try another test instead?

I am testing a payment screen in Cypress. We have two third-party payment systems, and when the user pays, they will go from my site to the payment provider and then back to my site. For the purposes of this example, the payment provider hosts can be regarded as https://demo.paymentprovider1.com and https://demo.paymentprovider2.com.

A complication is that currently the system can go to either provider in a way that I cannot predict. I will change this in the future, but currently I plan to work around it. I understand the well-meaning warnings in the manual but I intend to ignore them in the short term (this would, after all, be easy in Selenium).

Normally if one knew which card provider I would land on, I would do this:

it.only('Makes a Visa/Mastercard payment', () => {
    clickPaymentTypeRadioButtonAndSubmit(0);
    cy.url().should('not.contain', 'test.myapp.com');

    cy.origin(
        'https://demo.paymentprovider1.com',
        () => {
            cy
                .get('body', {timeout: 5000})
                .should('contain.text', 'Select payment method');
        }
    );

});

However if I get that wrong, because the other provider is chosen, the test will fail with this:

CypressError: Timed out retrying after 5000ms: The command was expected to run against origin demo.paymentprovider1.com but the application is at origin demo.paymentprovider2.com.

This commonly happens when you have either not navigated to the expected origin or have navigated away unexpectedly.

I would like to capture this case, so that I have this arrangement:

  • If the get() inside the origin() succeeds then I do the tests for the first payment provider
  • If it fails I do another origin() on the other domain, and if that succeeds, do the tests for the second provider

I have tried various tests to location() and url() to run tests conditionally, but those approaches have not yielded successful results. What can I try next?

tool for no variable shadowing for global variables in javascript (vs-code)?

I’m relatively new to the developer scene. VS code accepts shadowing a global variable from the BOM, without saying anything:

const document = 5;
console.log(document);

Luckly the browser warns me with: ‘Uncaught SyntaxError: redeclaration of non-configurable global property document’ because document is part of the BOM.’
But there are other objects part of the BOM, and both the browser and the code editor don’t bat an eye if I write this:

const navigator = 5;
console.log(navigator); // 5

I wish there was an extension that could warn me directly inside of the vs code editor I’m shadowing a global variable (I don’t understand why it doesn’t exist by default) without setting up a big mess with npm and settings every time like with ESlint