#development

1 messages Ā· Page 258 of 1

crystal wigeon
#

yes

#

That

neon leaf
#

what is this convo šŸ™

#

I aint paying internet for this shit

coral pagoda
#

kinda close

crystal wigeon
#

It went from discussing a dating app idea to paranoia

#

We hunting this guy now

wheat mesa
#

Complaining about the facets of being secure on the internet whilst actively using the internet

crystal wigeon
#

The irony

coral pagoda
wheat mesa
#

Sure

crystal wigeon
#

The moment you bought a modern device they already got your info, voice, face everything

#

wait I gotta find this

deft wolf
#

That's why i use Nokia 3310 Clueless

coral pagoda
#

and i use tor 24/7 for most things :v

wheat mesa
#

You’re chatting on a non-e2ee platform on the internet 😳 it’s so insecure

coral pagoda
#

like discord

crystal wigeon
#

Watch this

wheat mesa
#

NSA probably contracting those kids rn

coral pagoda
#

but i do use xmpp

wheat mesa
crystal wigeon
#

It’s not new

coral pagoda
crystal wigeon
#

Cameras have existed for long time

wheat mesa
#

NASA no, NSA yes

coral pagoda
#

they use reverse image search shit

crystal wigeon
#

Anyway waffle do you wanna build it together kitadance

wheat mesa
#

Your face is probably somewhere on the internet, maybe not the main subject but still probably on there somewhere

crystal wigeon
#

We get rich or die trying

wheat mesa
#

Already building something with my wife :p thanks for the offer though

deft wolf
#

HoaX, Tim and Waffle... real dream team

crystal wigeon
#

Damn lucky

coral pagoda
crystal wigeon
#

Tim, NyNu and Kohaku dream team

coral pagoda
#

if someone has it they earned it :v

crystal wigeon
#

Waffle too

wheat mesa
#

Now that’s a level of paranoid that is unhealthy

crystal wigeon
#

Actually there lotta people here

#

That are op

coral pagoda
crystal wigeon
#

But just tech savy haha

deft wolf
#

Everyone from top.gg in one team

earnest phoenix
#

plsno

crystal wigeon
wheat mesa
#

If you look at some of my first messages in this server I look stupid :p

crystal wigeon
#

We’ve all been there

wheat mesa
#

Still got a lot to learn but I’m on the grind now

crystal wigeon
#

it’s an experience

#

same

coral pagoda
crystal wigeon
#

I also have an idea for an AI clone

deft wolf
crystal wigeon
#

Like to reply to messages as you and even code as you

#

heck it could even do your 9-5 job

#

kekcry long term goal

wheat mesa
#

Yeah that’s not happening lol

crystal wigeon
#

Trust me it can happen. I got some ideas

wheat mesa
#

You can have ideas that are theoretically possible but practically infeasible

crystal wigeon
#

Well not take over fully

#

But like an assistant

#

So you could save lot more time

earnest phoenix
#

i already got my assistant, my brain

crystal wigeon
#

Yeah practically there are lot of variables for sure. But saving time will be huge deal

#

Get a second brain

earnest phoenix
#

gotta first make the first usable

crystal wigeon
#

Lmao

#

Tru

#

What are you building btw @waffle

#

With your wife

earnest phoenix
#

a kid /s

crystal wigeon
#

Anyway NyNu

wheat mesa
wheat mesa
crystal wigeon
wheat mesa
#

Secret to everyone!

crystal wigeon
#

And wish congratulations man!!! You got married 4 months ago?!

#

I’ve know for more than 2 years now

wheat mesa
#

Yep, on our 3rd anniversary together

crystal wigeon
#

Aw that’s nice

#

Happy married life pal Party

wheat mesa
#

Tysm

sharp geyser
pearl trail
#

šŸ’€

pearl trail
lament rock
#

("ba" + + "a").toLowerCase()

sharp geyser
lament rock
#

Yup

#

banan

#

come, mr tally man. Tally me banan

steady saffron
#

Using Next.js v14 App Router:

import HomeHero from "@/layouts/home/HomeHero";
import ServerSection from "@/layouts/home/parts/ServerSections";
import { APIKey } from "@/lib/data";

export const revalidate = 300;

export default async function Page() {
  const response = await fetch(`${process.env.API_ENDPOINT}/home`, {
    headers: APIKey,
    next: {
      revalidate: 300
    }
  });

  const data = await response.json();
  
  return ...

Every single time I refresh the page, this request is made and it's not being cached meaning my function invocations are increasing significantly on Vercel. When running this on localhost it used cache but running it on Vercel doesn't

lyric mountain
#

I dont think vercel keeps created/modified files

#

so you'd be relying entirely on browser cache

steady saffron
#

also, when i switch to a server action it works perfectly fine however i believe that counts as a function invocation then which im trying to avoid

lyric mountain
#

hm, I stand corrected then

sharp geyser
#

What the heck

lyric mountain
#

idk anyone here who uses vercel, perhaps Tim but idk

sharp geyser
#

Was I pinged

radiant kraken
#

@sharp geyser

sharp geyser
#

L

#

bozo

radiant kraken
#

😭

sharp geyser
sage bobcat
#

One message removed from a suspended account.

sage bobcat
#

One message removed from a suspended account.

#

One message removed from a suspended account.

#

One message removed from a suspended account.

pearl trail
#

chnbnale

radiant kraken
#

L

#

chnbnale

neon leaf
#

(im quite proud of the result)

civic scroll
#

@scenic kelp as of now i have this

  Expr() {
    let token: Token;
    if (token = this.consume(TokenKind.OpenParen) as Token) {
      let expr = this.Expr();
      this.expect(TokenKind.CloseParen);
      return expr;
    }

    if (token = this.consume(this.UnaryOperators) as Token) {
      let expr = this.Expr();
      return new UnaryExpr(new Operator(token.type), expr);
    }

    let left = this.expect(this.LiteralTypes, TokenKind.Ident);

    let operator: Token;
    if (operator = this.consume(this.BinaryOperators) as Token) {
      let right = this.Expr();
      return new BinaryExpr(left, new Operator(operator.type), right);
    }
    return left.type === TokenKind.Ident
      ? new Identifier(left.value!)
      : new Literal(left.type, left.value!);
  }
scenic kelp
#

ill write up a parser real quick so i'm not talking out of my ass

civic scroll
#

valid with ```
2 + -(3 * 4)

but dies at 

(2 + -3) * 4

scenic kelp
#

what's the issue with that?

civic scroll
#

technically it should've worked

#

so i'm quite puzzled

scenic kelp
#

oh do you do precedence parsing separately?

#

or are planning on it?

civic scroll
#

there's no precedence system

#

but i wish to include one

#

since this is AST generation phase

#

i looked at something like "infix double-e" but utimately confused

scenic kelp
#

normally you get the parenthesis for free as part of the precedence parsing if you're doing it recursive descent style

#

i'm lowkey not sure how you handle it otherwise

#

i think you'd need an intermediate rule

civic scroll
#

treat my impl as incorrect

scenic kelp
#

yeah

civic scroll
scenic kelp
#

that shouldn't need to be a thing

#

there's a fault in the grammar if you need to do that

civic scroll
#

hopefully not in mine

scenic kelp
#

do you have the grammar rules written out at all

civic scroll
#

yeah

#

hang on

#
Program is
  Statement[] statements
,

Statement is
  Expr 
  Semicolon
,

Expr is
  BinaryExpr
or  UnaryExpr
or  Ident
or  Literal
,

BinaryExpr is
  Expr left
  BinaryOperator operator
  Expr right
,

UnaryExpr is
  UnaryOperator operator
  Expr expr
scenic kelp
#

if you add a ParenExpr in somewhere i'd imagine it'd work

#

don't quote me on it

civic scroll
#

i thought of it

#

but then thought ParenExpr is already Expr

scenic kelp
#

i think the other thing you can do is parse something like (2 + 3) as a BinaryExpr(BinaryExpr(2, +, 3), null, null)

#

i've never implemented a grammar like that i'm ngl

#

i always do operator precedence right in the main grammar

civic scroll
#

i can't do that since i want to add custom operators later on

#

but i think i can group them

scenic kelp
#

if you want to be really crazy you can leave operator expressions somewhat unparsed and then parse them separately way later on in the pipeline

#

then that enables user defined operators with custom precedences

#

😱

civic scroll
#

then might have to change how trees are constructed

#

especially with operators that are in the same group

#

come back to (1 + 2) * 3

#

how do i make sure it parses after the paren

wheat mesa
#

You can look at my math expression parser 🄺

civic scroll
#

i'm reading it at the same time

wheat mesa
#

Recursive descent is like pseudo magic because it kinda just works

#

Like it makes sense but it’s hard to explain how it handles precedence

scenic kelp
#

okay what if

civic scroll
#

let left = this.expect(this.LiteralTypes, TokenKind.Ident);

#

^ what if i make this also work with groupped expr

wheat mesa
#

Yes that’s what you’re meant to do

scenic kelp
#
  "(" Expr ")",
or  Expr
#

let me cook 1 sec

#

something with a separate ParenExpr would be required though i think

civic scroll
wheat mesa
#

You’d just do

if (matches(leftParen))
    let expr = ParseExpr()
    expect(rightParen)
    return new GroupingExpr(expr)
civic scroll
#

got it

civic scroll
wheat mesa
#

Just depends on your setup

civic scroll
#

although how do i deal with operator precedence?

#

if say i have a dict with operators mapped to a precedence value

wheat mesa
#

Don’t do that

#

That’s shunting yard

#

You have to deal with queues and stacks and all that other BS with shunting yard

#

With recursive descent you define precedence as a natural part of your grammar

civic scroll
#

although wouldn't it be more complex as i add more operators?

wheat mesa
#

Not really

#

I changed a little bit since then but this gives you the general idea

civic scroll
#

another reason is that i saw rust also impl custom precedence

wheat mesa
#

rustc is a very complex system

civic scroll
#

very

#

they have a separated section for parser and ast generation alone

wheat mesa
#

Well, parser is AST generation

#

But they have several layers of analysis and error reporting and such

civic scroll
#

i wanted to make a similar framework for error reporting like that

#

but nothing beyond static analysis

#

another bug

#
(-3 ^ 2)

generated

UnaryExpr {
  operator: Operator { op: 'Minus' },
  expr: BinaryExpr {
    left: Literal { type: 'IntLiteral', value: '3' },
    operator: Operator { op: 'Caret' },
    right: Literal { type: 'IntLiteral', value: '2' }
  }
}
wheat mesa
#

You should have a separate groupingexpr that just holds an Expr

civic scroll
#

hmm

wheat mesa
#

And unary is a bit different iirc

civic scroll
#

yeah

wheat mesa
#

It’s been a while but just look at those two parsers I wrote

civic scroll
#

it's calling into itself?

sharp geyser
#

Gotta love terrible UI

#

I feel like there should be more text sadge

real rose
#

i see no issue

civic scroll
#

i think we need a stack/queue based mechanism

real rose
#

its got action buttons

#

and a label

#

fr

#

maybe a bit much air

solemn latch
#

The buttons should be bigger ^-^

civic scroll
sharp geyser
#

Yea, I should never be a UI/UX person

#

This looks straight ass to me

lyric mountain
#

make it vertical

#

and increase icon size

#

also make the disclaimer about 30% smaller

#

and the title bigger

sharp geyser
#

vertical?

lyric mountain
#

column instead of row

#

you'll also be able to add more buttons latter without having to change the layout too much

sharp geyser
#

Yea, this is starting to look better

lyric mountain
#

increase icon size, make it very visible

spark flint
#

make the icons the same size

lyric mountain
#

they are already

spark flint
#

they dont look it

lyric mountain
#

it's just that square > circle (visibly)

#

but the pixel dimensions are identical

sharp geyser
#

Increased the size

lyric mountain
#

looking good

#

love how f.lux adds mexico filter on every screenshot

sharp geyser
#

lol

coral pagoda
quartz kindle
#

rename it to macrohard

civic scroll
#

i used shunting yard šŸ˜”

bold crypt
#

Why is it flipped

#

0xf is right not left

civic scroll
#

yes

crystal wigeon
#

hey, just out of curiosity. are you guys usually building multiple projects?

sharp geyser
#

We wouldn't be developers if we weren't

#

Devs are master procrastinators

lament rock
#

I have multiple projects some taking much higher priority over others when they shouldn't. Some work for money and others for hobby

#

and the list keeps growing

tough condor
crystal wigeon
crystal wigeon
#

i have this idea for a marketplace for microservices, where you can simply plug-n-play the service. which would save you a lot of time. not having to rebuild things. like payments, or mail, or user auth with rbac. it can save you a lot of time.

tidal pendant
#

hey do welcomer bot even have any value in the market ?

crystal wigeon
tidal pendant
#

what are the commands most in demand for a welcomer bot which most bots lack

crystal wigeon
#

ye idk. you'll need to figure it out

tidal pendant
#

oh ok thanks

crystal wigeon
#

im pretty content with what current bots do

tidal pendant
#

ā¤ļø

crystal wigeon
sharp geyser
#

I use an auth server and then interact with it via its api

crystal wigeon
#

so you use the same for all your projects no?

#

copy paste

#

pretty much what the marketplace will offer.

sharp geyser
crystal wigeon
#

now for the developer, the marketplace could allow you to sell your microservice

#

to others

sharp geyser
#

I mean

#

I just use an OIDC library to interact with the auth server

#

Theres no need for a microservice

crystal wigeon
#

well auth is just an example. there's stuff like auth with rbac etc

#

but it can be any service. like maybe image optimization

#

cicd

sharp geyser
#

Microservices are honestly more harmful than helpful imo

crystal wigeon
#

basically marketplace to find the services you need

sharp geyser
#

9 times out of 10 you dont need to use such a tactic

crystal wigeon
#

imagine you are building 10 projects. and having to build the same service over and over for 10 times

#

takes a lot of time. but if you make that service re-usable

#

it'd save a lot of time

sharp geyser
#

I mean sure but the liklihood that you're doing it exactly the same each time is highly unlikely

crystal wigeon
#

think about the people who cant build that 1 service or want to build it faster. they would benefit from using the marketplace to quickly download what they want and plug-n-play.

#

yes it could be a bit different each time according to the business logic

#

but the underlying feature will be the same.

sharp geyser
#

How are you going to gurantee its plug n play

crystal wigeon
#

you just get the microservice and start using the endpoints it exposes. people can make whatever changes they want

#

and add their own custom business logic

#

like OAuth for example. google oauth even if you implement in 10 projects its always the same

#

the only difference is what you do with the data

#

so you will save a lot of time with all the initial set up

#

that are common accross

#

thats what the marketplace will give you

#

you add whatever business logic you want

sharp geyser
#

Im not discrediting that some microservices are useful, most of the time though it isnt

crystal wigeon
#

well it is a start

#

just see shipfast. we know we wont use it

sharp geyser
#

Over using causes problems in the long run

crystal wigeon
#

but they are still profitable

#

yeah you are not over-using it or anything. you are saving time with all the initial set up

#

so now i wanna know what microservices would you want if there was a marketplace flork_think

sharp geyser
#

I honestly would never pay

#

If its not open source and i cant host it myself its not useful to me

crystal wigeon
#

even if it saved you time? flork_think

#

huh you can host it yourself

#

you get the full code

#

you get everything

#

you can choose how to host it.

#

on the marketplace or your own

#

and if you were to be a dev publishing microservices you'd be making money

#

so its a passive income

#

you build the service once and sell. ofc and maintain

#

but yeah, let me know if you have any services in mind that youd want to see on the marketplace

earnest phoenix
#

so pretty much selling open source stuff

earnest phoenix
tough condor
#

What intents do you require for a discord bot, so the bot can see what VC the user is connected to?

sharp geyser
#

Guilds & GuildsVoiceStates

#

Actually

#

you only need GuildVoiceStates

tough condor
sharp geyser
#

nah

#

voice state should be seperate from member intent

#

Intents & the events they fire

lament rock
sharp geyser
#

Huh then why does docs say its a seperate intent?

slender wagon
#

Have u guys ever ran a llm locally?

keen meteor
obsidian obsidian
polar hollow
#

I have a question, the webhook has the authentication option, how does it send this to my endpoint? in the headers?
If so, how is it shipped?

earnest phoenix
#

@radiant kraken worked with mpsc channels before? if so, you prefer tokio's variant or flume?

#

i kinda don't use tokio atm as dependency but maybe in the future, so i don't know if it's worth using tokio's variant if i got to install the dependy just for that, flume works with stdlib

#

cc @sharp geyser - i think you also code in rust PepeHmm

earnest phoenix
#

essentially what tokio's mpsc do but standalone

radiant kraken
#

i've never used flume, i've only used tokio's

pure vessel
#

when did null code in rust

radiant kraken
#

since 2021

earnest phoenix
#

you got to use tokio's threads? or you can also use std?

radiant kraken
#

the former

#

if you use std, it will be blocking

#

(to join)

earnest phoenix
#

i got twice the same code with tokio and flume, both work 1 to 1 the same

#

feel like adding tokio as dependency just for mpsc is maybe too much

radiant kraken
#

exactly

#

same as what i thought

#

i rarely add more dependencies unless it's very necessary

earnest phoenix
#

and i can't get just tokio mpsc and threads

#

like somehow just install these two

radiant kraken
#

wdym?

earnest phoenix
#

instead of cargo add tokio -F full, just get the two features

radiant kraken
#

wait i think i read that wrong

#

my bad

#

are you using the tokio runtime?

#

like the runtime itself for async/await purposes

earnest phoenix
#

not right now

#

maybe later, don't know

radiant kraken
#

or are you using another async runtime like async-std

earnest phoenix
#

i just want to run threads concurrently and atm it works with std

radiant kraken
#

ah, so blocking

earnest phoenix
#

the code inside the threads yeah, the threads/tasks run all at the same time though

radiant kraken
#

ah icic

#

then for now i suggest flume

#

if you do use the tokio runtime, use tokio

earnest phoenix
#

okie dokie

#

kinda makes sense because i used

txt.send(Event::Ready).await.unwrap();

everywhere KEKWaddle

pearl trail
#

pros

radiant kraken
#

you

earnest phoenix
#

with tokio i didn't

#

i used a tokio's thread, but in the end it's the same as std thread?

#

or are they lightweight or something idk

radiant kraken
#

no, tokio's threads allow you to run async code/futures in a separate thread

#

you can also run blocking code in a tokio thread

earnest phoenix
radiant kraken
#

the thing with tokio threads is that you can join them with await afaik

earnest phoenix
#

though if i don't really make use of tokio's features, it doesn't make much sense to use them?

#

like with tokio i did

tx.send(Event::Ready).await.unwrap();

and with flume i did

tx.send(Event::Ready).unwrap();

which is essentially the same?
like i don't really use await/async within the thread::spawn

radiant kraken
#

huh, alright

#

what about in your codebase? do you use async/await?

earnest phoenix
#

nope

#

i just want multiple tasks to run in background

radiant kraken
#

oh alright then there's no need to use tokio

earnest phoenix
#

code in the tasks themselves are blocking either way

#

but the difference between a tokio::spawn and std::thread::spawn is none?

#

without taking into account that tokio can use await etc. in them

#

in both spawned threads the code is blocking

radiant kraken
earnest phoenix
#

and the threads/tasks spawned are the same on the cpu

radiant kraken
#

you can achieve std functionality in tokio with tokio::spawn_blocking tho

earnest phoenix
#

like there isn't one that is more lightweight than the other

radiant kraken
#

when we're talking lightweight then std obviously wins

#

because there's no need to worry about async/await stuff

earnest phoenix
#

yeah there's no wrapper around it

radiant kraken
#

precisely

earnest phoenix
#

and can you limit the threads spawned? like 50 and then it automatically waits

#

or i gotta make a thread pool or smth

radiant kraken
#

limit the threads spawned? hmmmm

earnest phoenix
#

like i don't want it to spawn like 5000 threads

#

iirc the limit is os limit, but don't want to go that high either

#

there's apparently semaphore but idk

radiant kraken
earnest phoenix
#

seems like it doesn't prevent the threads from being created but just the code within the thread to not continue if you get over the limit when getting a permit, i'll look a bit more into that MF_Reading

radiant kraken
#

yeah semaphores take a bit to master

earnest phoenix
#

thanks for everything salute

lyric mountain
#

You've got a stock of 40 tickets for sale, you can't go over it

#

However, used tickets will be resold for the next show, so whoever is done "opens up" their seat

earnest phoenix
#

but people can still enter the show, just not sit until someone stands up

#

at least from what i understand

lyric mountain
#

They can wait in the queue, but can't enter

#

Most langs will have 2 acquire methods, one being getOrFail and the other getOrWait

#

The former won't even wait, just straight up error

earnest phoenix
#

oh wait, that is interersting

lyric mountain
#

The latter will hold the thread till a slot is opened

earnest phoenix
#

yeah, that is what i don't want it to do

#

but getOrFail looks like what i want

lyric mountain
#

What lang

earnest phoenix
#

rs

#

all in tokio šŸ’€

#
use tokio::sync::{Semaphore};

let semaphore = Semaphore::new(2);

let permit = semaphore.try_acquire().unwrap();
lyric mountain
#

Yeah saw try_acquire on docs, that appears to be what you want

earnest phoenix
#

but i don't want to install tokio just for that Smiley

lyric mountain
#

Ah, right, well you can make your own semaphore handler

earnest phoenix
#

semaphore crate seems do be simple enough

lyric mountain
#

It's really not that hard

earnest phoenix
#

seems painful enough

#

it's like stuff i've never looked at before

lyric mountain
#

Nah, it just an int counter

#

When someone acquires, decrease by 1

#

When someone releases, increase by 1

earnest phoenix
#

ah

lyric mountain
#

The hardest part is just holding off the thread

earnest phoenix
#

well i don't need to hold it

#

i just want it to fail and close it

#

so probs much easier to implement

lyric mountain
#

Yep, just throw an error if permits <= 0

earnest phoenix
#

lmao pog

lyric mountain
#

Idk if rust does, but make sure the number is atomic

earnest phoenix
#

thought it was fancy background threading shit

lyric mountain
#

Semaphores are really simple in concept, it's just an atomic number that forces a limit upon stuff

earnest phoenix
#

AtomicUsize::new(0)

lyric mountain
#

Yeah use that, atomic guarantees the number will be the same across any thread

#

No chance of race condition or dirt reads

earnest phoenix
#

still no idea how atomic stuff works in the background but i know it's fancy

lyric mountain
#

It's basically a reference to a value, instead of the value

#

So any read regardless of thread will refer to that reference

earnest phoenix
#

but what if thread 3 edits the value

#

thread 2 and 1 may not see the same value

lyric mountain
#

They will, cuz it's the same address

earnest phoenix
#

yeah but they may not access it at the same time, even if they run in a while true loop in the background

#

at some point they'll see the same value, but not at the exact same time?

lyric mountain
#

Like, you shouldn't store the value of the atomic in a variable ofc, always read from the atomic directly

earnest phoenix
#

yeah definitely

lyric mountain
#

Atomics are sync, so you can't have 2 threads editing it at the exact same time

#

If you edit in one then all others will see the new value too

#

Hate oracle but here's some explanation

earnest phoenix
#

so it's pretty much what a mutex does

#

or at least sort of

lyric mountain
#

Well, kinda a mutexed value if you will

#

Mutexes are more like a bouncer that only allows 1 person to be inside the room at any time

earnest phoenix
#

yeah you just don't need to have a mutex to control the variable

lyric mountain
#

Yep

earnest phoenix
#

the variable itself is kinda the mutex and does everything

#

though they don't use locks

#

as anyone can read it

earnest phoenix
raven nexus
#

is there a guide to write a base?

earnest phoenix
#

@solemn latch

quartz kindle
raven nexus
deft wolf
#

There are probably plenty of templates on github

raven nexus
#

what is the keyword should i search

coral pagoda
deft wolf
#

Probably something like discord bot and filter by the programming language you are interested in

coral pagoda
#

oh template

earnest phoenix
quartz kindle
#

unsigned integer underflow? :^)

earnest phoenix
#

yeh was doing a sub and it was already 0 Smiley

radiant kraken
#

they are like alien to me

earnest phoenix
#

yeah i swear, i just use whatever internet recommends me lmao

lyric mountain
lyric mountain
#

when you have an atomic value it means that value will BE that value regardless of where you use it, and any change will be set globally across the runtime

quartz kindle
#

ie, when you atomically change a value, do you want it to atomically update the order/sequence of the store/array, or not nvm

#

the cpp explanation looks better anyway

#

when multiple threads simultaneously read and write to several variables, one thread can observe the values change in an order different from the order another thread wrote them. Indeed, the apparent order of changes can even differ among multiple reader threads.

dry frost
#

hello

#

im add my bot to top.gg so im waiting for acc?

eternal osprey
#

LETSS GOOO BOYS

#

I SUCCESSFULLY HACKED 4 FUCKING PC'S

#

(legally, it was my hacking exam)

lament rock
#

Cant believe they killed my boy @prisma lichen

eternal osprey
#

Call me hecker

raven nexus
#

anyone use mongodb here?

pearl trail
sharp geyser
pearl trail
gilded anvil
green kestrel
#

I have an answer

gilded anvil
dry frost
#

@bitter granite

deft wolf
bitter granite
#

Wait what did i do?

dry frost
#

im relly not see my bot can send nsfw tf

deft wolf
#

Write a private message to the person who reviewed your bot and explain it to them

#

They definitely have more information than we do

bitter granite
dry frost
#

thanks

earnest phoenix
#

for those interested

steady saffron
#

using next.js v14 app router, i have a discord application system where users can create or fill out custom applications for guilds.

currently, i fetch the form for every single user viewing (because i parse a 'userid' header so my bot can determine what data to send for each user depending on permissions within the Discord server.
however, this can be A LOT of data transferred and cached because most forms on average 10 questions, with descriptions, custom HTML, custom validation etc

i plan on moving the form data fetch to a global request which is fetched once and reused between all users and make a second api request to fetch the users permissions which would determine what they can / can't do as well as providing additional data for what would be included in the form fetch provided they have the permissions.

  1. both requests would be blocking meaning it would have to be done before the page is rendered to the client
  2. if a form is hidden, i would have to return the form in the user specific request (the new route i plan on adding)

what would you guys advise me doing ? whether to keep it how it is, fetch the form data for every user, or introduce a new route separate to the form data to check permissions / provide additional data and why would this be better? (essentially it's like bot pages on top.gg, how could i cache the main fetch to the bot data, and then get the additional data if the member has permissions)

lyric mountain
timber hatch
#

yappatron

steady saffron
lyric mountain
coral pagoda
#

same

#

i tried to ask gpt to summarise it but it couldnt

lyric mountain
#

What forms are we talking about? Are them the same for every user?

steady saffron
# lyric mountain What forms are we talking about? Are them the same for every user?

okay so imagine google forms for discord.

discord servers create a form, they can edit it, hide it or share it with their members for them to fill out at a url like domain.com/:formId
this means that whenever accessing this url, i will need to determine the permissions the user has in the discord server. if they have manage guild permissions, then i provide extra properties, otherwise i dont.

with this said, the form data is currently fetched for every single user who accesses this page and then cached for an hour
i want to change this and make it so it's fetched one time and then cached and another request is made to check their permission so this means the form data won't be getting fetched over and over again resulting in a lot of cached and transferred data, however im not sure if this is the best choice which is why im coming here for advice on the best choice

lyric mountain
#

It's simple, just store the form somewhere, then cache the answers themselves

steady saffron
#

i dont think you're understanding

lyric mountain
#

Probably not

steady saffron
#

okay let me use top.gg as an example

coral pagoda
#

probably would be better if you keep it short

steady saffron
#

you have bot pages which top.gg needs to fetch the data for
the owner of the bot has extra data whereas everyone else hasnt

#

i currently fetch the bot data and cache it for every single user (each user has their own fetch cached)

#

i want to fetch the bot data once, and alongside it, make another request to fetch their permissions

#

so the fetch for the bot data is always reused and i can render additional details depending on their permissions

#

whats the better option, fetching and caching for every user leading up to a significant amount of data transferred and cached

#

or, fetch and cache one time and make a fetch every time for the users permissions

#

is this clearer? @lyric mountain @coral pagoda

lyric mountain
#

I still don't get it, why cant you store the form once? Does it change for every user?

steady saffron
#

and then to get the extra data, make another api request to a different route to return data depending on their permissions

#

or would this harm performance? because its increasing blocking time

coral pagoda
#

have an endpoint for admins?

lyric mountain
#

Simply hash the form, only refetch it if the hash mismatches

steady saffron
steady saffron
lyric mountain
#

When the user submits the form (I suppose discord form) you have the full form object right there, which u can hash

#

On the server, you can do the same

steady saffron
#

what? this is when viewing the form page on my website

#

i need to render the form to the user

#

and display extra stuff if the user viewing is an admin

lyric mountain
#

Yes

#

Hash locally, hash at the server, if mismatch then invalidade cache

#

But I'm really struggling to understand what u mean at all, images would help a lot to understand ur current system

steady saffron
#

also i cant access any local storage (if you're referring to browser storage) because this is all done on the server

#

the only way i can get the data is via fetch

#

so my only options is to keep doing what im doing, fetching and caching the same form data for every single user who views it
OR
fetch and cache it one time, reusing this data and making another api request alongside it to determine the members permissions

lyric mountain
steady saffron
#

it is cached on the server, next.js does that

#

it caches the response of the fetch call

#

and when the fetch call to the same url, headers, etc is made again, it will reuse the data

lyric mountain
#

not what I mean by cache

#

ok, let's start from the beginning, you have a site that allows viewing form X, right?

#

said form will be seen differently depending on whether the viewer is a simple user or the form's creator

#

what I dont understand is why you're having to fetch anything at all

hidden gorge
#

MongoDB Returning User Already Exists even though they don't

Create Endpoint:

  app.post('/create/user', async (req, res) => {
    console.log("BODY:", req.body);

    try {
        const Username = req.body.username;
        const NonHashed = req.body.password;

        if (!Username || !NonHashed) {
            return res.status(400).send('Username and password are required');
        }

        const sRounds = 10;
        const salt = await bcrypt.genSalt(sRounds);
        const hashedPassword = await bcrypt.hash(NonHashed, salt);
        
        const UserData = new UserModel({ Username: Username, Password: hashedPassword });

        await UserData.save();
        res.status(201).send('User created successfully');
    } catch (err) {
        console.error(err);
        res.status(500).send('Internal Server Error');
    }
});

Error:

PS C:\Users\therb\Projects\Websites\FireReporter> node . 
MongoDB Connected
BODY: { username: 'testUser1', password: 'testPassword1' }
MongoServerError: E11000 duplicate key error collection: test.users index: username_1 dup key: { username: null }
    at InsertOneOperation.execute (C:\Users\therb\Projects\Websites\FireReporter\node_modules\mongodb\lib\operations\insert.js:51:19)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async tryOperation (C:\Users\therb\Projects\Websites\FireReporter\node_modules\mongodb\lib\operations\execute_operation.js:192:20)
    at async executeOperation (C:\Users\therb\Projects\Websites\FireReporter\node_modules\mongodb\lib\operations\execute_operation.js:69:16)
    at async Collection.insertOne (C:\Users\therb\Projects\Websites\FireReporter\node_modules\mongodb\lib\collection.js:154:16) {
  errorResponse: {
    index: 0,
    code: 11000,
    errmsg: 'E11000 duplicate key error collection: test.users index: username_1 dup key: { username: null }',
    keyPattern: { username: 1 },
    keyValue: { username: null }
  },
  index: 0,
  code: 11000,
  keyPattern: { username: 1 },
  keyValue: { username: null },
  [Symbol(errorLabels)]: Set(0) {}
}
POST /create/user 500 111.804 ms - 21
#

Only entry in the db is this:

lyric mountain
#

is username supposed to be null?

hidden gorge
#

this is how im testing it.

lyric mountain
#

please use uniform case btw, either camel or Pascal

#

preferrably camel

hidden gorge
lyric mountain
#

ok but it takes no time to simply use the proper casing

steady saffron
hidden gorge
# lyric mountain what's `UserModel` class?

lemme grab it.

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const UserSchema = new Schema({
    Username: { type: String, required: true, unique: true },
    Password: { type: String, required: true },
    Profile: {
        displayName: { type: String },
        avatarURL: { type: String, default: "https://us-east-1.tixte.net/uploads/cdn-firereporter.tixte.co/DefaultAvatar.png" }
    }
});

module.exports = mongoose.model('User', UserSchema);
lyric mountain
steady saffron
lyric mountain
#

to see what's being passed to it

lyric mountain
lyric mountain
#

if both the creator and the user are viewing it on the site, where does discord fit into it

steady saffron
lyric mountain
#

ok but what are u fetching from discord?

steady saffron
lyric mountain
steady saffron
#

the only thing i fetch from discord is the user viewing the form

hidden gorge
hidden gorge
lyric mountain
#

the user viewing the form is in discord or in the site?

steady saffron
#

they see the form on the website.
they authorise their discord account

lyric mountain
# hidden gorge

oh, actually, can you see the document structure at mongo itself?

#

note username: null is written in lowercase

lyric mountain
#

I think you might've created a structure that's { username, Username, Password, Profile }

hidden gorge
#

wdym

lyric mountain
#

basically u have 2 fields with the name name, just diferring at case

#

since ur never sending username, it's null

hidden gorge
steady saffron
#

@lyric mountain

hidden gorge
#

nvm i didnt

#

its still broken

lyric mountain
#

try adding another field to your model called username

#

lowercase

#

see if it allows you to save if that field is filled

hidden gorge
lyric mountain
#

yes

hidden gorge
#

like this?

lyric mountain
#

yes

hidden gorge
#

welp that failed

lyric mountain
#

what now?

hidden gorge
lyric mountain
#

well yes, fill both

lyric mountain
# steady saffron <@350836145921327115>

you'll have to re-fetch user permissions everytime, this isn't avoidable but the form you can use a single cached version for all viewers, simply store it in a global cache in the server

hidden gorge
steady saffron
lyric mountain
#

it is better cuz you're reusing a single instance to serve all users, since it's supposed to be the same on all ends fetching a new instance everytime would be wasteful

#

you can hide the secret stuff at clientside

steady saffron
#

the only thing now is that the discord admins can hide their form, meaning the route which fetches the form data wouldn't know if it's an admin trying to view

#

so if the form is hidden, in the user permission fetch, i would have to return the form data depending if they're admin right

lyric mountain
hidden gorge
lyric mountain
#

but this confirms what I meant

#

you have a dangling field in your form at database

hidden gorge
hidden gorge
lyric mountain
#

can you drop your whole model and recreate again?

hidden gorge
#

ok i dropped it

lyric mountain
#

not discord token, you own generated ones

steady saffron
#

no, i have session tokens and that pretty much all

lyric mountain
steady saffron
#

i use auth.js

hidden gorge
lyric mountain
#

be careful with your namings, cases matter

steady saffron
#

and regardless, in-discord permissions can change so storing their permissions will not be ideal

lyric mountain
lyric mountain
#

include it in the body or a header

#

then at the server check if the perms contain what they need to contain

steady saffron
lyric mountain
#

no

#

you'll only fetch the user permissions, nothing more

#

the form will still exist on the server, you'll simply modify the response depending on their permission

steady saffron
#

how will it exist on the server when its on a database used on a completely separate server

#

its hosted serverlessly (the nextjs app)

#

hence why i have a separate express api on my discord bot

#

which is where i fetch the form data from

lyric mountain
#

the form is cached somewhere (ignore nextjs for now), acessible by an identifier

#

the api should return given form

#

on that same endpoint, you'll receive user permissions on a header/body

#

simply change your response depending on the permissions

steady saffron
#

but i dont know the users permissions?
if they have manage guild permissions (in the discord server) they're considered a form admin, otherwise, a regular user

lyric mountain
#

you know because you sent in the GET request you used to fetch the form

steady saffron
#

yes which is what im currently doing and this results to fetching and caching the form data for every unique user

#

i cant store the form data when its serverless hence why the nextjs cache does that

lyric mountain
#

but you dont need a cache for EVERY user, you just need one, unique cache entry

#

which is the full form

steady saffron
#

yeah which is on the bot API which stores the form data

lyric mountain
#

there you go

#

cache on the database

steady saffron
#

yeah but i cant connect to the database on the next.js app

lyric mountain
#

the api can

steady saffron
#

which it does

lyric mountain
#

lemme draw for you, sec

steady saffron
#

the api gets the form data from the database and appends a few more properties if the user requesting it is a form admin

lyric mountain
#

yes, exactly

#

this is what ur supposed to do, it's doing a single fetch in this case

steady saffron
#

keeping in mind, i also need to be able to know if this specific user has even filled out this form yet, if so, they shouldnt be able to fill it out again (by displaying this on the UI)

lyric mountain
#

well, 2, one being to get user permission

steady saffron
lyric mountain
#

the single fetch is your app getting the form from the api

#

I said "well, 2" because the other is getting permissions from discord

#

also dont cache fetches if the answer is dependable on context

steady saffron
#
  1. user goes to domain.com/[formId]
  2. fetch request to get form data (either request or get from cache - handled by next fetch method), fetch user permissions
#

is this what you mean

lyric mountain
#

almost, cut the next part

#

next shouldn't cache a response that might vary depending on context

#

you have 4 context for your endpoint:

  • User is admin and can see all data
  • User is common and cannot see all data
  • Form is private and user is admin, so they can see
  • Form is private and user is common, so they cant see
steady saffron
lyric mountain
#
  1. user goes to domain.com/[formId]
  2. fetch request to get form data, fetch user permissions
steady saffron
#

so dont cache.. anything?

lyric mountain
#

you do, on the api

#

or in this case, u dont since ur serverless

steady saffron
#

i dont need to cache the data on the API though

#

i need it cached on the next.js app for the highest possible performance

lyric mountain
#

then just ditch the whole caching, you dont need it at all

#

you simply cannot cache at next.js side because it depends on context

#

the response might be totally different depending on permissions

steady saffron
#

but the chances of form data being changed is minimal meaning ill be refetching the same data so many times unnecessarily

lyric mountain
#

then simply include the permission bitfield in the fetch request

#

if they change then next.js will drop the cache no? since the request was changed

quartz kindle
#

if you want absolute performance, run a discord websocket and listen to role edits in real time, so you always have updated permissions locally

#

but of course, that is extremely unscalable

#

well to be honest, depending on how often the forms are accessed, it could be more scalable than fetching every time

steady saffron
#

this is what ive been thinking about doing

lyric mountain
#

the issue is that you're overthinking

steady saffron
#

if the form was only just made hidden, im not bothered about it still being accessible for a short while because POST requests wont be processed

lyric mountain
#

you said that next.js will use cached view if the request is exactly the same right?

steady saffron
#

yeah

lyric mountain
#

then simply include a header with the user permissions you got from discord

steady saffron
#

right now i parse user id in the header so requests are different for each user

lyric mountain
#

u dont need to do anything else

quartz kindle
#

having a short lived cache is a good idea, as long as you have it well written somewhere and also have a refresh button

steady saffron
quartz kindle
#

i mean for example, user changes roles on discord so now his permissions are different
user accesses form, sees form for old permissons
have button the user can click to refresh form and update permissions

lyric mountain
#
GET http://yoursite.com/[the endpoint]
- X-UserPerms: [perms int discord gave you]
#

next.js will ditch the cache if the permissions change

#

if you want to be even more precise, send the single bit regarding MANAGE_SERVER permission

steady saffron
#

yeah however that introduces this:

  1. fetch and cache form data for every unique permissions (to bot api)
  2. fetch permissions from discord (to discord)

when i could do this:

  1. fetch form data and cache only providing regular user data - only cached once (to bot api)
  2. fetch user and if they have permissions, send the remaining properties (to bot api)
lyric mountain
#

fetch and cache form data for every unique permissions
refer to my appended message

lyric mountain
#

it'll only cache 2 answers

#

either 1 or 0 for that specific bit

steady saffron
#

true, but now i need to know if this user has filled the form out, i know you mentioned something about a token but im not sure how this would work, especially as 1 user can fill out limitless forms (for other servers / other forms)

lyric mountain
#

you dont need to know if they filled the form

steady saffron
#

this would be solved by option 2 in my previous reply

lyric mountain
#

you have that bit the moment discord gave you the perms

#

oh, right nvm, u mean filled previously

steady saffron
#

thats why i think the 2nd option would be better then i cache minimal

lyric mountain
#

how do you know that atm?

steady saffron
#

right now:

  1. fetch form data with user-id header
#

so its fetched and cached for every unique user

#

which i want to not do

lyric mountain
#

that shouldn't be cache at all

steady saffron
#

why wouldnt i cache this?

#

i dont want to make an api call everytime the same user goes back to this page

#

especially when nothings changed

lyric mountain
#

"Hey server, how many people are inside there? Actually dont answer, I already know it's 5 people since I'm using red shirt today"

  • There were 17 people
steady saffron
#

yeah, but i revalidate the form when it changes meaning if the user goes back, the updated version will be used

lyric mountain
#

if you're asking something to the server, you dont cache the response, you need a true-state response

#

overusing next.js weird caching is hurting you more than it's worth it

steady saffron
#

how?

lyric mountain
#

the only things you need to cache are things that are immutable (at least on a short timeframe)

steady saffron
#

but i cache them, and once the data is changed, i "clear" the cache for that form

#

therefore it always shows up to date data

lyric mountain
#

yes, but you could simply never cache it to begin with

steady saffron
#

which means i have to make an api request EVERY TIME someoen goes to that page

#

which ruins performance

lyric mountain
#

you will be doing a request regardless

steady saffron
#

how so?

lyric mountain
#

you're purging the cache as you said

steady saffron
#

yeah, if the data is changed

lyric mountain
#

and you'll only check if the user filled a form when submitting it no?

steady saffron
#

user123 fills out form -> revalidate their cache

therefore when user123 goes to /form/x it will be refetched

#

then the next time they go to it, it will be a cache hit

#

revalidate means to refetch their next fetch

#

then cache that

steady saffron
#

what about it ?

lyric mountain
#

you said you need to know if the user already filled the form beforehand

steady saffron
#

yeah, if they havent yet been to that route, then the data will be fetched therefore up to date

lyric mountain
#

yes, exactly, THIS is the endpoint that I said you dont (and shouldn't) cache

#

because it'll never use the cached view

steady saffron
#

but it will?

#

if they refresh or go back to it without fillign out the form

lyric mountain
#

ok, let's go slowly

#

when do you check if the user already filled the form?

#

before even starting or right before sending the data?

steady saffron
#

in the only api request i do, alongside fetching form data

lyric mountain
#

so you fetch before even starting right?

steady saffron
#

i fetch when they go to the page

lyric mountain
#

so why did you say it'll have many cached versions? it should only have 1 at all time

steady saffron
#

because its fetched for every unique user? each user has its own cached version of the form data and extra properties (e.g. if they've filled it out) which is sent in the same request as the form data

lyric mountain
#

let's talk individually

#

as in, single user

#

it's easier to understand what ur doing

#

the relation of that endpoint is - given ONE user, you'll have ONE cached view, right?

steady saffron
#

yes

lyric mountain
#

ok, then no issue here, you can keep it as is

#

for the other endpoint, the one where you get the actual form - given ONE user, you'll have TWO cached views

steady saffron
#

i dont understand

lyric mountain
#

1 - Permission bit is 0
2 - Permission bit is 1

#

permission bit being the permission extracted from the permissions bitfield discord gave you

#

you'll include it every time you try to get the form itself

#

this will make next.js create at most 2 cached views, since the rest will be the same

steady saffron
#

yeah but how would i get whether or not they've submitted the form before

lyric mountain
#

you already fetched that info the moment they opened the page, as you said

lyric mountain
#

you'll be doing 2 fetches

steady saffron
#

thats what i do currently, but as i've said, i want to stop doing what i currently do

lyric mountain
#

one for the "has filled" and one for the actual form

steady saffron
#

right now, i already know their permissions on the bot api therefore the data i get is always right (whether they're admin or normal)

#
export async function Page(...) {
  const response = await fetch('url', {
    headers: {
      APIKey,
      'user-id': session.user.id
    },
    next: {
      revalidate: 3600,
      tags: [`formData:${formId}`, `formData:${formId}:${session.user.id}`]
    }
  }

  // this resposne is cached for every unique user
  // if user 1 goes to this page, it will be fetched then cached
  // if user 2 goes to this page, it will be fetched then cached
  // if user 1 refreshes, it will be retrieved from cache
  // if user 3 goes to this page, it will be fetched then cached

  // total fetches and data cached = 3
  // this form is therefore fetched and cached 3 times when it doesn't need to be
}```
lyric mountain
#

the only way you could go lower - 2 cached views - is by stop using next.js cache and make your own handler

steady saffron
#

how could it possibly get lower when i need to know user specific data?

lyric mountain
#

save the form in a (not next.js) cache, including visibility and which fields are private (only admins can see)

#

in the app you'll only have 2 cache views

#
  • Whether the user has filled the form already
  • The form
#

the latter is regardless of user permissions, you'll handle that locally

#

in this one you'll disable next.js caching for that specific route

#

and handle caching yourself

steady saffron
#

my idea was this:

export async function Page(...) {
  const formDataRes = await fetch('../api/forms/:formId', {
    headers: APIKey,
    next: {
      revalidate: 3600,
      tags: [`formData:${formId}`]
    }
  }

  const userPermissionsRes = await fetch('../api/forms/:formId/:userId', {
    headers: APIKey,
    next: {
      revalidate: 300, // cache for only 5 minutes 
      tags: [`formData:${formId}:${userId}`]
    }
  }

  // if user1 goes to this page, form data will be fetched and cached, their permissions will be fetched and cached
  // if user2 goes to this page, form data will be cached, their permissions will be fetched and cached
  // if user1 goes back to this page, form data will be cached, permissions will be cached
  // if user3 goes to this page, form data will be cached, permissions will be fetched

  // total fetches = 4
  // form data cached only 1
  // user permissions cache = 3 (but this data is minimal)
}```
#

so i sacrifice 1 extra fetch to only have form data cached once

#

therefore i eliminate having the same massive form data cached multiple times

lyric mountain
#

user permissions cache = 3
???

#

the lowest possible is what I said, 1 cache for form and 1 for "has filled" state

steady saffron
lyric mountain
#

yes, but why 3?

#

it should only ever have 1 value

steady saffron
#

because 3 users went to the page

#

the user permissions would return this:

  1. additional form properties
  2. hasFilled
lyric mountain
#

you see, this is confuse as hell

#

dont use multi-user when explaining things

#

we're talking about a scenario where one user is accessing the site, let's keep things at him/her

steady saffron
#

but in the comments, you can see i used user1, user2 and user3

lyric mountain
#

yes

steady saffron
#

that helps demonstrate the flow of the code more and how much is actually being cached

lyric mountain
#

yes but if it's a site, then you'll only have 1 user in the cache

steady saffron
#

you said your idea is

1 cache for form and 1 for "has filled" state
what about if 2 users went? is it then 2 cache for form and 2 for has filled state?

lyric mountain
#

site caches are stored locally, not on the server

steady saffron
#

but this is ran on the server due to SSR

lyric mountain
steady saffron
lyric mountain
#

yes

#

but yours use next.js cache, in my case it's regardless of it

#

either a redis file or in-memory expiring map

#

this also has the advantage that u can get the data regardless of request

steady saffron
#

why wouldnt i use next.js cache when im using next.js and hosting on vercel? when using next.js cache, it creates a file in the .next build files and its hosted serverless

lyric mountain
#

cuz you're constrained in how you can access the cache

#

next.js will only use the cache if the request is the same

steady saffron
#

which is all i need

#

no?

lyric mountain
#

but with a separate cache you could access it even in different requests

steady saffron
#

i dont need to fetch it any other way

#

i can easily revalidate the cache, and once done, it will be refetched and recached

#

just as i need

lyric mountain
#

then carry on

eternal osprey
#
function romanToInt(s: string): number {
    return recursiveSolver(s, 0);
};

function recursiveSolver(s: string, v: number):number{
   if(s.length == 0) return v;
   if(s.length == 1) return v + calculateValue(s);
   let firstChar:string = s[0];
   let secondChar:string = s[1];
   let combined:number = checkSpecificCombo(firstChar+secondChar);
   if(combined !== 0){
    let remainder:string = s.slice(2);
    return recursiveSolver(remainder, combined + v);
   }else{
    let remainder:string = s.slice(1);
    return recursiveSolver(remainder, calculateValue(firstChar) + v);
   }
}

function checkSpecificCombo(combined:string):number{
    let value:number = 0;
    switch(combined){
        case 'IV':
        value = 4;
        break;
        case 'IX':
        value = 9;
        break;
        case 'XL':
        value = 40;
        break;
        case 'XC':
        value = 90;
        break;
        case 'CD':
        value = 400;
        break;
        case 'CM':
        value = 900;
        break;
        default:
        value = 0;
        break;
    }
    return value;
}
function calculateValue(s: string):number{
    let value:number = 0;
    switch(s){
        case 'I':
        value =  1;
        break;
        case 'V':
        value = 5;
        break;
        case 'X':
        value = 10;
        break;
        case 'L':
        value = 50;
        break;
        case 'C':
        value = 100;
        break;
        case 'D':
        value = 500;
        break;
        case 'M':
        value = 1000;
        break;
    }
    return value;
}```
anyone got some optimizations for this leetcode solution?
earnest phoenix
#

why do you want optimization, i love it

#

just the formatting that is weird , but such code is 21/20

eternal osprey
#

i am acoustic i can't know whether you are sarcastic or not lmao

eternal osprey
earnest phoenix
#
function romanToInt(s: string): number {
    return recursiveSolver(s, 0);
};

function recursiveSolver(s: string, v: number): number {
    if (s.length == 0) return v;
    if (s.length == 1) return v + calculateValue(s);
    let firstChar: string = s[0];
    let secondChar: string = s[1];
    let combined: number = checkSpecificCombo(firstChar + secondChar);
    if (combined !== 0) {
        let remainder: string = s.slice(2);
        return recursiveSolver(remainder, combined + v);
    } else {
        let remainder: string = s.slice(1);
        return recursiveSolver(remainder, calculateValue(firstChar) + v);
    }
}

function checkSpecificCombo(combined: string): number {
    let value: number = 0;
    switch (combined) {
        case 'IV':
            value = 4;
            break;
        case 'IX':
            value = 9;
            break;
        case 'XL':
            value = 40;
            break;
        case 'XC':
            value = 90;
            break;
        case 'CD':
            value = 400;
            break;
        case 'CM':
            value = 900;
            break;
        default:
            value = 0;
            break;
    }
    return value;
}

function calculateValue(s: string): number {
    let value: number = 0;
    switch (s) {
        case 'I':
            value = 1;
            break;
        case 'V':
            value = 5;
            break;
        case 'X':
            value = 10;
            break;
        case 'L':
            value = 50;
            break;
        case 'C':
            value = 100;
            break;
        case 'D':
            value = 500;
            break;
        case 'M':
            value = 1000;
            break;
    }
    return value;
}
earnest phoenix
lyric mountain
eternal osprey
#

damn mf gave me hope with that 21/20

earnest phoenix
eternal osprey
#

but guess we back in the trenches

lyric mountain
#

ah it's chitty asking

eternal osprey
#

elo

lyric mountain
#

well, use a map + regex

eternal osprey
#

why would a map be beneficial in this case?

lyric mountain
#

O(1) retrieval

eternal osprey
#

regex is very much understandable, i was thinking about it as well but i hate it

lyric mountain
#

for regex you'll use /I[VX]|X[LC]|C[DM]|[IVXLCDM]/

#

simply iterate all matches and value += map[match]

eternal osprey
#

damn that reduces the complexity of my code to a few lines lmao

#

thank you very much!

lyric mountain
#

lul yw

eternal osprey
#

nah idk such problems that are on leetcode are like 140% easier in haskell for some reason

#

everything seems so simple in haskell. especially as you don't have to deal with crazy ahh loops etc.

#

i am a haskell fanboy

neon leaf
eternal osprey
#

it looks alr

#

my shit is better but i mean, everyone has to start somewhere

neon leaf
#

<1ms time to run on cold start šŸ”„

neon leaf
wheat mesa
#

I'm trying to make a web app with Vue as the frontend and ASP.NET as the backend. How should I implement OAuth2 so that I can do the following?

  1. Prevent users from navigating to certain routes on the frontend (securely, people should not be able to access the page by modifying some sort of local data like localStorage)
  2. Validate requests to certain endpoints on the ASP.NET backend
  3. Not need to frequently log in to the site and re-authorize
sharp geyser
#

What is your oauth2 provider?

wheat mesa
#

MS and Google accounts

sharp geyser
sharp geyser
#

Anyway off topic

#

Storing it in localStorage is honestly the best way

#

the library I use for handling talking to my auth server (which acts as a middle man for MS and Google) saves the resulting ID Token & access token to localStorage

#

This is stored in localStorage, which is accessible via the lib I use

#

to be frank, it doesn't matter if its in local storage, if its something completely unique / random. If someone puts in an access token and it is somehow valid, well that means someone leaked their own access token (which trying to guard against that is not worth putting time into)

#

I really don't know any other way you can do this in the browser without using localStorage or sessionStorage

wheat mesa
#

ok I’ve run into a bigger issue for now

#

I had to purge my NVIDIA drivers because I updated and Linux Mint would not boot. However, my network drivers might’ve gotten damaged in the process because now when I boot I have no network connections recognized (even when using Ethernet!). Doing ip link shows that I don’t have anything other than lo, and gpd0, so it isn’t even recognizing my network interfaces. How should I go about fixing this? I cannot access the internet so I cannot do something as simple as apt install linux-firmware

#

I’m going to go to sleep but any advice would be seriously appreciated

radiant kraken
#

very useful error message

sharp geyser
#

well, give it a callable

eternal osprey
#

that is what i did once for client-side session management

earnest phoenix
#

the one starting at line 8

neon leaf
#

translated into normal sql:

SELECT 
  json_extract(data, '$.build.versionId') AS version,
  COUNT(*) AS total,
  COUNT(DISTINCT ip) AS uniqueIps
FROM 
  requests
WHERE 
  data IS NOT NULL
  AND path NOT LIKE '%tracking=nostats%'
  AND data LIKE '%lookup%'
  AND json_extract(data, '$.build.versionId') IS NOT NULL
GROUP BY 
  json_extract(data, '$.build.versionId')
ORDER BY 
  total DESC```
lyric mountain
#

ah, much better

#

try ```sql
SELECT x.version
, COUNT(*) AS total,
, COUNT(DISTINCT ip) AS uniqueIps
FROM (
SELECT json_extract(data, '$.build.versionId') AS version
FROM requests
WHERE data IS NOT NULL
AND path NOT LIKE '%tracking=nostats%'
AND data LIKE '%lookup%'
) x
WHERE x.version IS NOT NULL
GROUP BY x.version
ORDER BY total DESC

neon leaf
#

dam, like double the speed already

lyric mountain
#

the trick is getting json_extract only after you run the other filters

#

if you put a function in the where clause it'll have to run for every single row on the table

#

but if you reduce the sample beforehand you only need to run it in a small amount

#

oh, put the where version is not null back

#

forgot to include it

neon leaf
lyric mountain
#

there

#

it's best if you avoid leaving optimization to the database, also EXPLAIN helps a lot finding bottlenecks

neon leaf
#

yeah, I should use subqueries more often. thanks for the help!

lyric mountain
#

yw

lyric mountain
neon leaf
#

🤨

lyric mountain
#

or at least it seems to, from what their blog says

frosty gale
#

sql database users wondering why their 100m row table with no index and with string wildcard lookups takes ages

neon leaf
#

smh its cuz theres no jsonb column or whatever in d1

lyric mountain
#

btw why dont u map the version to a column instead?

neon leaf
#

theres a lot of different data schemas that can be in that data field

lyric mountain
#

you can use a trigger to map it

#

this way you can make custom behavior for each case, and in the end you have it available in a column

neon leaf
#

hmm

dry frost
#

who have template for terms web

lyric mountain
#

terms web?

pearl trail
#

probably the terms of service etc

outer crater
#

use /styles.css and /test.js

pearl trail
#

whoa

outer crater
#

css god has arrived

outer crater
#

please if anyone can help me with this

quartz kindle
#

it asks me for github login lol

deft wolf
#

He actually added subtitles to the video instead of writing what he meant in the message MegaThonk

outer crater
outer crater
empty raft
#

yo
would anyone here make a script into a bot?

outer crater
#

no it should say Error: failed to load

#

i just want css to be fixed šŸ˜­šŸ™

lyric mountain
#

all bots are scripts

earnest phoenix
#

but not all scripts are bots

pearl trail
#

so like this script into a bot

earnest phoenix
#

yes

quartz kindle
#

i prefer the batman movie written by AI

#

joker gave batman a gift, inside was a coupon for new parents but its expired
this is a joker joke

raven nexus
#

anyone use mongodb here

node:events:496
      throw er; // Unhandled 'error' event
      ^
ValidationError: OnlineTime validation failed: channelId: Path `channelId` is required.
    at Document.invalidate (/home/container/node_modules/mongoose/lib/document.js:3318:32)
    at /home/container/node_modules/mongoose/lib/document.js:3079:17
    at /home/container/node_modules/mongoose/lib/schemaType.js:1388:9
    at process.processTicksAndRejections (node:internal/process/task_queues:85:11)
Emitted 'error' event on Client instance at:
    at emitUnhandledRejectionOrErr (node:events:401:10)
    at process.processTicksAndRejections (node:internal/process/task_queues:92:21) {
  errors: {
    channelId: ValidatorError: Path `channelId` is required.
        at validate (/home/container/node_modules/mongoose/lib/schemaType.js:1385:13)
        at SchemaType.doValidate (/home/container/node_modules/mongoose/lib/schemaType.js:1369:7)
        at /home/container/node_modules/mongoose/lib/document.js:3071:18
        at process.processTicksAndRejections (node:internal/process/task_queues:85:11) {
      properties: {
        validator: [Function (anonymous)],
        message: 'Path `channelId` is required.',
        type: 'required',
        path: 'channelId',
        fullPath: undefined,
        value: undefined
      },
      kind: 'required',
      path: 'channelId',
      value: undefined,
      reason: undefined,
      [Symbol(mongoose#validatorError)]: true
    }
  },
  _message: 'OnlineTime validation failed'
}```

how could i fix this?
wheat mesa
#

channelId was null/undefined when you gave it to mongo and your schema requires it to be present

lyric mountain
#

seeing the code would help

raven nexus
#
const mongoose = require('mongoose');

const onlineTimeSchema = new mongoose.Schema({
  userId: {
    type: String,
    required: true,
  },
  guildId: {
    type: String,
    required: true,
  },
  channelId: {
    type: String,
    required: true,
  },
  joinedAt: {
    type: Date,
    required: true,
  },
  totalOnlineTime: {
    type: Number, // Online time in seconds
    default: 0,
  },
});

// Check if the model already exists
const OnlineTime = mongoose.models.OnlineTime || mongoose.model('OnlineTime', onlineTimeSchema);

module.exports = OnlineTime;
wheat mesa
#

You are not providing channelId here, but it is required in your schema

raven nexus
#

it should be process.env

wheat mesa
#

What?

#

Oh I think I understand what you’re saying

#

That’s not how process.env works, it doesn’t get automatically injected into your schema. You have to add it like anything else, the difference being you just use process.env.VARIABLE

raven nexus
#

oh

#

like this?

wheat mesa
#

Yes but no, the GUILD_ID was not the problem

#

The problem was your channel id

raven nexus
#

ohh

raven nexus
# wheat mesa The problem was your channel id
                const channel = client.channels.cache.get(CHANNEL_ID);
                if (!channel) {
                    console.error('Channel not found. Please check the channel ID.');
                    return;
                }

                await channel.send({ content: `<@${randomUserId}>`, embeds: [embed] });
                console.log(`Embed sent to channel ${channel.id} for user ${randomUser.username}.`);
            } catch (error) {
                console.error('Failed to update user coins or send message:', error);
            }
                }```
#

what i should change to

wheat mesa
#

Did you write this code

#

I don’t want this to come off as hostile or anything but you should really learn the language before making a discord bot, it can be very difficult if you don’t know it

raven nexus
#

but this mongo

#

is bug

#

i have been coding since v12

wheat mesa
#

Yeah it’s not a mongo bug. You are not giving the schema a value it requires

#

I took a screenshot of the exact lines where the problem is, take a look at it more carefully before just asking for the code :p

daring cove
#

can bots be added to this server?

deft wolf
#

Only if they are selected by the mods as worth showing afaik

#

Top.gg has a "program" called Staff Picks and every few months they select bots from their website that deserve recognition and they are probably also added here

wheat mesa
#

I’m stumped by a bug at work rn

#

Like the best explanation I have is that my object is getting hit by a cosmic ray every single time I try to call a certain method

#

Wtf

sharp geyser
#

How unlucky would that be

daring cove
sharp geyser
#

You don't really apply for it from what I recall

#

They choose bots on the website that they think are worth noting.

#

As to the actual process its unknown to us

daring cove
#

okay

#

thank

#

you

raven nexus
#

not channel id

deft wolf
#

Your schema requires a channel_id field and they sent you a screenshot that even though this field is required, you do not provide it when creating the document

bitter granite
#

does anyone know how to connect mysql to java?