#development

1 messages · Page 220 of 1

civic scroll
#

i just want it to syntax highlight

#

because i can't read with one color

sharp geyser
#

what is that yt video

civic scroll
sharp geyser
#

lol

civic scroll
lyric mountain
civic scroll
sharp geyser
#

:D

wheat mesa
#

That’s cheating 😡

#

Honestly it’s better to manually roll out your own parser for your first few languages if your intent is to learn

civic scroll
#

maybe i can cheat my way through textmate

sharp geyser
#
expression     → equality ;
equality       → comparison ( ( "!=" | "==" ) comparison )* ;
comparison     → term ( ( ">" | ">=" | "<" | "<=" ) term )* ;
term           → factor ( ( "-" | "+" ) factor )* ;
factor         → unary ( ( "/" | "*" ) unary )* ;
unary          → ( "!" | "-" ) unary
               | primary ;
primary        → NUMBER | STRING | "true" | "false" | "nil"
               | "(" expression ")" ;

@wheat mesa

#

HOW THE FUCK DOES THIS MAKE SENSE

#

😭

#

wait

#

Is it because expression evaluates to equality, which trickles down the ladder in terms of building a complete syntax?

#

because equality at the end of the day is making a reference to all of them

#

as each one references the next

lyric mountain
#

I once fell into that trap

sharp geyser
#

still not sure what it means by equality being the "lowest prescendence"

lyric mountain
#

when I was writing my expression parser

sharp geyser
#

😭

lyric mountain
#

turns out the generated AST was impossible to work with

#

to process it all I'd have to write a very large file

sharp geyser
#

😭

#

This book is making me realize just how dumb I am when it comes to programming

#

its not a good feeling

lyric mountain
#

nah, making asts is like that

sharp geyser
#

The words he uses to describe things granted is very dumbed down

#

but I still do not understand the concept and theory behind an AST and the grammar rules and such

scenic kelp
#

this is how you implement operator precedence at a parser level

sharp geyser
#

Ima be real with you chief

#

idk what that means

scenic kelp
#

you add a different rule for each level, and each rule feeds into the next until you get back to the bottom

#

the other option is you can do it all in one rule and then fix it with a second pass and a different parser dedicated just to operator precedence

#

which would be cool actually because then theoretically users could define their own operators with their own precedences

sharp geyser
#

I see

#

I just have no idea how t oread that

#

like how would (9 / 3) * 2 look going based off those rules

#

like what is the order at which it is evaluated

#

cuz I see no way an expression like that can escape comparison since there is no comparison going on

#

so would it not get stuck at that parsing stage in the grammar?

scenic kelp
#

no because look at the grammar

sharp geyser
#
expression     → equality ;
equality       → comparison ( ( "!=" | "==" ) comparison )* ;
comparison     → term ( ( ">" | ">=" | "<" | "<=" ) term )* ;
term           → factor ( ( "-" | "+" ) factor )* ;
factor         → unary ( ( "/" | "*" ) unary )* ;
unary          → ( "!" | "-" ) unary
               | primary ;
primary        → NUMBER | STRING | "true" | "false" | "nil"
               | "(" expression ")" ;

putting it here cuz tired of scrolling

scenic kelp
#

term (('>' | ... | '<') term)*;

sharp geyser
#

oh wait does the * mean 0 or more?

scenic kelp
#

yes

sharp geyser
#

so that means if there is 0 it moves on?

scenic kelp
#

that rule is equivalent to term | term (('<' | ... | '>') term) (im actually not sure if * is 0-1 or 1+ or 0+ or what so yknow)

#

if it's the same as regex then 0+ but

sharp geyser
#

term (('>' | ... | '<') term)*; what is the point of the term outside of the paren if its inside the paren as well

scenic kelp
#

wdym

#

there's a group

sharp geyser
#

like term (('>' | ... | '<') term)*;

scenic kelp
#

because

sharp geyser
#

whats the point of that term

scenic kelp
#

that's the part that enables everything

sharp geyser
#

how so?

scenic kelp
#

if there's no operator, it continues down the parse tree

sharp geyser
#

so wait

#

this allows for stuff like 1 + 1 > 1-1?

scenic kelp
#

yes

#

i'll use a simpler example to explain

sharp geyser
#

1 + 1 / 1 -1 would be the term and then it allows for plugging in >

#

and then that 1 + 1 and 1 - 1 would continue trickling down the parse tree until it is associated properly

#

but if you were simply doing 1 + 1
it'd go
expression -> equality nothing there -> comparison nothing there -> term ah there is a + -> 1 & 1 move on to factor nothing there -> unary nothing -> primary ah 1 & 1 are numbers -> primary (NUMBER) term (+) primary (NUMBER)

scenic kelp
#
expression: group1 (('+' | '-') group1)*;
group1: group2 (('*' | '/') group2)*;
group2: unary group3 | group3;
group3: '(' expression ')' | atom;
atom: NUMBER;
#

that's a simpler grammar

#

i might actually even write a simpler lexer and parser to demonstrate it hold on

scenic kelp
#

something like that

scenic kelp
#

i'm also stupid and forgot to parse group 2 i think lol

#

oh wait no i just named it wrong

#

ok that's the actual result

sharp geyser
#

hm ic

scenic kelp
#

you were right

sharp geyser
#

oh was i

#

kekw

#

So all a CFG is, is just plugging in values once they are determined

#

and sometimes they can be indefinite if you don't specify an escape condition like say allowing it to be 0 or more, or an empty character or something else in the grammar

#

like

S -> aSB
B -> b

this would cause an indefinitely loop of aabbabbbabbb or smth

#

I am going based off a video I just watched and notes someone sent me on understanding a CFG

sharp geyser
# scenic kelp you were right
 private Expr Primary()
    {
        if (MatchExpr(TokenType.FALSE)) return new Expr.Literal(false);
        if (MatchExpr(TokenType.TRUE)) return new Expr.Literal(true);
        if (MatchExpr(TokenType.NIL)) return new Expr.Literal(null);

        if(MatchExpr(TokenType.NUMBER, TokenType.STRING))
        {
            return new Expr.Literal(Previous().literal);
        }

        if(MatchExpr(TokenType.LEFT_PAREN))
        {
            Expr expr = Expression();
            Consume(TokenType.RIGHT_BRACE, "Expected a ')' after expression");
            return new Expr.Grouping(expr);
        }

        // How would I handle this return case? 
    }

So what should I return if none of the MatchExpr follow through? I was thinking of somehow making it return a EOF token but idk how that'd work

#

The java code for this is weird because java will accept any return statement as an ending, C# on the other hand needs a top level return as well e.g one directly returning in the scope of the function and not inside an if statement or smth

#

I don't necessarily want to return a null literal do i?

#

cause my first thought might of been to do

private Expr Primary()
    {
        if (MatchExpr(TokenType.FALSE)) return new Expr.Literal(false);
        if (MatchExpr(TokenType.TRUE)) return new Expr.Literal(true);
        if (MatchExpr(TokenType.NIL)) return new Expr.Literal(null);

        if(MatchExpr(TokenType.NUMBER, TokenType.STRING))
        {
            return new Expr.Literal(Previous().literal);
        }

        if(MatchExpr(TokenType.LEFT_PAREN))
        {
            Expr expr = Expression();
            Consume(TokenType.RIGHT_BRACE, "Expected a ')' after expression");
            return new Expr.Grouping(expr);
        }

        // How would I handle this return case? 
        return new Expr.Literal(null)
    }

but that seems counter-productive to what the code is trying to do which is do nothing if none of the if statements match.

eternal osprey
sharp geyser
#

yea

#

it was easy to understand after breaking it down and thinking ofi t like placeholders

warm imp
#
const fs = require('fs');

const client = new Client({ 
    intents: [
        Intents.FLAGS.GUILDS,
        Intents.FLAGS.GUILD_MESSAGES
    ] 
});

client.commands = new Map();

// Load commands
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
    const command = require(`./commands/${file}`);
    client.commands.set(command.name, command);
}

// Load event handlers
const eventFiles = fs.readdirSync('./events').filter(file => file.endsWith('.js'));
for (const file of eventFiles) {
    const event = require(`./events/${file}`);
    if (event.once) {
        client.once(event.name, (...args) => event.execute(...args, client));
    } else {
        client.on(event.name, (...args) => event.execute(...args, client));
    }
}

client.login('Token');```
#

What is wrong with this?

deft wolf
#

It looks like it works without any problems. What error do you have in the console?

warm imp
#
                ^

TypeError: Cannot read properties of undefined (reading 'FLAGS')
    at Object.<anonymous> (D:\Invite Manager\index.js:6:17)
    at Module._compile (node:internal/modules/cjs/loader:1434:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1518:10)
    at Module.load (node:internal/modules/cjs/loader:1249:32)
    at Module._load (node:internal/modules/cjs/loader:1065:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:158:12)
    at node:internal/main/run_main_module:30:49```
deft wolf
#

So you are using discord.js v14 right?

warm imp
#

yes

deft wolf
warm imp
deft wolf
#

It's your bot, you should know what intents it needs PepoThink

surreal sage
#

where did it go wrong 💔

lyric mountain
warm imp
#
const fs = require('fs');

const client = new Client
    intents: 
        GatewayIntentBits.Guilds,
        GatewayIntentBits.GuildMessages,
        GatewayIntentBits.MessageContent,
        GatewayIntentBits.GuildMembers,

client.commands = new Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));

for (const file of commandFiles) {
    const command = require(`./commands/${file}`);
    client.commands.set(command.data.name, command);
}

const eventFiles = fs.readdirSync('./events').filter(file => file.endsWith('.js'));

for (const file of eventFiles) {
    const event = require(`./events/${file}`);
    if (event.once) {
        client.once(event.name, (...args) => event.execute(...args, client));
    } else {
        client.on(event.name, (...args) => event.execute(...args, client));
    }
}

client.login('Token');```
#

Says ClientMissingIntents

lyric mountain
#

they even changed the uppercase constant to pascalcase

deft wolf
#

I have no idea where all your brackets went

neon leaf
#

should I continue optimizing some endpoints or is this good enough? (db is on same server, so 0 ping)

warm imp
#

Why is my commands not syncing with discord?

deft wolf
#

Because you have to register them in the Discord API

warm imp
#

How

#

Where

deft wolf
#

You really need to read this entire guide masnakappa

warm imp
#

DId the API

#

Now what

deft wolf
#

Now the commands should pop up when you type /

warm imp
#

I have 3 other ones but i deleted those

#

Do i have to add it in my index.js?

deft wolf
#

I don't quite understand what you mean now. Have you registered commands before?

warm imp
#

Nope just started today kinda

deft wolf
#

Generally, this should not be added to index.js because the code from it is fired every time the bot is turned on. You don't want to register commands again every time your bot starts, only when the situation requires it. Therefore, it is recommended to create a separate file for deploying commands

eternal osprey
neon leaf
#

most are just ratelimits or unauthenticated

surreal sage
#

feeling cute might make my own wiki alternative to mediawiki for no reason

sharp geyser
#
private void Syncronize()
    {
        Advance();

        while (!IsAtEnd())
        {
            if (Previous().type == TokenType.SEMICOLON) return;

            switch (Peek().type)
            {
                case TokenType.CLASS:
                case TokenType.FUN:
                case TokenType.VAR:
                case TokenType.FOR:
                case TokenType.IF:
                case TokenType.WHILE:
                case TokenType.PRINT:
                case TokenType.RETURN:
                    return;
            }

            Advance();
        }
    }

Not quite sure what this is exactly doing

#

It has to do with something about synchronizing the recursive descent parser's state

#

But I dont quite understand how it is doingthat

#

all its doing is returning whenever it runs ito the keywords class, fun, var, for, if, while, print and return

#

oh and a semi then it consumes that token moving on

#

Pulled directly from the book

With recursive descent, the parser’s state—which rules it is in the middle of recognizing—is not stored explicitly in fields. Instead, we use Java’s own call stack to track what the parser is doing. Each rule in the middle of being parsed is a call frame on the stack. In order to reset that state, we need to clear out those call frames.

The natural way to do that in Java is exceptions. When we want to synchronize, we throw that ParseError object. Higher up in the method for the grammar rule we are synchronizing to, we’ll catch it. Since we synchronize on statement boundaries, we’ll catch the exception there. After the exception is caught, the parser is in the right state. All that’s left is to synchronize the tokens.

We want to discard tokens until we’re right at the beginning of the next statement. That boundary is pretty easy to spot—it’s one of the main reasons we picked it. After a semicolon, we’re probably finished with a statement. Most statements start with a keyword—for, if, return, var, etc. When the next token is any of those, we’re probably about to start a statement.
It says it makes use of the call stack, but idk if that applies to C# as well (im sure it does since they both are similar in how they compile I think)

sharp geyser
#

Side Note:
I have this string representation of my AST: (/ (* (group (* 2 10)) 40) 3)

#

Is this how it'd look like written out?

proven lantern
#
const placementDisplay = require("../record_match/placementDisplay");
const displayLeaderboard = (elo_ratings) => {
    if (elo_ratings.length === 0) {
        return `No players have played any matches yet. Use \`/record_match\` to record a match.`;
    }
    let leaderboard = "";
    const limit = 4096;
    for (const eloRating of elo_ratings) {

        // Skip hidden ratings
        if (eloRating.hidden) {
            continue;
        }

        // the next line to add to the leaderboard
        const nextLine = `${placementDisplay(eloRating.placement)} ${
            eloRating.players.map(p => `**__${p.name}__**`).join(" ■ ")
        } ${eloRating.elo}\n`

        // the potential length of the leaderboard if the next line is added
        const potentialLeaderboardLength = leaderboard.length + nextLine.length;

        // if the next line would exceed the 4096-character limit, break the loop
        if (potentialLeaderboardLength > limit) {
            console.log("Leaderboard too long, breaking");
            break;
        }

        // add the next line to the leaderboard
        leaderboard += nextLine;
    }
    return leaderboard.trim();
}

module.exports = displayLeaderboard;

I am trying to prevent discord from trimming the message in the middle of a line, but it seems to be trimming some of the message. are there too many new lines \n?

#

what is discord doing to my messages?

quartz kindle
#

so all texts combined cannot exceed 4k

#

the trimming is weird tho, one would think it would error instead

proven lantern
#

it cuts in almost in half

quartz kindle
#

is it embed description or embed field?

#

ah description

proven lantern
#

embed description

quartz kindle
#

so yeah idk

proven lantern
#

when the lines are shorter i can add more new lines

quartz kindle
proven lantern
sharp geyser
#

wrong chat

quartz kindle
#

what if you remove those first 3 emojis?

#

emojis count towards the limit in their full form name:id, not in their short form

proven lantern
#

oh yeah, that would be longer. i only have those 3 emojis

quartz kindle
#

what about the squares in the middle?

#

there is a chance discord counts them as 2 characters

proven lantern
#

perhaps, let me check

#

also a weird things how Player 2 was removed, but the elo is there and the placement for the next line is there

quartz kindle
#

what if you remove the formatting

proven lantern
#

it's the formatting

#

discord must have some sort of bug there

quartz kindle
#

they count characters based on how its rendered

#

not the characters you send

#

maybe the rendering turns into html

#

and they count the full tags

proven lantern
#

but i am sending less than 4096 characters so the API accepts it, but still cuts it down in size

quartz kindle
proven lantern
# quartz kindle there are some issues about it on their gh

i think they have a bug like this somewhere too

const tokens = [
    "102nd ", "**__Player 1__** ", '1000\n',
    "103rd ", "**__Player 1__** ", '1000\n',
];

const maxLength = 20;
const description = tokens.reduce((acc, token) => {
    if (acc.length + token.length > maxLength) {
        return acc;
    }
    return acc + token;
}, "");
console.log(description);```
#

that's how this happened

quartz kindle
#

and they run that after transforming and formatting the text

#

which probably turns it into html

mystic zinc
#

@river flicker

proven lantern
#

could be this too

pearl trail
#

ong

radiant kraken
#

Array.from splits the string in terms of unicode codepoints, while string itself is internally encoded in UTF-8 iirc

proven lantern
#

the weird thing is that i can retrieve the whole message using the API. it's just when it displays in discord that it cuts down the message

sharp geyser
#

discord trims it in the app

#

but I think it still stores the entire message

proven lantern
sharp geyser
#

I think this is mainly due to them increasing the limit for nitro users

#

and bots have basically nitro limits on messages

proven lantern
#

no it's a bug

sharp geyser
#

I doubt its a bug

#

because they limit the amount of characters in embeds

proven lantern
#

if you go above it rejects the message

sharp geyser
#

Yea

#

How many characters is what you are putting in the description?

proven lantern
proven lantern
quartz kindle
surreal sage
#

chatgpt moment

pearl trail
#

not entirely wrong

quartz kindle
#

including the html tags

quartz kindle
#

what about the count without the newline spans?

#

counting only the content and the strong/u tags

ashen scroll
#
// Check if the bot has permission to send messages in the music channel
      if (!interaction.guild.me.permissionsIn(musicChannel).has(PermissionsBitField.Flags.SendMessages)) {
        return interaction.reply("I don't have permissions to send messages in that channel.").catch(err => {
          client.error(err);
        });
      }

its not working am i missing something?

deft wolf
#

Shouldn't it be ineraction.guild.members.me? PepoThink

proven lantern
quartz kindle
#

im guessing they count the characters from the formatting tags but dont count the spans for newlines

ashen scroll
# deft wolf Shouldn't it be `ineraction.guild.members.me`? <:PepoThink:970083360460398625>

hmm i try that and array return this

[
'CreateInstantInvite', 'AddReactions',
'Stream', 'SendMessages',
'EmbedLinks', 'AttachFiles',
'ReadMessageHistory', 'UseExternalEmojis',
'Speak', 'UseVAD',
'ChangeNickname', 'UseApplicationCommands',
'RequestToSpeak', 'CreatePublicThreads',
'CreatePrivateThreads', 'UseExternalStickers',
'SendMessagesInThreads', 'UseEmbeddedActivities',
'UseSoundboard', 'UseExternalSounds',
'SendVoiceMessages', 'SendPolls'
]

when bot dont have send message permission in that channel

quartz kindle
#

the math still doesnt addup completely tho

#

im guessign you could open an issue on their github and wee what they say

deft wolf
civic scroll
#

gaming

sharp geyser
#

Never seen someone make a language for drawing

surreal sage
eternal osprey
sharp geyser
#

what

#

thats cool

civic scroll
sharp geyser
#

she made a language....to draw

#

I'd say thats cool asf

deft wolf
#

What

green kestrel
#

hmmm, i forgot, triviabot is keeping a count of http requests by status code for posting webhooks

#

since i started counting, about 3 years ago, triviabot has sent 90 million messages 😮

#

that is just... absolutely nuts

lyric mountain
#

the misaligned arm was triggering my ocd

solemn latch
real rose
#

that's wild

#

i didnt even notice

sharp geyser
devout spade
surreal sage
#

"well a pro made it"
guys does this look like a pro's work

neon leaf
#

yes

surreal sage
#

what about a throw error statement without a catch block

neon leaf
#

amazing

#

only pros do that

#

job security

sharp geyser
#

Gotta secure your own job!

civic scroll
#

it's sorta getting out of hand now

stark abyss
#

what did i even do smh

split bane
#

is something being read wrong?

sharp geyser
#

How are we supposed to know

split bane
#

yeah I dont really know either atp

sharp geyser
#

Do you have any errors?

split bane
#

no errors

sharp geyser
#

Are you silently dismissing them?

#

no .catch(() => null)

split bane
#

I wrote this back like 2 years ago I forgot how everything was made

#

it is silent

sharp geyser
#

If something is going wrong, its highly likely the error is being dismissed

split bane
#

lemme just try something that could break the whole thing

#

actually I wont do that

#

found the problem

#

when someone votes it doesnt get pushed to the database

#

no idea how to fix it

#

¯_(ツ)_/¯

#
module.exports = async (data: VoteUser) => {
    getCollection("votes").updateOne({id: data.user_id}, {"$push": {votes: {at: Date.now(), source: data.source}}}, {upsert: true});
    addEvent({
        type: "vote",
        command: "vote",
        source: data.source
    });
}
#

this isnt working?

#

it should be though

civic scroll
#

updateOne could fail

shell tundra
#

has anyone been able to successfully change their verified bot's name?

#

like did discord let you

deft wolf
#

I have never had such a need, but someone on DDevs wrote that it is not that simple because you also need to have some reason to do it

#

I found this message

bitter granite
#

Basicly you need a reason

#

Usualy it needs to be legal reason

shell tundra
#

i see

#

ty

frosty gale
#

you can probably make some shit up

#

like some arbitrary company that has a similar name to your bot is threatening to sue for it

#

doubt theyll investigate it

deft wolf
#

"We need proof" Madge

frosty gale
#

or just rebrand and thats probably a good enough reason

lyric mountain
surreal sage
#

ughhh i love webp

#

1.5 mb grayscale png down to 325 kb

#

and then with gzip

#

😫

frosty gale
surreal sage
#

yes

radiant kraken
#

@lyric mountain do u know how to publish a jar file to sonatype?

#

i tried looking up online and it seemed that some of the results are outdated

lyric mountain
#

You don't publish a jar file, you deploy

radiant kraken
#

what's the difference

lyric mountain
#

You never upload a file, you build there + source and javadocs

radiant kraken
#

noooooo 😭

lyric mountain
#

You'll use sonatype plugin for this

radiant kraken
#

my java library involves some native binaries

lyric mountain
#

If it's in the classpath I think it's sent together with anything else

radiant kraken
#

the native binary files are stored in a zip file in the repository

#

and unzipped before being built to a jar

lyric mountain
#

Well

#

You'll need to include it as a resource

#

As in, the resources folder

#

Then call it from there

radiant kraken
#

resource?

#

like this? ```
jar {
from('./bin') {
include '.dll'
include '
.dylib'
include '*.so'
}
}

radiant kraken
lyric mountain
#

you can also instruct the users to download one of the native bundles and put it in a predictable folder in the project

lyric mountain
#

packages deployed through the plugin are signed and checked for CVEs automatically

solemn latch
#

I figure its about time I play with redis. Does anyone have an NPM lib they use/reccomend? 👀

sharp geyser
solemn latch
#

Yeah, thought so

#

thanks

sharp geyser
#

👍

lyric mountain
#

you'll have a hard time trying to get redis to work on windows

solemn latch
#

Yeah, I'm on linux anyway

lyric mountain
#

you're fine then

sharp geyser
#

Also isn't redis no longer free & open source?

solemn latch
#

Some parts are iirc

sharp geyser
#

yea they changed their licenses and caused an outroar

#

dk if they changed em back or not

lyric mountain
#

changing license midway on a very popular project just means people will fork the hell out of it while the original thing falls to oblivion

#

cant think of a single case where it worked out well

solemn latch
#

Its still too early to tell which fork will survive and be maintained, so for now redis will work for me

neon leaf
#

keydb ftw

prisma nebula
#

Hey why my application cant be launched using the installed tab. It says lsunch override only

sharp geyser
#

making your own redis ftw

prisma nebula
#

Is there a requirement or something

warm imp
#

const result = binding.readdir(
^

Error: ENOTDIR: not a directory, scandir 'D:\Invite Manager\commands\ping.js'
at Object.readdirSync (node:fs:1509:26)
at Object.<anonymous> (D:\Invite Manager\index.js:15:26)
at Module._compile (node:internal/modules/cjs/loader:1434:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1518:10)
at Module.load (node:internal/modules/cjs/loader:1249:32)
at Module._load (node:internal/modules/cjs/loader:1065:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:158:12)
at node:internal/main/run_main_module:30:49 {
errno: -4052,
code: 'ENOTDIR',
syscall: 'scandir',
path: 'D:\Invite Manager\commands\ping.js'

#

How do i fix that

earnest phoenix
#

average person asking for help about code

#

you did not provide code and the error is a little obvious

split bane
warm imp
deft wolf
#

Without the code it's hard to say how to fix it

lyric mountain
warm imp
#

What's that?

lyric mountain
#

...did you copy the bot from somewhere?

warm imp
#

So kinda

lyric mountain
#

I'd advise against trying to make a bot without any introduction to coding whatsoever

#

you'll very likely end up with a non-functional bot or be unable to do anything outside what's written in the guides

#

but well, to answer your question, readdir which is likely being used to dynamically load commands cannot be used on files, as files aren't directories

#

for files you use require instead

devout spade
lyric mountain
#

I still dont get why ur posting it here

surreal sage
#

hi chat

#

how can i fix this

sharp geyser
#

you cant

surreal sage
sharp geyser
#

it tells you what to do

surreal sage
#

ehem

#

node_auth_token

#

is set

#

i was using pnpm before this

sharp geyser
#

that doesnt matter

#

you need to be logged in on the registry

#

and authorize that machine to make publishes

surreal sage
#

hey thanks no thanks i had to add registry-url to actions/setup-node

split bane
# civic scroll did you await
import { VoteUser } from './VoteUser';
import { getCollection } from '../mongo';
import { addEvent } from '../functions';

module.exports = async (data: VoteUser) => {
    await getCollection("votes").updateOne(
        { id: data.user_id },
        { "$push": { votes: { at: Date.now(), source: data.source } } },
        { upsert: true }
    );

    await addEvent({
        type: "vote",
        command: "vote",
        source: data.source
    });
}
#

it still doesnt push

civic scroll
#

is addEvent async

#

also

#

actually

#

run a debugger

#

insert breakpoint on addEvent
see if it hits

#

and also, log the result of updateOne and verify if it's updated successfully

split bane
#
import { VoteUser } from './VoteUser';
import { getCollection } from '../mongo';
import { addEvent } from '../functions';

module.exports = async (data: VoteUser) => {
    try {
        await getCollection("votes").updateOne(
            { id: data.user_id },
            { "$push": { votes: { at: Date.now(), source: data.source } } },
            { upsert: true }
        );
    } catch (error) {
        console.error('Error updating votes collection:', error);
        throw new Error('Failed to update votes collection');
    }

    try {
        debugger;
        await addEvent({
            type: "vote",
            command: "vote",
            source: data.source
        });
    } catch (error) {
        console.error('Error adding event:', error);
        throw new Error('Failed to add event (u suk ballz at coding)');
    }
}
#

I havent tested it

quartz kindle
neon leaf
#

tim says bye

split bane
#

where did my testvote thing go

#

wtf

#

istg nothing working 🤩

neon leaf
#

@lyric mountain sir

sharp geyser
quartz kindle
split bane
#

uhh

#

nothing in logs lets go

sharp geyser
#

wait

sharp geyser
#

so why is it being compared to redis

#

redis isn't really a database

#

its a caching layer at most

#

tf is blueql

#

is it their custom sql language

#

it honestly looks rather neat

#

the first nosql db that actually looks promising

frosty gale
#

i hate to say it but it looks just like postgres with extra steps with mongodb roots

lyric mountain
sharp geyser
#

it looks more promising than mongodb

#

as far as nosql goes i'd rather use something like this than mongodb

neon leaf
#
const stats = await client.$queryRawUnsafe<{
                type: MinecraftServerType
                minecraft: BigInt
                project: BigInt
                builds: BigInt
            }[]>(types.map((type) => `
                SELECT 
                    '${type}' AS type,
                        (SELECT COUNT(*) 
                        FROM "minecraftVersions" mv
                        WHERE EXISTS (
                            SELECT 1
                            FROM "minecraftServerBuilds" b
                            WHERE b."versionId" = mv.id
                            AND b.type = '${type}'
                        )
                    ) AS minecraft,
                    (SELECT COUNT(*) 
                        FROM "projectVersions" pv
                        WHERE EXISTS (
                            SELECT 1
                            FROM "minecraftServerBuilds" b
                            WHERE b."projectVersionId" = pv.id
                            AND b.type = '${type}'
                        )
                    ) AS project,
                    (SELECT COUNT(*)
                        FROM "minecraftServerBuilds" msb
                        WHERE msb."type" = '${type}'
                    ) AS builds
                `).join(`
                UNION ALL
                `).concat(';')
            )```
#

this is my current solution

sharp geyser
#

minecraft?

neon leaf
lyric mountain
#

first tell me what u want

neon leaf
#

for each type in the "MinecraftServerType" enum, I want to know how many builds, projectVersions and minecraftVersions

neon leaf
lyric mountain
#

why are u doing union all?

neon leaf
#

I really do not know

#

its slightly faster than what i had before

#

but still quite slow

lyric mountain
#

a bit busy atm, I'll come back in a few mins

neon leaf
#

k

split bane
#
[ERROR] [9055:12:36]     at resolveColor (/home/simplyreact/node_modules/discord.js/src/util/Util.js:260:63)
[ERROR] [9055:12:36]     at EmbedBuilder.setColor (/home/simplyreact/node_modules/discord.js/src/structures/EmbedBuilder.js:22:36)
[ERROR] [9055:12:36]     at module.exports (/home/simplyreact/out/events/interactionCreateModal.js:21:65)
[ERROR] [9055:12:36]     at Client.emit (node:events:513:28)
[ERROR] [9055:12:36]     at module.exports (/home/simplyreact/out/events/interactionCreate.js:9:13)
[ERROR] [9055:12:36]     at Client.emit (node:events:513:28)
[ERROR] [9055:12:36]     at InteractionCreateAction.handle (/home/simplyreact/node_modules/discord.js/src/client/actions/InteractionCreate.js:97:12)
[ERROR] [9055:12:36]     at module.exports [as INTERACTION_CREATE] (/home/simplyreact/node_modules/discord.js/src/client/websocket/handlers/INTERACTION_CREATE.js:4:36)
[ERROR] [9055:12:36]     at WebSocketManager.handlePacket (/home/simplyreact/node_modules/discord.js/src/client/websocket/WebSocketManager.js:352:31)
[ERROR] [9055:12:36]     at WebSocketShard.onPacket (/home/simplyreact/node_modules/discord.js/src/client/websocket/WebSocketShard.js:494:22) {
[ERROR] [9055:12:36]   code: 'ColorConvert'
[ERROR] [9055:12:36] }
#

💀

#

im so done

sharp geyser
#

you're doing smth wrong

#

:)

split bane
#

I havent changed anything

#

code just breaks cause it feels like it 😭

sharp geyser
#

nah

#

you're doing something on line 21 of interactionCreateModal

#

what is line 21

frosty gale
neon leaf
#

no

#

type is controlled by me

frosty gale
#

funnily enough thats how most sql injection cases occur

#

developers assume a certain value is always controlled by them but forget about that one small factor

neon leaf
#

thats why I am only using unsafe query in this one place in my entire codebase

#

types is a constant array

#

readonly

quartz kindle
#

if you need a full table scan anyway, theres not much you can do to make it faster than a full table scan

neon leaf
#

well

#

I have a feeling im doing multiple

#

because a full scan is very quick in my case

#

only ~2mil rows in all those tables

quartz kindle
#

you might as well SELECT buildNumber, versionId, projectVersionId from MinecraftServerBuilds

#

and then count it in js

neon leaf
#

rip my ram

quartz kindle
#

i guess you can make sql do it somehow, from only 1 table scan

#

try this

SELECT buildNumber, versionId, projectVersionId, COUNT(*) FROM MinecraftServerBuilds GROUP BY buildNumber, versionId, projectVersionId
neon leaf
#

sir

#

that returned 102k rows

devout spade
#

I feel so wrong 💀💀💀💀💀

quartz kindle
sharp geyser
neon leaf
#

red

#

color

#

color = something used in discordjs

sharp geyser
#

I think you read too much into that

quartz kindle
# neon leaf

lets first establish a baseline, how fast is it if you just run multiple queries? SELECT COUNT(*) FROM minecraftServerBuilds WHERE type = "${type}"

sharp geyser
#

This seems like some wild roleplay type shit

#

dont tell me top.gg roleplay is making a comeback /j

neon leaf
#

28ms for quilt

#

pretty much all around 30ms

quartz kindle
#

thats not bad for 2 million rows

#

i guess

neon leaf
#

well

sharp geyser
#

yea but I bet you can make it faster tim

neon leaf
#

the table isnt 2 mil rows

#

all tables combined are

sharp geyser
#

you are the god of optimization

neon leaf
#

minecraftServerBuilds is 104k rows

quartz kindle
#

i see

#

and for each type, you want an output like this? builds: 7375, versions: 783453, projectVersions: 495983953

neon leaf
#

yes

#

@quartz kindle I have found the solution

#
SELECT 
    "type",
    COUNT(DISTINCT "versionId") AS versions,
    COUNT(DISTINCT "projectVersionId") AS project_versions,
    COUNT(*) AS builds
FROM 
    "minecraftServerBuilds"
GROUP BY 
    "type";
#

149ms

quartz kindle
#

cool

neon leaf
#

i didnt even know you could do this tbh

quartz kindle
#

yeah that looks sane

#

i was trying to setup an sql fiddle to test it

sharp geyser
#

you can compound count ofc

quartz kindle
# neon leaf 149ms

just for the heck of it, what would be the performance of dumping 104k rows and counting in js?

#

lmao

neon leaf
#

I think this phenomenon is called "v8 stack trace: "

quartz kindle
#

xD

solemn latch
#

for the performance

quartz kindle
#

jenius

quartz kindle
neon leaf
quartz kindle
neon leaf
#

its really hard to do any indexes on this table

#

the data is so absurdly different

quartz kindle
#

well, type apparently isnt

neon leaf
#

this is my hashes table

#

index bigger than data itself

quartz kindle
#

lmao

neon leaf
#

changes deployed and its so much faster holy shit

#

1.5s to 250ms

eternal osprey
#

ahh hell nah, i hired a fiverr developer for some graphics they gave me doodo

#

deadass served me shit

#

70$ for this bitch ass

neon leaf
#

lol

surreal sage
#

ah yes, an update is available!

runs pnpm update
"Already up to date"

runs pnpm update next
"Already up to date"

:(

neon leaf
#

well

#

update follows semver

#

it does not update major automatically

#

you need to edit package.json for that or do pnpm i eslint@latest

surreal sage
#

ughhh

quartz kindle
#

if you're still using the eslintrc file you're gonna have a bad time

surreal sage
#

compatibility shucks with extensions i think

#

just on the latest v8 for now

#

as long as it works..

quartz kindle
#

v9 moved to the new eslint.config.js format

#

its a pain to migrate

surreal sage
#

yea i didnt really like how the settings for rules were done

#

no types either..

#

just pray it works

#

barely updated it nvm

eternal osprey
#

@frosty gale Are you familiar with using DNSSec over regular DNS?

frosty gale
#

havent heard of it 😦

eternal osprey
#

It's over for me.

#

I need to migrate to DNSSec with 0% practical knowledge, only theory

neon leaf
eternal osprey
neon leaf
#

no

pale vessel
neon leaf
#

hey

#

thief

pale vessel
#

yup

neon leaf
#

im calling the meows

pale vessel
#

i'm on phone 😔

surreal sage
#

just saw 5 websites

#

owned and operated by the same company

#

with the same similair designs

#

selling the same products

#

competing against urself..

sharp geyser
#

well yea

#

probably all US companies right?

surreal sage
#

nope

#

all dutch

sharp geyser
#

interesting

#

but ye

#

common tactic

#

usually I see US companies doing it more tho

surreal sage
#

5 of them is crazy

sharp geyser
#

and all 5 of them probably generate revenue

#

don't hate the player hate the game

#

gotta make money in this world

surreal sage
#

all the boxed ones are server racks, all the rest are cables

#

crazy...

past field
#

anyone have a good strategy for tagging players in a lobby while staying within the character limit?

#

i had a lobby of 96 people, tried to tag all players that the game is about to start then crash’s with 2000 characters limit

sharp geyser
#

just dont

#

1 method you can do is make a channel jsut for that lobby

#

so you can ping everyone

#

:)

past field
#

i was thinking have the server owner create a role for the game, bot will assign it when they hit “join” and when the game starts it’ll say “Game is starting @(role name)” so they get pinged and the bot just removes it from everyone once the game ends.. is this possible?

sharp geyser
#

Yes

#

but relying on the server owner to do so is ill advised

#

just make it yourself

#

assign people to it when they join and when the game starts and ping em

#

remove role from em at the end

#

Note you will run into limits doing this

#

so its better to create a private channel, have an array of ids. that you will use for channel overwrites making it so only those people can view the channel disallowing everyone else

#

and then ping everyone

past field
#

ahhhh that’s a good idea

warm imp
#

Is typescript easier than most languages?

sharp geyser
# past field ahhhh that’s a good idea
const channel = await guild.channels.create('somename', {
  permissionOverwrites: [
    {
      id: arrayOfIds
      allow: [arrayOfPermissionBitFlags]
    },
    {
      id: guild.id,
      deny: [PermissionBit.Flags.ViewChannel] // or smth idk
    }
  ]
})
#

I might be wrong on the arrayOfIds part

#

but iirc you can use an array of ids

#

if not

#

just loop through the array of members in the lobby and make a permission overwrite for each of em

#
const channel = await guild.channels.create('somename', {
  permissionOverwrites: [
    {
      id: guild.id,
      deny: [PermissionBit.Flags.ViewChannel] // or smth idk
    },
    ...arrayOfMembers.map((r) => { return { id: r.id, allow: [ViewChannelPermission] } })
  ]
})
#

I think that could work idk

#

Haven't done js in a while

#

nvm

#

there we go

#

that should work

#

:)

sharp geyser
#

dont have to follow it exact but this is one way to do it

past field
quartz kindle
warm imp
quartz kindle
#

typescript is the same thing as javascript but with an extra safety layer where you have to declare the types you are using

sharp geyser
#

you dont have to

#

unless you have strict mode on

quartz kindle
#

for example, in tyopescript you dont do const abc = 1, you do const abc: number = 1

sharp geyser
#

you can still do const abc = 1

quartz kindle
#

just illustrating an example ignoring inference for now

sharp geyser
#

typescript is only useful when you want to enforce the type of something, like a class declearation, or a function declaration

#

generics are also helpful unless you are using js

quartz kindle
# warm imp Someone said it was

the idea is that with typescript you have more control over the types of things you are using, instead of letting javascript guess them

sharp geyser
sharp geyser
#

It also prevents stuff like say a function takes in a parameter of a string but you give it a number

#

so it will error before runtime

#

because types dont match

quartz kindle
sharp geyser
#

but thats the point of ts

#

it errors more because it has more typesafety

#

it forces you to think in terms of types rather than js's way of "ah yes this will work for now"

quartz kindle
#

javascript forgives your mistakes and tries to run anyway
typescript doesnt forgive you and wont let you run unless the code is actually good

sharp geyser
#

yup and thats the beauty of the type system

#

imo at least

#

js's way of thinking is flawed imo

warm imp
#

What about PY?

sharp geyser
#

py also has types yes

past field
#

i hear a lot about oregon

#

python i mean

quartz kindle
#

py is a different language altogether, it uses indentation as the main way to organize your code

#

so for example

sharp geyser
#

I love how thats the difference you point out, and not its biggest flaw

past field
#

tim knows all

#

i wanna be tim i swear to god i do.

sharp geyser
#

no you dont

#

that brain is a curse

#

you constantly want to optimize everything

#

the horror

#

the pain

#

I feel bad for tim

past field
#

i curse a lot so it works out.

sharp geyser
#

😔

quartz kindle
#
if(a) {
  b;
}

if(a) { b; }
``` these are both the same thing in js, it uses the brackets, regardless of spaces and new lines

```py
if a:
  b
``` with py the `b` needs to be exactly where it is, one line below and more to the right >>>
sharp geyser
#

tim is at the top of a lonely tower of optimization

sharp geyser
sharp geyser
#

"BUT THERE IS NO FUCKING SPACE"

quartz kindle
sharp geyser
#

if you want a strict language learn C++

quartz kindle
#

spaces and newlines have meaning, where in js they dont

#

js uses () and {} to define blocks and limits, py uses spaces and newlines instead, less typing but you need to pay more attention

warm imp
#

🙂

sharp geyser
warm imp
#

JS is so hard 😦

past field
sharp geyser
#

Ah yes the beauty of JS

quartz kindle
#

otherwise js is one of the easier languages out there

warm imp
sharp geyser
#

JS is easy if learned the right way

quartz kindle
#

if you want to learn programming, be prepared to spend at least a few months learning

#

just like you would when learning a foreign language

#

for example french or italian

warm imp
sharp geyser
#

all depends on your conviction

#

If you go into it not wanting to spend the time to learn it it will take longer

#

but if you sit down and take the time to learn it, you will acheive great results

warm imp
#

For months on end

sharp geyser
#

If you dont want to spend the time to learn

#

programming is not right for you

#

Programming is not something you learn over night, or quickly

quartz kindle
#

when learning a foreign language, how do you start? you dont read a book in french to learn french

#

you start with the basics, basic grammar rules, basic words and their meanings

warm imp
#

Yeahhhh

sharp geyser
#

😏

quartz kindle
#

lmao

#

read a book in jsfuck then

sharp geyser
#

no

#

cuz I value my time

warm imp
sharp geyser
#

a few

warm imp
warm imp
sharp geyser
#

I know JS

#

Rust

warm imp
sharp geyser
#

and some c++

sharp geyser
#

It just sticks after a while

quartz kindle
sharp geyser
#

I don't memorize the entire langauge by heart no

#

but I know the basics

#

and I know how to google what I dont know

#

every language shares the basics for the most part

warm imp
#

So there is var | let | const

sharp geyser
#

Strings, Ints, Bools

warm imp
#

Var is variable so like numbers right?

sharp geyser
#

don't use var

warm imp
sharp geyser
#

var has some issues perserving scope (or whatever its called)

quartz kindle
#

for example, most languages have variables, most languages have if else conditions, most languages have loops
there are a lot of things that programming languages share, they just do it a little different, with different keywords, different syntaxes

sharp geyser
#

let is for variables you want to be mutable meaning you can reassign the values of

#

const = constant

#

meaning it will ALWAYS be that value you set

#

it cannot be reassigned

warm imp
#

Yeah

sharp geyser
#

so you can do

let a = 5;
a = 7
console.log(a) // 7
#

but you cant do

const b = 5;
b = 7; // errors here because b is a constant
console.log(b);
warm imp
#

Yeah

#

So let can be changed and const can't

#

Makes sense now

sharp geyser
#

yup

#

var is special

#

it doesn't respect scope

#

or recognize scope

warm imp
#

What's scope?

sharp geyser
#

I can give you an example

#
const a = 5;
function b() {
  const c = 6;
}
console.log(a) // 5
console.log(c) // Will error because C is defined inside the scope of a function
#

Basically scope is like a boundary

#

Anything defined inside that function, cannot be used outside of it

quartz kindle
#

there are 3 types of scopes, global, function and block

sharp geyser
#

a is a global scope

#

c is a function scope

#

and

{
  // block scope
}
#

iirc

quartz kindle
#
// this is the global scope

function abc() {
  // this is a function scope
}

if() {
  // this is a block scope
}
sharp geyser
#

yo ucan also make a separate scope inside stuff right

#

like

#
function abc() {
  let a = 5;
  {
    let b = 6;
  }

  console.log(a + b) // will error because b is defined in its own scope
}``` right tim?
#

or am I mixing up languages

quartz kindle
#

yup

sharp geyser
#

😔

#

basically anything inside of {} is its own scope

#

it separates whats inside from whats outside

warm imp
#

So in a ping command what would i use?

sharp geyser
#

wdym?

#

depends on how your commands are setup

quartz kindle
#

thats like asking "now that i know how to say dog and cat in french, how do i read a french book?"

warm imp
#

Like I do /ping bot will say Pong

sharp geyser
#

it'd be either a block scope or a function scope

sharp geyser
#

what are yo uasking tho mate

warm imp
#

What scope would I use?

sharp geyser
#

depends

#

but it'd be either block scope or a function scope

quartz kindle
#

discord.js is a big big program created to help you connect with discord

warm imp
quartz kindle
#

discord.js is the one that tells you what you should use

sharp geyser
#

discord.js is a library

warm imp
#

Yoy would get a error if you use a wrong one?

quartz kindle
#

a library is a big piece of javascript code that someone else wrote and you can use by downloading and installing it

sharp geyser
#

its a collection of code that helps you make something

#

ima go tho so ima let tim explain any other questions oyu have

#

bye guys

quartz kindle
#

lmao nooo

#

stay

warm imp
#

Lol

quartz kindle
#

i g2g

warm imp
#

Lmao

sharp geyser
#

I am not letting you make the excuse of leaving me here

#

I knew it'd come soon

warm imp
#

All good

#

Don't worry

pine willow
warm imp
#

Yoy guys can leave

sharp geyser
#

shut up sky

warm imp
#

🙂

pine willow
sharp geyser
pine willow
warm imp
pine willow
#

Nuh uh

#

Whats the Issue at all

warm imp
sharp geyser
#

I still dont even know the issue myself

#

Cause we aren't going to teach you how to program

#

thats up to you

#

All we do is guide you in the problems you face while programming

warm imp
#

But yoy guys are amazing teachers

pine willow
#

Oh he doesnt have a bot yet?

warm imp
pine willow
sharp geyser
#

you have to be reliant on your own self

warm imp
sharp geyser
#

We are all volunteers here in this channel

#

We help when and where we can

pine willow
#

Yuh

sharp geyser
#

Best resource I can give you

#

It teaches a lot about JS

pine willow
#

Use brainfuck

#

Better

sharp geyser
#

sky

#

stop

pine willow
#

Sorry

sharp geyser
#

we don't troll new people in this channel

pine willow
#

Mb

#

Use the js Tutorial

warm imp
#

I understand some of it

#

But not all

#

Kinda

#

It's like 75% I don't know

sharp geyser
#

keep at it

#

With enough patience you can learn anything if you put your mind to it

quartz kindle
#

xD

sharp geyser
#

Anything you dont understand ask here

warm imp
warm imp
sharp geyser
#

Cognitive bias in which incompetent people tend to assess themselves as skilled

#

Its the peak of mount stupid stuff

warm imp
#

Oh

sharp geyser
#

Point is, its terrible to assess yourself in such a broad way

#

You are a beginner

quartz kindle
sharp geyser
#

its expected that it wont make sense to you at all

sharp geyser
quartz kindle
#

:^)

sharp geyser
#

😭

#

not wrong tho

#

Swear learning language development makes me think im in that valley of despair

pine willow
#

Programming spawned in my Head

quartz kindle
#

your head spawned in programming

warm imp
pine willow
#

Idfk i understood everything so fast

sharp geyser
#

your spawning in head programming

sharp geyser
#

there is still a lot you dont know

warm imp
sharp geyser
#

trust me bro

pine willow
#

Yes i know

warm imp
sharp geyser
#

Programming is something you will never master

warm imp
sharp geyser
#

There will ALWAYS be something to learn

pine willow
#

400

warm imp
#

Just wondering no hate at all

sharp geyser
#

I bet even the actual language developers of the langs you guys use don't know their own language fully

#

💀

warm imp
quartz kindle
#

400... um... speed

pine willow
#

Not the best

warm imp
sharp geyser
pine willow
#

1 month ago

warm imp
#

How already 400

sharp geyser
#

He has gained 400 servers in one month

#

thats faster than most multi purpose bots

warm imp
#

Fr

sharp geyser
#

and all his bot does is play tictactoe

warm imp
#

Lmao

sharp geyser
quartz kindle
#

its not a multipuropose bot thats why

#

multipurpose bots suck

pine willow
#

Multi purpose is bd

#

Bs

sharp geyser
#

indeed

pine willow
sharp geyser
#

I am working on a 10/10 bot idea rn

#

Its going to reach thousands of servers

#

:D

warm imp
#

Was it hard it make a tictac toe bot?

sharp geyser
#

his uses ai

quartz kindle
#

a good specific purpose bot will take you far, provided its not too niche

pine willow
#

Not really

#

It wasnt that hard to code the Basics

sharp geyser
#

It will still reach millions of servers

#

trust

quartz kindle
#

hueheuhue

warm imp
#

The only thing i don't understand is the index that trips me up

quartz kindle
#

mine is hard stuck for like 2 years now

sharp geyser
#

remake it

#

in C++

#

trust it helps

warm imp
#

Lol

quartz kindle
#

lel

sharp geyser
#

idk how but hte magical effect of C++

quartz kindle
#

gonna use D++

pine willow
#

Use brainfuck

sharp geyser
#

makes bos succeed

sharp geyser
#

its amazing

warm imp
#

Do people even make Bots in that?

sharp geyser
#

yes

#

D++ is actually better than discord.js

warm imp
#

Ok

#

It is?

#

How

pine willow
#

Time to recode TicTacToe

sharp geyser
#

D++ is made in C++ which is more memory efficient

warm imp
quartz kindle
#

it stands for Discord++

sharp geyser
#

So once you get into those thousands of servers most people go libless or swap to a more memory efficient language

#

like C++

pine willow
quartz kindle
sharp geyser
pine willow
#

Mee6 Python

#

Trash bot

sharp geyser
#

it'd be cheaper buying more server room than hiring devs that specialize in C++ or some other language

quartz kindle
warm imp
sharp geyser
#

JS only becomes a limitation at large amounts of servers

#

Mac's bot uses 16gb of ram

quartz kindle
pine willow
sharp geyser
#

and they spend hundreds on servers to keep it running

#

💀

quartz kindle
pine willow
#

Imagine

warm imp
sharp geyser
pine willow
warm imp
quartz kindle
sharp geyser
pine willow
sharp geyser
#

It makes enough money to sustain you most of the time

sharp geyser
#

Those dyno devs make BANK

warm imp
#

Fr

#

Or saphriaa

sharp geyser
#

sapphire is a shit bot ngl

pine willow
#

@warm imp all of my Stuff is hosted on my local Servers

sharp geyser
#

oh god

quartz kindle
#

my bot made me a whole 30 bucks last month

#

im rich

sharp geyser
#

giving sky another chance to flex his servers

pine willow
#

No

sharp geyser
#

At this point sky mentioning servers should be banned

pine willow
#

Serwers

quartz kindle
#

sewers

sharp geyser
#

Why you living in the Sewers?

warm imp
sharp geyser
#

what are you doing here

warm imp
quartz kindle
sharp geyser
#

no idea what that is

quartz kindle
#

old ass mmorpg

#

from 2005

sharp geyser
#

makes sense

#

oh wait that game

#

nvm I do know what that is

#

god haven't played that in AGES

quartz kindle
quartz kindle
#

forget about slash commands for now

#

play around with text commands instead

#

for example !ping

pine willow
#

Pong! 9ms

quartz kindle
#

you will need to configure something in your discord app tho

#

but its gonna be much much easier to start with

#

and you're gonna have a better time understanding whats going on

#

also forget about handlers and all that crap

warm imp
quartz kindle
#

i would recommend not using handlers for now

#

stick the the basics

pine willow
#

Everything has to be sorted otherwise I can't cope

warm imp
#

Same

pine willow
#

If i would put my Stuff in 1 File hell no

#

Brain would die