#development

1 messages · Page 2034 of 1

quartz kindle
#

like many other email clients

marble juniper
#

Is this a valid sql statement?

DELETE FROM guilds WHERE EXISTS (SELECT * FROM guilds WHERE id = $1)
#

$1 is obviously replaced with a real value

quartz kindle
#

yes, but kinda redundant

#

DELETE FROM guilds WHERE id = $1 would do the same thing

marble juniper
#

Ok

split hazel
#

quite complicated but i can give it a try

#

other than scamming

#

anyways i want to actually fix my databases TCP

#

so theres no set message length

#

im thinking make a buffer, check the message length and if it doesnt match the actual length, store it in some variable and wait

#

of course setting the limit to something generous to not run out of memory

#

like 100mb maybe

#

mysql's packet limit is 1gb

#

but for incoming packets from the database there wont be a limit

#

but by default there will be a limit of rows returned

#

if someone decides to request every record and theres a million of them, i hope you have enough time and memory

#

well same applies to the database tbh

pine nova
split hazel
#

that is just cringe

pine nova
#

fr

split hazel
#

topgg mfs dying because someone made a rickroll joke

pine nova
quartz kindle
boreal iron
#

how do actually change the prefered guild locale (for testing reasons)?

quartz kindle
#

imagine you're waiting for a 200 byte message, but you get in 3 tcp frames:

on first frame:
start = rope = {
  size: a
  ptr: aaa
  next: null
}

on second frame:
rope = rope.next = {
  size: b,
  ptr: bbb,
  next: null
}

on third frame:
rope = rope.next = {
  size: c,
  ptr: ccc,
  next: null
}
#

final structure for the start variable would be ```js
{
size: a
ptr: aaa
next: {
size: b,
ptr: bbb,
next: {
size: c,
ptr: ccc,
next: null
}
}
}

#

on each frame you follow the next chain and count the sizes, until the combined size surpasses the expected message size (provided in a header in the first frame)

#

if the size surpasses, then you follow the chain again to assemble the buffer pointers

#

and then emit the final combined buffer, and reassing the excess bytes back to the first element

#

this is basically what node.js does in its tcp stream

#

this way you dont need to preallocate a massive buffer to account for all possible message sizes

split hazel
#

ima just malloc a base buffer size(e.g. 1mb) then check if all data has arrived (check for null character at the end of the buffer size) if not maybe make a linked array and store the buffer pointers in it then at the end assemble them, or just concat them immediately (maybe using realloc)

#

the obvious problem is how big of a contiguous block can i allocate with malloc

#

apparently its compiler and OS dependent

quartz kindle
#

1mb should be more than fine

split hazel
#

yeah

quartz kindle
#

how many bytes are you using for the length header?

split hazel
#

for now its only 2 but i can extend that to 4

#

no biggie

#

or even 8

#

but i dont need that much

quartz kindle
#

idk if its possible in c++, but in node its possible to receive tcp frames of 0 size, or 1 size, or anything weird like that

split hazel
#

it gets a bit complicated

#

the receive function takes in a max size, if a packet exceeds that size the next receive call will give you the other part of the packet

#

but thats per packet, it doesnt take into account split packets

wheat mesa
#

Just make incredibly unsafe macros to outsmart the compiler 😉

quartz kindle
#

i would do something like this (pseudocode)

buffer = <1mb buffer here>
bytesWritten = 0
tcp.on("message", data => {
  if(bytesWritten + data.length > buffer size) { realloc/extend buffer }
  buffer.write(bytesWritten, data)
  bytesWritten += data.length
  if(bytesWritten < 4) { return } // return if buffer not big enough to get our header
  header = buffer.readUint32(0)
  if(bytesWritten < header) { return } // return if buffer not big enough to contain our data
  ourdata = buffer.slice(0, header); // copy data from buffer
  buffer.write(0, buffer.slice(header)) // write excess bytes to the beginning for next messages
  bytesWritten = bytesWritten - header; // write excess bytes to the beginning for next messages
  emit(ourdata)
})
split hazel
#

c++ has no events silly

#

(jk)

quartz kindle
#

this is not the most efficient solution, because it involves copying buffers

#

but its the easiest solution

#

if you want max performance, you need to implement a zero-copy solution

#

which is a bit more complicated

split hazel
#

i think i know how i can kind of achieve that

#

i can always extend the buffer with realloc

#

how it does that does not concern me but the important thing is it works

quartz kindle
#

it can be done with the rope method i mentioned before

split hazel
#

why cant tcp just be normal and let you decide if you want to split packets or not:(

quartz kindle
#

because it cant lul

#

tcp has to follow the hardware transmission units

split hazel
#

honestly it'd be easier to just use a library that does this for you

#

they would probably do a better job anyways

quartz kindle
#

lel

#

i did it on tiny-discord, well kinda because node did half of it for me

split hazel
#

at the end

#

the json parser i use has to have the entire string at hand

#

cant have it in parts sadly

#

otherwise that would make it so much easier

#

i might ask some c++ experts to see what they think

quartz kindle
#

the rope method doesnt require copying to a temporary buffer

#

it stores the pointers to the original buffers provided by the tcp

#

can you create a buffer composed by multiple pointers in cpp?

split hazel
#

well here you have to make your own buffer and point to it

split hazel
#

unless they have some std function for it

#

but then again you cant make a buffer composed of the size of a packet

#

you have to set a strict size for it

#

so if you want a buffer to fit that packet size you either have to shrink it (with realloc) or copy

#

but then what realloc does to achieve that is implementation details

#

it may or may not copy

#

though that doesnt really matter considering you can place a null terminator at the end

#

so you can assemble the entire string at the end

quartz kindle
#

im reading some stuff on zero copy, it seems they use mmap for that

split hazel
#

huh?

quartz kindle
#

the rope method does not require copying the tcp packets, but it does do a copy at the end when the final message is assembled

#

basically when the entire message is available, a new buffer is created for that message, and the parts are written to it

split hazel
#

yeah i can do that with a linked list no biggie

#

allocate size of message, write message, push pointer to linked list then assemble the string at the end

#

and continue until everything has been read

#

when it reaches the size of the string, it saves the position in the buffer and the pointer currently being read, processes the current string and continues with the next

#

it is a lot of copying though

#

because we have the size of the entire packet in the header, you can allocate the exact amount of memory needed for it

#

mapping separate buffers to appear contiguous would be very good though

#

oh wait

#

i thought of a million dollar idea

#

lets split that real quick

#
  • make the receive function take in 4 bytes (the header size) at first
#
  • allocate a buffer of that exact size and store the pointer in a variable
#
  • make the receive function take in the "remaining" size of the data with the pointer pointing to the next position in the buffer we allocated previously
#
  • subtract the remaining size by the amount of bytes written, if it is zero, send off the buffer for processing, if not repeat previous step
#
  • at last the last step, free!
#

@quartz kindle thoughts?

#

I AM A GENIUS

#

not a single copy in sight

quartz kindle
#

yeah

#

you just need to also handle excess bytes

split hazel
#

no need

#

we have the max size parameter

#

we only take in what we need

#

i will focus on detecting incorrectly or maliciously crafted packets later

fickle arch
#

tried to install better-sqlite3 by adding it to package.json, deleting the node_modules and it still gave me an error, any clue how to fix this ?
the regular way have the same error.

vivid fulcrum
#

what node version are you running

fickle arch
#

v18.1.0

vivid fulcrum
#

is node-gyp installed?

fickle arch
simple stump
#

This is a bit vague, but how can I prevent an user from sending too many requests? I have a few situations I need to fix for a website I’m making using ExpressJS. One is creating accounts/logging in where the user data is stored in a SQLite database. However, the user can slow down the server if they create too many accounts at once, but I’m not sure how I can prevent this. Another is through the search bar, where I send HTTP requests to an API and to another website. I’m planning on only having the user be able to search 5 times per minute (as a start), but I don’t know how to track that if they don’t have an account (staying logged in is also a problem I’m having since I don’t know how to track that).

fickle arch
#

limit request per user ?

split hazel
#

honestly its quite a tricky topic

#

the easiest way is to do it via a users ip

#

but if an attacker was motivated enough they can perform a DDOS where IPs dont really matter

solemn latch
#

you're really going to want to have logging in & sessions sorted out before moving forward with ratelimits(for ratelimiting per user)

#

express also has a few middleware options for rate limits per ip.
For account creation you'd ideally have a captcha used along with ratelimits per ip..

split hazel
#

yeah a captcha

#

forgot about that

#

a captcha is a must for ratelimiting registrations

#

logins too

#

after that you can rate limit per account

#

@quartz kindle to make you feel better

#

for tracking the buffer position im using a pointer to the position rather than an index

#

because indexes use multiplication on the buffer to get to the destination

#

and multiplications are slow:)

feral aspen
#

Well... we're going to have fun.

stable eagle
#

what, so fast?

feral aspen
split hazel
boreal iron
#

Does anybody have a "smart" idea how to parse the JSON and replace the double quotes of the value direct_message (of the key errors) by ` to turn it into a template string

{
    "errors":
    {
        "direct_message": "**Sorry** ${somevar}",
    }
}
radiant kraken
split hazel
#

lmao

earnest phoenix
cinder patio
#

What's the goal here though?

boreal iron
#

nvm need to do it differently anyways

cinder patio
#

so ${somevar} gets replaced with the variable's value?

#

you'll need to use eval

#

or Function

boreal iron
#

gonna take my php language parser as example

boreal iron
cinder patio
#

You can make up your own templating engine which is simpler to parse

#

and parse the strings

boreal iron
#

yeah I do

cinder patio
#

that's your safest option

boreal iron
#

im gonna replace {{somevar}} by the arguments I pass

cinder patio
#

yeah that works

#

I'd go with something like @somevar cause it's simpler

#

Easier to escape as well

boreal iron
#

errr nope, that could get in conflict which strings containing @

#

double brackets are actually good to go in JS and PHP

cinder patio
#

you can easily detect the escaping character before it though

#

@

#

\@

boreal iron
#

yeah ik, I just prefer {{..}}

#

to be consistent in my projects, you know

#

damn can't test things atm

#

Is that the correct syntax for optional chaining for dynamic keys?

#

object[key]?.[val]

cinder patio
#

yes

boreal iron
#

alr

lament rock
#

Optional chaining for methods is cursed

#

value?.(args)

boreal iron
#

wdym by is cursed?

boreal iron
#
    language(localization, group, key, placeholder = false)
    {
        if(!localization || !group || !key) return;
        
        if(localization.includes("en-")) localization = "en";
        
        const language = (this.client.localizations.has(localization)) ? this.client.localizations.get(localization) : ((this.client.localizations.has(locale)) ? this.client.localizations.get(locale) : null);
        
        if(language)
        {
            if(language[group]?.[key])
            {
                let string = language[group][key];
                
                if(Array.isArray(placeholder))
                {
                    const match = string.match(/{{.+?}}/g);
                    
                    if(match)
                    {
                        for(let i = 0; i < match.length; i++)
                        {
                            if(placeholder[i]) string = (placeholder[i].length > 0) ? string.replace(match[i], placeholder[i].trim()) : string.replace(match[i], match[i].slice(2, -2));
                        }
                    }
                }
                
                if(string) return string.replaceAll("{{", "").replaceAll("}}", "");
            }
        }
        
        return this.utils.log("warn", `Missing language record for '${group}->${key}'`);
    }
#

could probably be compressed a little bit more but who cares

#

which allows me to call the method and pass my args where ever my vars are in the right scope

sharp geyser
#

what da fuq

#

Isn't this just doing what i18n does?

boreal iron
#

idk

#

I don't like libs when I can do stuff my own

sharp geyser
#

True, the code looks a bit weird to me since it is scrunched up :p

boreal iron
#

also I'm replacing placeholders in my language files by vars where I need 'em

copper cradle
#

Ah yes, reinventing the wheel. Classic js

cinder patio
#

that indentation is cursed

boreal iron
#

For example:

// lang json file
{
    "errors":
    {
        "direct_message": "test {{123}} {{afas}} df"
    }
}

const wow = 345;

app.language("en", "errors", "direct_message", [wow])

// test 345 afas df
boreal iron
#

I'm just using TAB not spaces

sharp geyser
#

I would actually prefer that over i18n ngl

#

It is way easier to implement

cinder patio
#

I guess not the indentation, just the style... Opening curly brackets on new line 🤮

sharp geyser
#

I assume whatever is in the {{}} will be replaced?

boreal iron
#

yes

sharp geyser
#

what about that [wow] thing?

boreal iron
#

the array does only replace the first placeholder of {{ }} as it has only 1 item

sharp geyser
#

Oh right, so that is what actually gets placed in there and the other 3 are to tell it where to look

#

gotcha

boreal iron
#

When I pass more items like [wow, 456] the result would be test 345 456 df

#

I can even pass more items than placeholders exist

#

that wouldn't do anything

sharp geyser
#

What happens if you nest inside direct_message with another object?

#

This is just a general example of what happens if you ever do need to nest

boreal iron
#

I don't need that over here, but my PHP equivalent build can lookup one structure deeper

sharp geyser
#

I see

boreal iron
#

For this example I don't need nesting as I already have the key errors and the value direct_message aka. 2nd key

#

In PHP a much deeper nesting wouldn't make sense, too

#

because I'm using an INI structure as language file

#

for example:

#
[static]
time_years = "year{{s}}"
time_months = "month{{s}}"
time_weeks = "week{{s}}"
time_days = "day{{s}}"
time_hours = "hour{{s}}"
time_minutes = "minute{{s}}"
time_seconds = "second{{s}}"
time_few_seconds = "a few seconds"

[footer]
link_tos = "Terms of Service"
link_privacy = "Privacy Policy"
#

while in that case when passing an empty item in my replacement array time_years would just be year and not years

#

that's very simply but effient

#

and when not passing any item in my array, then year{{s}} would get years

#

if(string) return string.replaceAll("{{", "").replaceAll("}}", "");

#

which allows me to replace any part of the final language string by a different string or for example by a var I pass

#

So I'm just loading my (JSON) language files into a map and access it whenever I need and replace my placeholder if I have to

#

can't actually think of any easier way to do it

boreal iron
proven lantern
#

i like this part

#

why not optional chain it twice?

cinder patio
#

He needs language again after that

proven lantern
#

language?.[group]?.[key]

proven lantern
#

i use the i18next lib, but only have American english

copper cradle
#

then what's the point

proven lantern
#

pluralization stuff

copper cradle
#

you could make a simple template for that

proven lantern
#

i also plan to support more languages

copper cradle
#

then that's ok

proven lantern
#

maybe european english. i'll add random u's to words

#

legacy english should be supported

cinder patio
#

simish too

proven lantern
#

latin is next

copper cradle
#

also old himalayan

proven lantern
#

sim cards! not the sims 3. oof

boreal iron
#

if not it will still be undefined

#

and the statement would fail

proven lantern
boreal iron
#

ah, that's what u mean

proven lantern
#

i mean things and stuff

boreal iron
#

actually not a bad idea

proven lantern
#

it's a miracle

boreal iron
#

huh?

proven lantern
#

it's a miracle that i didnt have a bad idea

boreal iron
#

regarding our i8n lib

#

the main feature I need is to replace placeholders

proven lantern
#

eval random strings. what could go wrong?
eval("`${alert('hello')}`")

#

edge doesn't want to protect me, but chrome does

split hazel
proven lantern
# boreal iron the main feature I need is to replace placeholders

you can use this if you want to make life easier ```js
const i18next = require('i18next');

const fallbackLng = "en-US"
const resources = {
[fallbackLng]: {
translation: require('./en-US/translation.json')
}
}

const initializeLocalization = async (locale) => {
await i18next.init({fallbackLng, resources});
return i18next.getFixedT(locale);
}
module.exports = initializeLocalization;

boreal iron
#

nah... don't wanna use libs

sharp geyser
#

How does supporting multiple translations even work in i18next

boreal iron
#

my selfmade thing actually works perfect and is damn effient

proven lantern
sharp geyser
#

Mmm

boreal iron
proven lantern
# boreal iron

you live dangerously. if you returned that object on a new line it would fail

#
return
{
  color: ...
  description: ...
};```
boreal iron
#

wut

#

returning it on a new line, huh?

proven lantern
#
function x () {
    return
    {
        hello: "world"
    }
}```
#

what do you think this code does?

austere surge
#

nothing

boreal iron
#

I'm not returning an object but a string

#

the language method can't return an object

proven lantern
boreal iron
#

well I wouldn't open that bracket in a new line

sharp geyser
#

This is when you make your own superset of js that supports line breaking

#

:^)

proven lantern
#

it's a bad habit in js

boreal iron
#

that's the issue when you don't need to put a ; to end your line

proven lantern
#

yeah, ; should be required

boreal iron
#

but I still don't get why I'm living dangerously

#

just because I generally open the brackets in a new line?

proven lantern
#

correct

#
let x = 
{
  live: "dangerously"
}
;```
boreal iron
#

I'm only doing it, when ever it doesn't fuck up the syntax, don't worry

sharp geyser
#

Making anonymous functions in js is a good reason why semi should be required

boreal iron
#

even in JavaScript I add ; to any line

proven lantern
#

fixed

boreal iron
#

to prevent that sort of bullshit to happen

proven lantern
#

i put my ; on a new line too

sharp geyser
#

I do it as much as possible but I just sometimes forget and let prettier do it for me

boreal iron
#

even if it isn't required

#

well npp doesn't do shit for me

#

once it belongs to your routines, shit can't happen anymore

proven lantern
#

notepad++. i just figured out what npp is

boreal iron
proven lantern
#

very nice

boreal iron
proven lantern
#

everything should be a oneliner

boreal iron
#

nah

#

I prefer human readability

proven lantern
#

well it can be multiline, but only one assignment is allowed

boreal iron
#

I could get rid of hundrets of lines if I optimize one liners but I don't like to

#

as I said earlier

#

well it's all about preferences

#

so... just because I'm not as lazy as you to add ; I can live my "weird" style

proven lantern
#

scala has similar problems because of the lookahead + auto inserted ;

wheat mesa
#

tbh I think js should require semicolons like every standard c-like lang does

#

it saves a lot of headaches

#

to have strictly defined behavior

proven lantern
#

yep, i'd change the way i write js if they did that

#

actually i probably wouldn't

#

this looks betterjs return { hello: "world" }

boreal iron
#

this looks better

#

pfff

#

go on

proven lantern
#

well this looks best

return { hello: "world" }
#

then do ctrl+shift+l

split hazel
#

no

#
return { hello: "world" };
#

does

boreal iron
#

awww speedicus saves the day

sharp geyser
earnest phoenix
#

You're trying to make a request with the client such as fetching a user before the client is even logged in

lament rock
#

didn't supply a token it seems

#

or that

split hazel
#

for discord.js unfortunately yes

#

you might have some luck trying to login then logout

#

i had the same issue but forgot how i solved it

#

hmm

#
#

oh last update 4 years ago

#

nevermind

#

and deprecated

earnest phoenix
split hazel
#

i think i know how you can do that

#

eris allows you to perform api calls without logging in

boreal iron
#

I mean if you dont wanna use simple IPC for example to pass the vote data to your logged in client then why don't you init a new client without any intents and cache?

#

even if a second connection doesn't really make sense tho

earnest phoenix
#

I don't think you need to be logged in, seems like they're just missing the token completely

boreal iron
#

ahh nvm then

split hazel
#

@earnest phoenix do you happen to know if node has a TCP interface similar to C? i need to receive a max amount of bytes, each time being variable and the event API nodejs has just fires the most bytes it can at you
I had to make an ugly solution with a main buffer being allocated with a set size and when bytes arrive, slice the buffer and copy over the contents to a certain position in the buffer

boreal iron
#

would have been strange if a login would be required just to send an request to the api

#

but djs is strange as we know

split hazel
#

funnily enough in this case its easier to work with TCP in C than nodejs

#

if you didnt know the C way of receiving TCP bytes is by
recv(socket_id, destination_buffer_pointer, max_bytes)

sharp geyser
#

I don't think my lib requires to be logged in to send rest api requests either Tho if someone would like to fully test that go for it :^)

split hazel
#

blocking if that isnt obvious

earnest phoenix
split hazel
#

yeah receiving data still requires you to use events

#

hm

#

i guess I can implement this myself

#

but eh

#

i feel that'll impact performance even more

#

because tcp is a stream API when you send a packet, at the receiving end it can be grouped with another packet or split into two

#

which makes the stream approach of it terrible to work with

sharp geyser
#

Should I make a Base Channel class and then have classes like TextChannel, DMChannel, etc extend it ? It seems like that would be the most logical as a dm channel will have different properties than a text channel or even a category channel

proven lantern
# split hazel no

ctrl+shift+l added semicolons for me. 3 key strokes is easier than pressing ;

split hazel
proven lantern
#

i use ken rename

earnest phoenix
split hazel
#

yeah not really just wondering

#

mainly not happy about the part that you have to copy from another buffer to another when you can directly write to the empty portion of the buffer

#

but I get thats not really easily implementable because js is a memory safe language

sharp geyser
#

What would be the most logical way to attach the guild the channel belongs to right onto the channel glass? I was thinking of getting it from the cache using the guildid the channel receives but that doesn't make sense as the guild could also not be cached

#

I was also thinking that to make a channel you must pass the guild with the channel class constructor but that would be rather hard to do as well for events where you either create a channel or update it and then you'd have no access to the guild there either

split hazel
#

its not much overhead and saves you a lot of headaches

sharp geyser
#

I am already caching every guild

#

I am trying to figure out how to get the guild the channel belongs to

#

and attach it to the channel class

split hazel
#

just attach the guild class to the channel?

#

if every guild is cached that shouldnt be an issue

sharp geyser
#

Mmm, should I even bother caching a channel on channel create?

#

If I don't have to bother I very well could easily do that

split hazel
#

i would let the user decide

#

maybe let the user set a channel cache limit

#

if it reaches that limit it will start overwriting older channels

#

on every action that involves a channel you should cache the channel discord sends you

sharp geyser
#

Hmmm that seems like a good idea but how should I tell if the channel is an older channel? If it is later in the cache or should I attach a timestamp of when it was added?

split hazel
#

good question

#

if you dont want to do it through time and instead through order:

sharp geyser
#

Also, how should I update the channel in the cache if it already exists, as the properties of the channel could change

split hazel
#

you should remove the first element of the map (assuming you'll use that for storage) since they're ordered and just set the new channel

#

be warned anything that holds the channel that isnt the map and is long-lived will result in a memory leak when you try remove them

sharp geyser
#

I understand what a memory leak is but not what you mean

split hazel
#

lets say you have a map of channels which holds a class to cached channels

#

then you decide to cache messages which also hold the channel class

#

if you remove the channel from the map the channel wont be released from memory since the message you cached still exists and holds it

#

you'd also have to remove the message to release it from memory

#

just a warning

sharp geyser
#

So should I also delete message as well?

split hazel
#

too much overhead

#

that was just an example but you shouldnt worry about that

sharp geyser
#

Mmm, I see

split hazel
#

just make sure your message cache is low

sharp geyser
#

ye

split hazel
#

a few excess channels wont hurt

sharp geyser
#

I plan on setting the limit for a lot of things by default

#

and then let them decide if they wanna cache more or less

#

But then I still have the question of how I should retrieve the guild the channel belongs to to attach it to the channel class I tried retrieving the guild from cache with the guild id you get from the channel object but it just returns undefined even tho the guild does exist in the cache

#

You say just attach the guild to it, I can surely do that when I cache the channels of the guild in the guild create event but not in say channel create or update

split hazel
sharp geyser
#

From what i've seen no

#

just the guild id

split hazel
#

ah probably to limit bandwidth

sharp geyser
#
{
  type: 0,
  topic: null,
  rate_limit_per_user: 0,
  position: 2,
  permission_overwrites: [],
  parent_id: '957867801119449110',
  nsfw: false,
  name: 'aha funny word',
  last_message_id: null,
  id: '972974453367652362',
  hashes: {
    version: 1,
    roles: { hash: 'kyCmkswUy88' },
    metadata: { hash: '7KBK+FxBI+w' },
    channels: { hash: 'oVyKHFAhsMU' }
  },
  guild_id: '957867801119449109',
  guild_hashes: {
    version: 1,
    roles: { hash: 'kyCmkswUy88' },
    metadata: { hash: '7KBK+FxBI+w' },
    channels: { hash: 'oVyKHFAhsMU' }
  },
  flags: 0
}
#

all you get back

split hazel
#

you must be doing something wrong when retrieving the guild form the cache

#

code?

sharp geyser
#
import { ChannelData, MessageCreateData, PermissionOverwrites } from '../../../util';
import { BaseClient } from '../../BaseClient';
import { ChannelType, RESTPostAPIGuildChannelJSONBody, RESTPostAPIGuildChannelResult } from 'discord-api-types/v9';
import { Message } from './Message';
import { Guild } from './Guild';

export class Channel {
    public client: BaseClient;
    public id: string;
    public type: ChannelType;
    public guildId: string;
    public position?: number | null;
    public permissionOverwrites?: Array<PermissionOverwrites> = [];
    public name: string;
    public topic: string;
    public parentId: string;
    public guild: Guild;
    public nsfw: boolean;
    constructor(client: BaseClient, data: ChannelData) {
        this.client = client;
        this.id = data.id;
        this.type = data.type;
        this.guildId = data.guild_id;
        this.position = data.position;
        this.permissionOverwrites = data.permission_overwrites;
        this.name = data.name;
        this.topic = data.topic;
        this.parentId = data.parent;
        this.nsfw = data.nsfw;
        this.guild = this.client.guilds.get(this.guildId)
    }

    public async send(data: MessageCreateData): Promise<Message> {
        return await this.client.rest.post(`/channels/${this.id}/messages`, data);
    }

    public async create(
        guildId: string,
        data: RESTPostAPIGuildChannelJSONBody,
    ): Promise<RESTPostAPIGuildChannelResult> {
        return await this.client.rest.post(`/guilds/${guildId}/channels`, data);
    }
}
split hazel
#

have you tried logging the guild id?

sharp geyser
#

yes I get back the guild id as expected

#

but this.client.guilds.get(this.guildId) is undefined

split hazel
#

have you tried fetching the guild with the ID hard coded?

#

are you sure its even cached? can you print your whole guild cache

sharp geyser
#

Printing the entire guild cache returns the base store with the guild in it, and fetching it with a hard coded id works fine and returns the guild

#

response

split hazel
#

im stumped then you have to be doing something wrong though

#

hard to debug when you arent in front of the code haha

sharp geyser
#

I can push to my repo and you can test whenever you have time

#

if you want

split hazel
#

sure

#

i can have a look at it there

sharp geyser
#

pushed

split hazel
#

where are you instantiating the channel?

sharp geyser
#

In the webhook shard, on guild create and channel create

#

I make a new channel to convert the data returned to my class's data so I can keep the methods with the data

split hazel
#

cant see it at first glance so i'll just clone and run it

sharp geyser
#

Alrighty ty in advance <3

split hazel
#

windows :~

#

wsl time

sharp geyser
#

lol

split hazel
#

oh dear i dont have a typescript compiler installed 💀

#

should be fine tho

sharp geyser
#

typescript is one of the deps for it so it should have it locally installed in the project

split hazel
#

what is the config layout?

#

its not included in the repo

sharp geyser
#

it is just a config file with an export of TOKEN

split hazel
#

always a good start

sharp geyser
#

Yea no idea what happened there

lyric mountain
# split hazel windows :~

windows: git is not a recognized cmdlet, go fuckin google how to solve this
linux: git is not recognized as a command, perhaps you could try installing with apt install git

sharp geyser
#

I thought you were being rude then realized you are mocking windows

#

:^)

copper cradle
#

That's not a windows thing eiter

#

That's a shell thing

#

I'm seriously considering installing wsl

lyric mountain
split hazel
#

i see the problem

#

im so kind i'll fix it for you

sharp geyser
#

lmao thank you :)

split hazel
sharp geyser
split hazel
#

sure

#

my personal preference is ? :

sharp geyser
#

Either way works tbh

#

I do like the look of ?? tho

split hazel
#

might be just you

#

imposter syndrome

sharp geyser
#

Mmm well doesn't really matter as long as it works :p

#

What should I work on next 🤔

split hazel
#

more useful connection errors

#

a few times my connections timed out and i got a basic "request failed"

sharp geyser
#

Mmmm

sharp geyser
#

So i was looking at discord.js lib and they do something rather confusing

#

They have a Channel class right which is just a basic channel not really a text, dm or category, etc. Then they have GuildChannel which extends that, then BaseGuildTextChannel which extends GuildChannel then TextChannel which extends BaseGuildTextChannel. What is the point of all this extension?

lyric mountain
#

inheritance

sharp geyser
#

Well yes but could they not have done it simpler?

lyric mountain
#

let's say all channels have id, name, permissions, category, etc

#

instead of repeating that same code in all channels, u just make a superclass with common properties

#

ur not really supposed to use the superclasses themselves

sharp geyser
#

Yea i know this much, but why the whole long winded extension

#

Why not just have a Super class then extend that super class for the things you need

#

Like
Channel (Super Class) -> GuildChannel -> TextChannel

lyric mountain
#

because not all guildchannels are textchannels

#

and not all channels are guild channels

sharp geyser
#

Yes, which is why GuildChannel is a class in its own where all guild related channels extend it

lyric mountain
#

ah, u mean there's a class between those two?

sharp geyser
#

Yes Channel is the super class, GuildChannel is the class that extends it and has basic properties a guild channel should have and TextChannel has the properties of what a guild channel should have + text channel properties

lyric mountain
#

that's how it's supposed to be

#

in jda it's that way

sharp geyser
#

Yes, but they add a fuck ton of what seems to be useless stuff

#

I am sure it has its uses but it seems to be overly done when it could be much simpler

lyric mountain
#

maybe the Base classes aren't classes but interfaces

sharp geyser
#

Looking at the difference between BaseGuildTextChannel and TextChannel seem to be nothing different despite a few things you could probably add to TextChannel in itself

lyric mountain
#

well then idk, base doesn't really make sense tbh

sharp geyser
#

They seem to apply a interface properties to it using applyToClass or smth

#

So it extends GuildChannel and implements TextBasedChannel

lyric mountain
#

in jda it's like ```
┌ PrivateChannel
Channel ┤
└ GuildChannel ┐
├ TextChannel
├ VoiceChannel
├ ...

sharp geyser
#

I don't really see the point in having a BaseGuildTextChannel class tho it seems like they took an unneeded extra step

lyric mountain
#

is that what u mean it should be?

sharp geyser
#

Yea, that is what I was planning to do

#

But I wondered why djs did it so weirdly

#

Wait what djs uses something from sapphire

#

:^)

lyric mountain
#

sapphire?

sharp geyser
#

the djs command framework

#

used to be klasa but the devs had falling out so the ones left made sapphire

quartz kindle
#

so they needed a common class for text channels that are not text channels

sharp geyser
#

Mmm, I guess that makes sense yea

#

I still feel there is a better way to do it tho but 🤷‍♀️

#

they are the pros

lyric mountain
#

In jda it just extends textchannel mmulu

quartz kindle
#

also soon there will voice text channels

lyric mountain
#

What

#

Why?

sharp geyser
#

I mean tbh isn't a thread channel just a special text channel?

dry imp
quartz kindle
#

discord is adding text to voice

#

like a stream thing

#

twitch etc

dry imp
#

its better than to comment about the stream on a irrelevant channel

lyric mountain
#

D.py devs going crazy for that update

quartz kindle
#

djs literally broke

#

when it started receiving message events in voice channels

lyric mountain
#

It already started?

sharp geyser
#

v10 I think is a part of that

solemn latch
#

Yeah

#

It's kind of an annoying feature for mods

lyric mountain
#

And they still didn't finish the join agreement part

#

The screen that appears when u join a server, it has many "To be added" features

quartz kindle
#

i had to upate djsl a few times to fix it

fringe pendant
#

Quick question: is server count setting via the API broken right now? Just noticed my bot hasn't updated in a while but as far as I can tell the API calls are going through

boreal iron
#

takes a while to update in your browser since the page is cached

fringe pendant
#

It's like 50 servers behind though, so I'm guessing something else is wrong then. I'll look into it thanks

boreal iron
#

well which duration since the last update are we speaking about?

fringe pendant
#

Estimate would be about a month

boreal iron
#

ow

#

is the count in a different browser the same?

lyric mountain
#

Mine is working fine, did u see if ur not getting any http error?

fringe pendant
#

I'm gonna try to set it manually and see if it updates, and if it does then I guess the library I'm using might have an issue

lyric mountain
#

What lib is it?

fringe pendant
#

It's the java library, version 2.0.1

#

java-sdk

boreal iron
#

I remember a few reports recently about the java lib iirc

lyric mountain
#

I use the java lib

boreal iron
#

might be an issue with it

fringe pendant
#

I tried updating to 2.1.1 but for some reason I can't seem to get it off maven

#

doesn't exist

lyric mountain
#

But tbh, I'm quite sure I'll not be using it anymore on my reworked bot

#

Doing direct http requests is easy enough to remove the dependency

fringe pendant
#

yeah it updated via manual API call, so something broke in the bot seems like

lyric mountain
#

Also iirc, the java lib has some vulnerabilities (uses org.json) reported on maven central

fringe pendant
#

nice

#

alright guess I'll implement it myself as you suggested then, thanks for the help

lyric mountain
#

Btw, before you go, I recommend using apache http for doing the requests

#

And moshi to parse data into json

fringe pendant
#

Noted, although I literally just update server count and nothing else. So... not too much work being done

lyric mountain
#

org.json is a terrible lib (it was created as a proof-of-concept) to use anywhere

#

Mostly because it lacks any optimization

fringe pendant
#

I usually use OkHttp, not a fan of that either?

lyric mountain
#

That's for requests, not parsing data

fringe pendant
#

oh yeah sorry I misread

lyric mountain
#

It's fine too, I like apache's bcuz it's very flexible

#

And since it uses factory pattern, u can set default settings for every request

fringe pendant
#

Yeah true, I've used Apache before for other things but for whatever reason I started with OkH with this and never changed. Does enough for what I need

lyric mountain
#

Oh, btw, do u use log4j?

sharp geyser
#

I gained something but I lost another as well

fringe pendant
#

I don't use log4j no

sharp geyser
#

I managed to split the channels up according to their type so now the data is properly typed with the methods that are meant for that channel but the channels cache on the client is only storing one channel

lyric mountain
#

Oh ok, I was going to warn u not to use earlier versions

#

Due to infamous exploit

fringe pendant
#

yeah don't worry I'm aware of that lol

copper cradle
#

I'd maintain the go package but tbh I haven't seen anyone using go here

wheat mesa
#

So I find that I am once again going down the hole of writing a minecraft mod, does anyone know a good way to avoid global state? A lot of the features I need to support rely on settings provided by the user, and in previous mods I've done this with using a bundle of static variables, but I know it's a bad practice

lament rock
#

pretty sure the mod loader provides a way of r/w of a config file

#

would have to read your mod loader's docs

wheat mesa
#

docs??!! on forge??! impossible

#

I'm using 1.8.9 forge, there's basically no resources for it

#

Because they refuse to support anything older than like 1.12

lament rock
#

surprisingly, they actually made some docs for later versions

#

yeah then you might be shit out of luck unless you find a mod's source that does what you want to do

copper cradle
#

/j

lament rock
#

Unironically, forge needs more love in the performance departments like fabric gets

#

or one of the mod loaders just gives up on trying to update and have it be obsolete

#

or both

sharp geyser
#

@wheat mesa Make your own mod loader

#

:^)

boreal iron
#

Is there actually some sort of process environment vars in node which can be an array?

lament rock
#

env vars are all strings

boreal iron
#

Ok let's say I'm exporting this:

module.exports =
{
    name: "evil",
    description: "very evil shit",
    do(param1, param2, lang)
    {
        // do some evil shit
                lang.something...
    }
};
lyric mountain
#

Let's pretend u didn't use "do"

boreal iron
#

I'm getting my params in the do() method right from where I require the module and execute do()

#

let's say lang is another class or object I wanna use on the module's name

#

I don't actually wanna define lang as global var

#

And I can't import/require it from anywhere else

lyric mountain
#

Can't u just require it inside the scope?

boreal iron
#

hmm... I feel like the only option is to export lang as module itself

#

and import it over here

#

in my case lang is a method in class

lyric mountain
#

The entire concept concept of having to export stuff in js so it's discoverable in other files is weird to me

#

In java u just write the class and that's it

boreal iron
#

yeah I don't have that trouble in PHP, too

lyric mountain
#

If u don't want to import u just write the full path to the class

#

Js is the only lang I see this behavior

#

Maybe that's due to its browser origins

boreal iron
#

Importing something that is I'm already passing as argument is weird

lyric mountain
#

Oh wait what, I just noticed that's a param

#

That still requires importing?

boreal iron
#

well the example was stupid

#

lang actually is a class, let's call it app and lang is it's method

lyric mountain
#

That should've work, if it's passed as a param u shouldn't need to import the class

boreal iron
#
// some other file
class app
{
    language() ...
}

// some very other file
module.exports =
{
    name: "evil",
    description: "very evil shit",
    exec(param1, param2, app)
    {
        // do some evil shit
        app.language(...);
    }
};
#

wait

#

the class app get's exported

#

module.exports = app;

#

can't I actually export language as well?

#

with a second export like module.exports = app.language;

#

which I can then import in my very, very, very other module

lyric mountain
#

I mean, that's what I mean

#

U shouldn't need to import every single method in a class if ur passing an instance of it as an argument

boreal iron
#

YES I'M PASSING THE ENTIRE INSTANCE

#

BUT

#

I'm passing it to exec(param1, param2, app)

lyric mountain
#

Yes?

boreal iron
#

I wanna use it ouside that scope already

lyric mountain
#

U mean outside of exec?

boreal iron
#
module.exports =
{
    name: app.language(...),
    description: "very evil shit",
    exec(param1, param2, app)
    {
        // do some evil shit
        app.language(...);
    }
};
lyric mountain
#

Ah, that

boreal iron
#

yeah that's the issue

lyric mountain
#

Well, that's something I don't think any lang can achieve

#

Forward reference in this case

boreal iron
#

that's what I mean, I need to export that method separately

#

which I can then import in this module

#

to NOT import the entire class (again)

lyric mountain
#

U could, tho, make it a class instead of a (whatever that structure is called in js)

#

Then instantiate the class with an instance of app

#

And use it in constructor to build ur command

#

(assuming that's a command)

boreal iron
#

err nope, just was a neat example I could copy real quick

#

hmm js classes are weird

lyric mountain
#

Like new SomeExample(app)

#

Then use app however u want inside that class

boreal iron
#

importing the class isn't the issue tho

lyric mountain
#

I mean, in ur example it'd not work since you'll be getting a static method instead of a reference's

boreal iron
#

but I don't want to initiate it another time in my module (since the entire class is already available as argument)

lyric mountain
#

2 different contexts

boreal iron
#

yeah

lyric mountain
#

You either use a class so u can store the reference in a broader scope or don't forward-reference it

boreal iron
#

that's why I asked

#

how I can do that in JS

lyric mountain
#

U can also set a placeholder in name

boreal iron
#

huh

#

you're actually right, lol

lyric mountain
#

Like, idk if those fields are all final, but can't u do something like this.name = app.language(...)?

#

If anything, replace that value where u import it

boreal iron
#

i could check if the module name is a string or an object, when it's an object I could pass my language key and value

lyric mountain
#

Ye

boreal iron
#
module.exports =
{
    name: { group: "something", key: "something else" },
    description: "very evil shit",
    exec(param1, param2, app)
    {
        // do some evil shit
        app.language(...);
    }
};
lyric mountain
#

For my commands I set their names like cmd/some_command, then when printing the name I grab that entry from the locale files

boreal iron
#

damn I haven't thought about that actually

#

actually a good idea tho

#

never thought I would appreciate tips from a Java user, but nice one

lyric mountain
boreal iron
#

there you go, good girl, take a cookie 🍪

#

man... localization stuff is expensive

lyric mountain
#

How are u doing it?

quartz kindle
#

i gave up on localizing timezones in my api

boreal iron
#

lol

#

NOW YOU FUCKING ARRIVE

quartz kindle
#

the user can localize them themselves if they want, fuck it

boreal iron
#

lmao

quartz kindle
#

theres zero consistency

boreal iron
#

just do an autocomplete list of timezones he can pick one of

lyric mountain
quartz kindle
#

lmao

boreal iron
#

pretty simple

lyric mountain
#

No, i mean, are u using files + cache?

boreal iron
#

i'm importing the lang file, yeah

lyric mountain
#

Oh, no cache then

boreal iron
#

so it's in the cache until I reload it

#

or should I say memory

lyric mountain
#

Like, in my schema I get from the cache, if it's missing it loads the entry from the target locale file

#

So the cache auto-loads itseld basically, and keeps the entries cached for 30 mins before discarding it

boreal iron
#

I'm not letting the user pick a language etc.

lyric mountain
#

This way I don't have the whole file loaded, only the requested lines

boreal iron
#

I only wanna support the description_locales

lyric mountain
#

Still, don't load the entire file

#

What format are u using?

#

Don't say json

boreal iron
#

technically not, no but why should I care?

#

the import process happens once when the client being initiated

lyric mountain
boreal iron
#

we're just speaking about a few bytes of ram

#

or megabytes

#

wtf who cares about RAM in 2022

lyric mountain
#

Definitely megabytes

boreal iron
#

I can fucking assign up to 198GB to the VM if I want to

#

but yeah I know what u mean

#

not going for microptimizing here

#

a few mb of ram as base load doesn't matter for me, tbh

lyric mountain
#

Remember fixing i18n-related issues gets exponentially harder the longer a project is

boreal iron
#

that's why I'm using my own simple system I used to show earlier this day

#

which is also capable of replacing placeholder in my language string if I wanna replace something with a var for example

lyric mountain
#

I faced the i18n demon eye-to-eye, which is part of the reason I'm rewriting my entire bot

#

Every single visible string is going to be localized

#

Ngl it's easier when starting again, but my file already surpassed a hundred lines

quartz kindle
#

im never gonna localize my help command, fuck that

boreal iron
#

yeah I'm currently rewriting my bot, too, making anything more dynamicly to be able to reload basically the entire app while keeping alive the gateway conection

quartz kindle
#

it would be like writing a book

boreal iron
#

Yeah I made the accident to translate the entire API docs

#

starting at line 170 to 271

#

doesn't sound much, but is 2s scroll time on 4K

lyric mountain
#

My current locale file

#

And I didn't even start the most verbose commands

boreal iron
#

I really dislike JS hasn't a native INI parser like php does

#

I prefer the INI format

#

over JSON

#

so much

lyric mountain
#

I like properties

#

No nesting, each line is a key-value

#

And u can stream the file to load the entry instead of loading the entire file

boreal iron
#

basically like this one

lyric mountain
#

Ye, we use that format at my work

boreal iron
#

while categories (as key) are sexy to work with

#

since you have to write same key, for example rarity/ in any line

#

I can just use the category

lyric mountain
#

I also use properties bcuz intellij has a i18n manager that shows the data side by side (edit all locales at the same time)

boreal iron
#

the ini file which will be parsed as array/object and I can easily access them by the key (category) and val (names)

#

if JS would only have a native INI parser

lyric mountain
#

The editor

boreal iron
#

danke schon

#

I don't trust those google translations

lyric mountain
#

Now you know how to say thank u in german

boreal iron
#

panzerfaust

#

now you know how to say good bye

#

ok enough of that

#

we were talking for an hour and I didn't make any progress

#

I feel like Tim

boreal iron
#

Ok fuck localization

#

The API isn’t ready for it yet

#

Once a command is registered/edited with a description localization for example, it does loose when I restart the app

#

Fetching the command from the API and boom localization is null again

sharp geyser
#

This whole localization gives me a wonderful idea

boreal iron
#

But the command registration promise does return the new and correct application command object

#

With the localization

#

But it’s not accepted by the API for some reason also doesn’t throw an error

#

My gosh

#

Fuck Discord

#

Ok I can now understand Tim

sharp geyser
#

Wait what are you talking bout at this point

boreal iron
#

Let’s say you register an application command at the API

#

You can now add a localization for the command name and description

#

While I don’t care about the command name, the description might be worth to translate

#

As well as any command option descriptions

sharp geyser
#

Yea

boreal iron
#

So when registering that command or editing it, a guild command in my test, I can add the description_localization property to the command object which is an object to

#

{ locale: string }

#

{ "en-US": "us description" }

#

The API will respond successfully with new application command object I’m logging

#

But nothings happens

#

When I restart the app and fetch the guild commands the description localization is null again

sharp geyser
#

Mmmm, maybe localization isn't fully out yet?

boreal iron
#

And even without a restart and clearing the cache no translation is happening

boreal iron
#

Nvm

#

It isn’t

sharp geyser
#

Yea, the api for it is, but client wise I don't think it is

boreal iron
#

Looks like it requires a special discord app built

boreal iron
#

Looks like it’s not ready yet

sharp geyser
#

Yea, well hopefully soon it will be :p

boreal iron
#

Regarding the time they posted it and I can’t even register the localization strings I highly doubt

#

Enough bot rehauling for me right now

#

Back to web development

#

The api isn’t ready for anything they introduced lately

#

As well as the missing features

#

Meh makes me sad

fickle arch
#

I still don't know how to solve this, already do all the troubleshooting on the github page, and I also have node-gyp either.

fallen shard
split hazel
#

why does node gyp always have issues

#

it is singlehandedly the most unreliable thing in node

stiff lynx
#
async function cercaCanale(id, client) {
  let canale;
  let contatoreRicerca = 1;
  do {
    canale = await client.channels.cache.get(id);
    console.log(`Canale cercato ${contatoreRicerca} volt*`);
    contatoreRicerca = contatoreRicerca + 1;
  } while (!canale);
  return canale;
}

Is this good or not?

cinder patio
#

no

#

First off, you're only getting the value from the cache

#

you're not fetching it

stiff lynx
#

the second problem is if the bot doesnt have the permession to see that channel

#

and it will loop forever

cinder patio
#

Second, fetching a channel multiple times makes no sense - you'll always get the same result, unless like you said suddenly a person gives you permission to the channel.

#

But that should be detected in an event

stiff lynx
#

I did this bcs I get a lot of errors bcs the bot doesnt find a channel

cinder patio
#

Third, it's API abuse

#

This will only make it worse

stiff lynx
#

I want to say that this is only a test, In my hosted bot I have

    let canale = await client.channels.cache.get(id)
    return canale
}```
#

lol, still in cache

#

but without cicles

#

I had also fetch

#

but still errors

#
async function cercaCanale(client, id) {
    let canale = await client.channels.fetch(id)
    return canale
}

This should be better, right?

cinder patio
#

yes

stiff lynx
#

with fetch is 100% sure to get the channel?

#

(with the right permissions)

cinder patio
#

yes

#

if it's the right ID and you have permissions to see it

stiff lynx
#

after this I have a question about bot verification, I have only the guild intent for a welcomer.
Is it enough to get the verification or It will be denied?

pale vessel
#

if you don't have permissions to see it you could fetch all channels of that specific guild and find it by id

earnest phoenix
#

@pale vessel your status is great haha

stiff lynx
#

How can I fetch for a guild?

eternal osprey
#
 for(const key in roledatabase){
      m = newMember.guild.roles.cache.find(r => r.id === key);
      newMember.roles.add(m)
      console.log(m)
     }```always returns missing permissions
#

While i am pretty sure the role hierarchy is set, alongside admin perms of the bot.

earnest phoenix
#

You're bots role is above the key role correct?

dry imp
#

@harsh nova scam

stiff lynx
#

I'm trying to add a role in another server for an user that uses a command, but I'm doing somethin' wrong and I don't get what lol

const NPW = await client.guilds.fetch("972430091927818280");
const utente = await NPW.members.fetch(interaction.user.id);

const aggiuntaRuolo = await NPW.utente.roles.add(ruolo);
lyric mountain
#

users cant have roles

#

ah nvm, ur fetching it

#

why dont u just get interaction.member?

stiff lynx
#

works for different server?
The command is being used in server X, and I want to add a role in the server Y

#

ik that is something strange, but is what I need 😮‍💨

lyric mountain
#

nope, for that u do need to fetch the member

#

what's the error ur getting?

stiff lynx
#
const aggiuntaRuolo = await NPW.utente.roles.add(ruolo);
Cannot read properties of undefined (reading 'roles')```
lyric mountain
#

either the member isn't cached or they arent in the server

stiff lynx
#

It's very strange, bcs the console.log of utente and the role are correct

#

I have the data of the Y server, and not X

#

nvm, I've solved it 'NPW.' was not needed

subtle fiber
#

is js better than python?

#

and why

dry imp
#

they are better for different purposes

boreal iron
#

True

#

Best py purpose I know is uninstalling it

hazy vigil
dry imp
#

worst js purpose is installing it

hazy vigil
dry imp
#

worst php purpose i suppose troll

boreal iron
#

lol compared to shit like JS or py php is far ahead

dry imp
#

cope with it fake COPIUM

boreal iron
#

Quiet py user freerealestate

cinder patio
#

lmao are you saying php is better than JS

#

That's objectively false 😦

hazy vigil
#

Make a discord bot in Holy C

hybrid cargo
#

I just made a bot with CSS

dry imp
#

guys remember rules, no lang war troll

boreal iron
#

Ofc that’s the only reason we’re here

hazy vigil
boreal iron
#

CSS very powerful…

dry imp
#

best prog lang imo

#

along with html

boreal iron
#

Aye

subtle fiber
#

bro

lyric mountain
subtle fiber
#

html is not lang

carmine summit
dry imp
cinder patio
boreal iron
#

lol

dry imp
#

my fav lag

boreal iron
#

It even has the L for language in its name

subtle fiber
#

👍

hazy vigil
lyric mountain
boreal iron
#

We’re moving straight of the topic that py sucks

#

Concentration please

carmine summit
#

well that doesnt change the fact that it has a maximum amount of characters you can use which is 30000

lyric mountain
#

for what?

carmine summit
#

i mean you could easily reach it by a few lines of code in js

lyric mountain
#

?

#

like, code doesn't have size limit, it's just that after a certain amount of lines most text editors will refuse to open the file

boreal iron
#

Windows notepad, best editor KEKW

lyric mountain
#

30k characters is easily reachable in normal code

lyric mountain
hazy vigil
lyric mountain
#

no like, really, it's just 3k lines of 10 characters

#

or 300 lines with 100 chars

boreal iron
#

Tbh npp is really good too

#

In opening large files

carmine summit
#

what is this then?

cinder patio
#

I wonder how many people will be able to run my 1TB javascript project smirk

boreal iron
lyric mountain
lyric mountain
#

heck I constantly see people who surpass 30k chars all the time here

#

by putting everything inside index

hazy vigil
carmine summit
boreal iron
#

True

#

50k line in one file is what the kids like to see nowadays

#

Especially on mobile freerealestate

lyric mountain
#

and with no indent

boreal iron
#

lol yes

quartz kindle
#

remember that line counter utility thing

#

that also says how much your code is worth

#

(kinda stupidly exaggerated tho)

lyric mountain
#

my code was worth some tens of millions

quartz kindle
#

lmao

carmine summit
#

wait, loops and functions are a thing?

lyric mountain
#

?

fathom sonnet
lyric mountain
quartz kindle
#

nah, code in powerpoint

cinder patio
#

nah, code with powerpoint

subtle fiber
#

how to get bot developer role

lyric mountain
#

develop a bot ||and have it accepted on top.gg||

subtle fiber
#

so im close

#

i already waiting a week

lyric mountain
#

can bitfields store negative values?

#

ah nvm, I can just use 255 and offset by 127

split hazel
tribal crow
#

Hello hello! I need some help! For a long time I've tried to sort and rank different objects in my database, but i cannot figure out a way to do so. I've managed to sort it from highest to lowest, but how to i get the rank of each item? Any help is appreciated :)

quartz kindle
#

any kind of ranking requires some sort of criteria, so you want to rank them according to what?

tribal crow
#

ok so

#

lets say i have 5 of these:

#

{
user: string
money: number
}

#

then i want to rank them based on the ammount of money they have

cinder patio
#

Use sort

tribal crow
#

I have

cinder patio
#

assuming the objects are in an array

tribal crow
#

Yeah

cinder patio
#

Well then show your code

tribal crow
#

var times = UserProfiles.length;

var Sorted = UserProfiles.sort((a, b) => b - a);

const rank = UserProfiles.map(v => Sorted.indexOf(v) + 1);

#

let UserProfiles = await UserSave.find({ guildID: interaction.guild.id });

cinder patio
#

And what do you want do to? You're already sorting them

tribal crow
#

yeah,

#

but lets say i have an array with the numbers

#

[10, 5, 100, 29, 52]

#

I want to sort then from high to low

#

and then give the highest number the rank #1

#

the second highest #2 etc

cinder patio
#

So you want to sort them in an descending order

tribal crow
#

Yes

cinder patio
#

Then you do a - b instead of b - a in your sort function

tribal crow
#

alr

cinder patio
#

Also this could be simplified, by a lot:

UserProfiles.sort((a, b) => a - b).map(v => v + 1);
tribal crow
cinder patio
#

Pretty sure UserProfiles.map(v => Sorted.indexOf(v) + 1); is wrong because v is the value, not the index

quartz kindle
#

the rank is literally the index of the item in the array after sorting

tribal crow
#

and i get that how?

quartz kindle
#

who is the first rank? sorted[0]
who is the second rank? sorted[1]
what rank is user ID? sorted.findIndex(x => x.id === ID) + 1

tribal crow
#

depends on how many users there are

quartz kindle
#

it doesnt matter?

#

the ranks dont change

tribal crow
#

yeah, but im using a forEach() to add a field to an embed for every user

quartz kindle
#

still doesnt matter

tribal crow
#

-.-

#

i know the ranks don't change, but when adding fields i do it like this

#

embed.addField(`#${rank} <@${element.userID}>`, `\`❂ ${element.bank + element.wallet}\``)

#

right?

#

so i dont know what rank is added

cinder patio
#

Show more code

#

show your entire command

#

you're overcomplicating this

tribal crow
#

i am

#

my english sucks

quartz kindle
#

Sorted = UserProfiles.sort((a, b) => a.money - b.money);

#

Sorted[0]

wheat mesa
#

Also, camelCase please mmulu

cinder patio
#
const sorted = UserProfiles.sort((a, b) => a.money - b.money);
for (let i=0; i < sorted.length; i++) {
   const user = sorted[i];
   embed.addField(`#${i + 1} <@${user.userID}>`, `\`❂ ${user.bank + user.wallet}\``)
}

Simple as that, sort the profiles, then loop through each one. The index of the profile is the rank, so you just add + 1 to it so it starts from 1

#

Also don't put await in front every function call

tribal crow
cinder patio
tribal crow
#

alr

tribal crow
#

ideally 10 times

quartz kindle
#

for (let i=0; i < 10; i++) {

tribal crow
#

alr

#

but since the amount of users is lower than than 10 rn, i get an error because user.userID is undefined 8 times

quartz kindle
#

for (let i=0; i < (sorted.length > 10 ? 10 : sorted.length); i++) {

tribal crow
#

lovely

#

thank you so much

tribal crow
#

ok

#

so now i need to find the rank of one specific user...

#

how would i do that?

cinder patio
#

sorted.find(u => u.userID === id)

tribal crow
#

that gives me the object of that user

cinder patio
#

findIndex

tribal crow
cinder patio
#

sorted.findIndex(u => u.userID === id)

split hazel
#

just found an infinite freelance developer customer glitch

#

lie about having a masters degree in cs

#

tbf hobbyist developers know way more than degree/master students

#

because you're actually motivated