#๐Ÿงฉ-plugin-development

1 messages ยท Page 37 of 1

abstract spire
#

oh nono i'm just making hop on bloons desktop edition

potent fox
#

Then simple regex match lmao

timid hinge
#

could still be vulnerable if the developer has a skill issue

potent fox
#

match steam://launch or smthn

#

As long as you are not idiot

#

It wont cause RCE

abstract spire
#

alright this worked thanks

potent fox
#

Np

steep vapor
#

๐Ÿ”ฅ

wooden dragon
#

is that your own chat app?

stiff cargo
#

so it would seem :o

#

very neat

wooden dragon
#

discord but better

stiff cargo
#

looks like its written in kotlin which is in fact not electron making it substantially better

proud cargo
#

ve_sad me building my client with electron

stiff cargo
#

:(

stiff cargo
proud cargo
#

eh its actually okay

#

i can crank out an .appimage with 80mb

stiff cargo
#

no idea if its any good

#

but rust = good

#

:D

proud cargo
#

tauris good but its missing stuff

#

electron isnt all that bad i swear

stiff cargo
#

๐Ÿ‘€

wooden dragon
#

it do be a bit odd

dry patio
#

how do i refresh the settings

#

i have a button for removing a certain field

#

easiest awy would be just refresh everything

cedar olive
#

make a force updater on the parent and just use that lol

dry patio
#

idk what that means cuz idk shit about react

cedar olive
#

vencord has useForceUpdater()

#

it's a simple hooks that re renders the component when you call the function it returns

dry patio
#

sounds great

amber basin
glass oracle
#

thats cool

#

i want to do a rust rewrite but rust gui isn't there yet

wooden dragon
#

whoa

#

custom discord client

glass oracle
#

i mean it's not the first but cool nonetheless

wooden dragon
#

I srsly wonder how people interface with discord using fully custom clients

glass oracle
wooden dragon
#

sounds like a bot lol

glass oracle
#

although maintaining a custom client is a very respectable feat, unlike maintaining a bot api framework (like djs, dpy, etc) you get no official docs or updates, you have to figure out everything in your own (previous implementation and datamining helps a lot tho)

glass oracle
#

but it should be fine as long as the custom client is sending proper headers

cedar olive
#

X-Super-Properties moment

glass oracle
#

i love x-super-properties

#

you send a request to /experiments, you get 50~90 experiments, add xsp now you get 100+

glass oracle
amber basin
#

i didnt see that anywhere in userdoccers

cedar olive
glass oracle
cedar olive
#

and doing some other stuff

glass oracle
#

not merged yet

#

i still have to document 30~ gateway op codes

proud cargo
amber basin
#

GUH

#

blehhh

glass oracle
amber basin
#

OH WAIt

glass oracle
#

i could but i'll have to setup mitm

amber basin
#

is it just the gateway identify packet

#

i have that

proud cargo
#

no its on all http requests

glass oracle
#

yes it's the properties key from identify

#

that too

proud cargo
#

ah nvm i misunderstood

amber basin
glass oracle
amber basin
#

will that suffice or do i need more

#

guh

proud cargo
#

YOURE PASSING INTENTS???

amber basin
#

I USED TO

#

i was following discord docs lmao

#

im dumb

cedar olive
#

โ˜ ๏ธ dont

glass oracle
#

dont do intents

#

users dont need intents

amber basin
#

ohhh ik why i did it

proud cargo
#

you need capabilities too

amber basin
#

i assumed intents atleast helped specify what the client could parse so discord doesnt break their old clients

#

wait is that capabilities

proud cargo
#

ya

#

but theyre different

amber basin
#

ah

glass oracle
#

and yeah capabilities they're in userdoccers

amber basin
#

can i make a vendetta plugin to yoink x-super-properties from the http client

#

thatd be easiest i fink

glass oracle
#

but mobile is no different

glass oracle
glass oracle
amber basin
#

i dont wanna setup a proxy waaaaaaa

glass oracle
#

a a a test

#

oh right yeah

#

but i think plugin would be more effort :3

#

you can also use the debugging socket feature and get props directly

amber basin
#

yeah thats what i meant

glass oracle
#

one sec let me start wsa

amber basin
#

sorry for confusion

#

wait im on m1 i can just run mobile discord

#

aaaaaaaaaa

glass oracle
#
{ os: 'Android',
  browser: 'Discord Android',
  device: 'windows_x86_64',
  system_locale: 'en-US',
  client_version: '200.7 - rn',
  release_channel: 'canaryRelease',
  device_vendor_id: '07d966d0-79ac-49fe-9fbd-8f12daa750d8',
  browser_user_agent: '',
  browser_version: '',
  os_version: '33',
  client_build_number: 200207,
  client_event_source: null,
  design_id: 0 }

meow

amber basin
#

a

glass oracle
#

guh why's my vendetta not on light theme

amber basin
#

Oh I got it

glass oracle
#

๐Ÿ‘

amber basin
#

tysm

glass oracle
#

i haven't documented design_id but there's 0 and 1

amber basin
#

how would i get a device_vendor_id

#

ah

glass oracle
#

i am not really sure (maybe hard code them)

#

iirc design_id corresponds to 0 -> normal, 1 -> tabs v2
i might be wrong

proud cargo
amber basin
#

oki

glass oracle
proud cargo
#

it doesnt work

#

windows packet on linux endpoint

glass oracle
#

guhhh

#

i could probably fix that

proud cargo
#

really thinking about just saying im a windows client rn, cba to wait

proud cargo
glass oracle
proud cargo
#

while youre here erm,, just to make sure, im not missing anything am i? planning on replacing props with api endpoint onesso ignore those

glass oracle
#

oh yeah native_build_number is windows only thing, so if you're not sure what os it is i'd recommend avoid that

proud cargo
#

is it? oh wow

glass oracle
#

and you can add these for linux

#

(env.XDG_CURRENT_DESKTOP || "unknown") + "," + (env.GDMSESSION || "unknown")

proud cargo
#

can but cba because not required

glass oracle
#

you could just hard code it to be unknown,unknown if os is linux trolley

glass oracle
proud cargo
amber basin
#

android, desktop, and ios's

#

is that good?

glass oracle
#

lgtm

#

also @amber basin you should set client_version and client_build_number dynamically

#

because discord has some goofy experiment filters based on client versions and api sometimes shits itself if it doesnt match the filter

amber basin
#

this is a completely custom client

#

im not using discord experiments

glass oracle
#

for example packs experiment had a minimum client version filter, any client sending version lower than that couldn't use packs api

amber basin
#

oh hell

#

okay

#

@austere mauve will you smite me if i send a server link

rocky jackal
#

I wanted to start making vendetta plugins but I didn't know where to start from

amber basin
#

no response means okay totally

glass oracle
dry patio
#

oops ๐Ÿ’€

#

i dont think im using the force update thing properly

viral roost
#

how are you using it

rocky jackal
dry patio
glass oracle
dry patio
#

i google searched and it might have to do with useState?

viral roost
dry patio
#

oops

#

idk what else to do ๐Ÿ˜ญ

#

i dont know shit about react

viral roost
#

best approach is probably to separate the return value of the map into it's own component

#

so you can use hooks properly

#

then just pass a and i as props to it

dry patio
#

grrr

#

hate object oriented programming

glass oracle
#

you should refer to textreplace plugin

#

it has similar functionality

dry patio
#

i have the tab open

#

just didnt wanna oop

#

guess im left w no choice unless i do something silly

stiff cargo
#

:))))

glass oracle
#

rust ๐Ÿ™

dry patio
#

rust โ€ผ๏ธ

#

my favorite

stiff cargo
#

rust is amazing

#

but it feels kinda OOP to me

steep vapor
#

where are the duke

stiff cargo
#

i can make structs with implementations

#

basically OOP

#

:)

glass oracle
#

but fungus named lang good :nod:

dry patio
#

thats like the tenant of oop

glass oracle
#

i love the concept of traits in rust

stiff cargo
#

which are sorta similar

dry patio
#

which are awesome

stiff cargo
#

very much so

dry patio
#

lets go i found a way without needing a component

#

๐Ÿ’€

viral roost
#

so approvestare

dry patio
#

more readable than a class

viral roost
#

no one mentioned classes, function components are a thing (and you are using them right now)

dry patio
#

idk what that means

#

i dont konw java script

viral roost
#

bleh

#

if what you did works it works

dry patio
#

well

#

it doesn't work

#

oops

#

im not out of ideas though

wooden dragon
#

given that polymorphism in rust uses composition over inerhitance

#

in terms of normal data structures yeah

#

its basically just moving the methods into their own semantic scope

dry patio
#

works now

#

yay

#

its not THAT ugly

wooden dragon
wooden dragon
dry patio
#

the only thing i need now is

#

i wanna make the delete button an icon

#

how do i reduce the amount of space here

#

oh i guess NONE

#

didnt even work

rocky jackal
#

I think it's an icon style

dry patio
#

i just did an override of padding

#

hacky but works i guess

#

i found something called Hovers in the Button type thingy

#

but i cant find a way to use it

#

want the buttons to be black and then go red when u hover

rocky jackal
#

the icon seems norm-

#

oh

#

You have to use button size icon

dry patio
#

will try

#

didnt change anything

rocky jackal
#

wait

#

bruh

dry patio
#

padding override works so i guess it stays like that

#

still wondering about the hover thing tho

rocky jackal
#

yeah the icon size makes the padding equal on all sides

dry patio
#

ok it works now

rocky jackal
#

(the button is stretched because of the flex container)

dry patio
#

yeah i dont konw how to do the hover thing

#

still a good ui though

rocky jackal
#

the hovers is an unused type

#

at least from what I can see

#

only those props are used

#

and available

viral roost
#

yeah hover effects need to be done in css

#

do you already have a css file for your plugin?

rocky jackal
#

The textinput component interface in vencord only has an option for a prefix component

#

what is this

#

how??

#

(experiments search)

#

same with discovery, though it's using a custom component there

#

it also doesn't work

amber basin
#

a story

dry patio
#

i have one single tsx file

#

i guess i could add a css file

topaz crest
#
import json
import asyncio
import websockets

async def send_heartbeat(ws):
    payload = {
        "op": 1,
        "d": None
    }
    res = await ws.send(json.dumps(payload))
    return res

async def keepalive(ws):
    print("Starting Heartbeat")
    await send_heartbeat(ws)
    while True:
            await asyncio.sleep(10000 / 1000)
            print("Sending Heartbeat")
            await send_heartbeat(ws)
            

async def standby_bot(token, status, activity):
    gateway_url = 'wss://gateway.discord.gg/?v=10&encoding=json'

    async with websockets.connect(gateway_url) as ws:
        res = await ws.recv()
        if json.loads(res)["op"] == 10:
            print("Hello Recieved")

        print(res)
        
        asyncio.create_task(keepalive(ws))


        payload = {
            "op": 2,
            "d": {
                "token": token,
                "properties": {
                    "os": "linux",
                    "browser": "disco",
                    "device": "disco"
                },
                "intents": 3276541
            }
        }

        await ws.send(json.dumps(payload))
        res = {"op":11}

        while res["op"] == 11:
            res = await ws.recv()
            res = json.loads(res)

        print(res)
        
        res_gateway_url = res["d"]["resume_gateway_url"]
        session_id = res["d"]["session_id"]
        bot_id = res["d"]["user"]["id"]

        print(f"Recieved Authentication from Discord {res_gateway_url}, {session_id}")

    async with websockets.connect(res_gateway_url + "/?v=10&encoding=json") as ws:
        res = await ws.recv()
        if json.loads(res)["op"] == 10:
            print("Hello Recieved!")
        
        a = await send_heartbeat(ws)
        print(a)

        asyncio.create_task(keepalive(ws))

        payload = {
            "op": 6,
            "d": {
                "token": token,
                "session_id": session_id,
                "seq": None
            }
        }

        await ws.send(json.dumps(payload))

        res = {"op":11}
        last_res = res
        while True:
            while res["op"] == 11:
                res = await ws.recv()
                res = json.loads(res)
            if res != last_res:
                last_res = res
        
                opcode = res["op"]
                
                if opcode == 0:
                    event_type = res["t"]
                    event_data = res["d"]
                    if event_type == "READY":
                        print("Bot Ready!")
                    elif event_type == "MESSAGE_CREATE":
                        message_content = event_data.get("content")
                        channel_id = event_data.get("channel_id")

                        print(f"Received a message in channel {channel_id}: {message_content}")
                    else:
                        print(event_type)
                else:
                    print(opcode)
                    print(res)


if __name__ == '__main__':
    token = "a"
    status = 0
    activity = "testing"
    
    asyncio.get_event_loop().run_until_complete(standby_bot(token, status, activity))
#

discord keeps giving me op code 9

#

and im not sure what I did wrong

#

issue is with the 2nd reconnection part

#

i dont think I did it correctly, but as far as I checked, it matched discords docs

amber basin
#

@topaz crest reset ur token lmao

topaz crest
#

i really dont care

#

its a test bot anyways

ashen axle
#

are you getting d = true or false

topaz crest
#

its just giving me code 9

#

invalid credentials

#

for the reconnect

ashen axle
#

your hearbeat interval needs to be set to heartbeat_interval provided in the HELLO payload
in regards to the opcode 9, you need to start a new session instead of trying to resume

#

try this

import json
import asyncio
import websockets

seq = None  # keep track of sequence

async def send_heartbeat(ws, interval):
    global seq
    while True:
        await asyncio.sleep(interval / 1000)  # sleep for the interval provided by HELLO
        payload = {
            "op": 1,
            "d": seq
        }
        await ws.send(json.dumps(payload))
        print("Heartbeat sent")

async def standby_bot(token, status, activity):
    global seq
    gateway_url = 'wss://gateway.discord.gg/?v=10&encoding=json'

    while True:
        try:
            async with websockets.connect(gateway_url) as ws:
                # receive HELLO payload to get the heaartbeat interval
                response = await ws.recv()
                response = json.loads(response)
                if response["op"] == 10:  # HELLO payload
                    heartbeat_interval = response["d"]["heartbeat_interval"]
                    asyncio.create_task(send_heartbeat(ws, heartbeat_interval))

                
                payload = {
                    "op": 2,
                    "d": {
                        "token": token,
                        "properties": {
                            "os": "linux",
                            "browser": "disco",
                            "device": "disco"
                        },
                        "intents": 3276541
                    }
                }
                await ws.send(json.dumps(payload))

                
                while True:
                    response = await ws.recv()
                    response = json.loads(response)
                    seq = response.get("s", seq)

                    if response["op"] == 9:  # INVALID_SESSION
                        print("Invalid session, reconnecting.")
                        break

                    # (Your event handling code goes here)

        except websockets.exceptions.ConnectionClosed:
            print("Connection closed, reconnecting.")
            # breakoff before connect
            await asyncio.sleep(5)

if __name__ == '__main__':
    token = "here"
    status = 0
    activity = "testing"

    asyncio.get_event_loop().run_until_complete(standby_bot(token, status, activity))
#

@topaz crest

topaz crest
#

alright

#

nothing happens

#

blank console

#

i see heartbeats being sent

#

but nothing else

ashen axle
#

are you on python 3.7+?

#

also do you have a new bot token cz i saw you accidentally showed it here earlier

#
import json
import asyncio
import websockets

seq = None

async def send_heartbeat(ws, interval):
    global seq
    while True:
        await asyncio.sleep(interval / 1000)
        payload = {
            "op": 1,
            "d": seq
        }
        print(f"Sending heartbeat: {payload}")
        await ws.send(json.dumps(payload))
        print("Heartbeat sent")

async def standby_bot(token, status, activity):
    global seq
    gateway_url = 'wss://gateway.discord.gg/?v=10&encoding=json'
    print(f"Attempting to connect to {gateway_url}")

    while True:
        try:
            async with websockets.connect(gateway_url) as ws:
                print("Connected to the gateway")
                response = await ws.recv()
                print(f"Received response: {response}")
                response = json.loads(response)
                if response["op"] == 10:
                    heartbeat_interval = response["d"]["heartbeat_interval"]
                    print(f"Received HELLO payload, heartbeat interval: {heartbeat_interval}")
                    asyncio.create_task(send_heartbeat(ws, heartbeat_interval))

                payload = {
                    "op": 2,
                    "d": {
                        "token": token,
                        "properties": {
                            "os": "linux",
                            "browser": "disco",
                            "device": "disco"
                        },
                        "intents": 3276541
                    }
                }
                print(f"Sending IDENTIFY payload: {payload}")
                await ws.send(json.dumps(payload))

                while True:
                    response = await ws.recv()
                    print(f"Received event: {response}")
                    response = json.loads(response)
                    seq = response.get("s", seq)
                    
                    if response["op"] == 9:
                        print("Invalid session, reconnecting.")
                        break
                    
        except websockets.exceptions.ConnectionClosed as e:
            print(f"Connection closed with exception: {e}")
            await asyncio.sleep(5)
        except Exception as e:
            print(f"An unexpected exception occurred: {e}")

if __name__ == '__main__':
    token = "your_token_here"
    status = 0
    activity = "testing"
    
    asyncio.run(standby_bot(token, status, activity))

here's a version with some prints so you can see whats happening

#

if ur on 3.7+ try asyncio.run() instead of get_event_loop().run_until_complete()

#

@topaz crest if that dont work lmk and i can try something else :)

topaz crest
#

alr

#

i think that worked

#

it spammed my console with server info about servers the bot is in

ashen axle
#

ay nice

ashen axle
topaz crest
#

alright ty

dry patio
#

how do i actually add css to my plugin

green vessel
#

is html "coding" enough for this channel

dry patio
#

maybe idk

green vessel
#

helpful response

dry patio
#

i dont own the server

proud cargo
green vessel
#

helo how can i
a. reduce this weird spacing
b. add some padding here without adding padding to everything solved by adding padding-left and padding-right to body

#

my css

body {
  background-color: #7d8491;
  font-family: Figtree;
}

.container {
  display: flex;
  align-items: center;
  justify-content: center;
}

img {
  border-radius: 10px;
}

.text {
  font-size: 20px;
}

.extraspace {
  padding-bottom: 100px;
}
#

each section (image and text on a row) is in its own container div

dry patio
#

ok guys i have completely update keyword notify ui

#

its live

ashen axle
ashen axle
green vessel
#

ah i see thanks

#

i broke it harder

#

i'll fix tomorrow

#

i changed my mind and wanted it to just be
text > image
text > image
etc

#

img {
  border-radius: 10px;
  right: 0px;
  position: absolute;
}

.text {
  font-size: 20px;
  position: absolute;
  left: 0px;
}

i prolly understood wrong but this is what i did

proud cargo
#

they are cooking

ashen axle
#

i didnt even know 3.12 was real

proud cargo
#

sadly i have it installed

#

cant build node modules at all hypershiggy

ashen axle
#

i figured i was an edgecase for using 3.11 as it is

#

WAIT 3.12 HAS PER-INTERPRETER GIL

#

true concurrent execution of python threads

#

at long last

proud cargo
#

and itll still be slower than js

ashen axle
#

LMFAO yea

dull magnet
#

ducko jumpscare

glass oracle
lofty crypt
#

owo

stuck falcon
#

do y'all recommend rspack or esbuild

#

or do they have different purposes

radiant olive
#

quick question: what would be a way to programmatically grab plugin settings and then apply the values to patches or are settings the wrong way to go about that?

dull magnet
dull magnet
stuck falcon
radiant olive
# dull magnet two options: - `$self.settings.store.someSetting` after putting return of define...

Hmm, guess I'm missing something

const options = generateOptions(soundmap);
export const settings = definePluginSettings(options);

function generatePatches(soundmap: Record<string, any>) {
    var patches: Array<{ find: string, replacement: { match: RegExp, replace: string; }; }> = [];

    for (const key in soundmap) {
        console.log(`${key}: ${soundmap[key]} `);
        const soundValue = self.settings.store.soundmap[key];
        console.log(soundValue);

        if (soundValue) {
            patches.push({
                find: `${soundmap[key]}:function(e,t,n){\"use strict\";e.exports=n.p+`,
                replacement: {
                    match: /n\.p\+"\w+\.mp3"/,
                    replace: `\"${soundValue}\"`
                }
            });
        }
    }
    return patches;
}
dull magnet
#

using rspack only really makes sense if you want to make use of webpack plugins

#

wtf is that

#

why would u do it like that

#

that's a really bad way of doing that - and i think there is already a sound changer plugin pr

stuck falcon
#

i see

#

thank you!

simple folio
#

going by the name im gonna assume that rspack is a rust implementation of webpack

stuck falcon
#

it is i guess

dull magnet
#

yes

stuck falcon
#

neubrutalism looks so cool

radiant olive
lofty crypt
proud cargo
proud cargo
#

uhhh

#

because

stuck falcon
#

guh

glass oracle
lofty crypt
#

look at these rustlovers

timid hinge
lofty crypt
#

do they rust?

stiff cargo
versed osprey
quaint cipher
#

Is it ok to use UserUtils.getUser multiple times every time I render a custom modal or should I store the user objects instead of IDs to avoid calling getUser every time?

#

or I could getUser the IDs once at plugin load then use those until restart

proud parrotBOT
quaint cipher
#

i guess its fine

near aurora
#

discord uses swc and not rspack iirc

#

swc is speedy web compiler

#

partial webpack replacement that was more mature at the time of migration that rspack

cedar marsh
#

They switched to rspack recently no?

#

That's what broke everything

near aurora
#

maybe, i didn't know about that

#

sounds real

#

that's why i said iirc

cedar marsh
near aurora
#

nice, okay

#

well, i only had to fix the classes with the class fixer thingy for my theme

#

and vencord was fixed overnight before i got to experience it broken

#

like, css stuff anyway

turbid spruce
#

how could i add some text right here im making a timestamp plugin for peoples local times and woudl like to see the current time on their profile

#

i figured i would need to do something like this tsx { find: ".useCanSeeRemixBadge)", replacement: { match: /(?<=onContextMenu:\i,children:).*?\}/, replace: "$self.renderUsername(arguments[0])}" } },

#

straight from the "ShowMeYourName" plugin

#

but im an amateur when it comes to js/ts

lofty crypt
lofty crypt
keen summit
#

Anyone know why my gltf models aren't showing up when I serve from dist and serve it, but works perfectly fine when I'm running from bun run dev? I'm using three js and vue 3 btw

#

Dist vs dev

amber mantle
#

i may try my first plugin idea again

versed osprey
amber mantle
#

message notes port
it was fairly simple i just stopped because my brain couldn't get around manipulating discord's message component

#

i ahould aleep

versed osprey
#

That's sounds nice

proud cargo
worn atlas
#

hello look to my profile

chrome elbow
#

no

amber mantle
#

dev loper

worn atlas
#

yeah is just a badge

#

to do that create a server

#

and go to google and type discord badge creator about me

#

click on the first link

#

and do the icon you want the text and the color

#

and import as badge.zip

#

and you will see 6 รฉmoji

#

if is 7 it will not work

#

and add the emojis on the server

#

and go to your settings

#

and go to profile

#

and go to about me

#

and click on รฉmoji

worn atlas
#

and do the badge

#

done

#

you have this

versed osprey
#

POV you are 12 and saw a no tts video on YouTube

worn atlas
#

WARING: Only work if you have Nitro

versed osprey
#

Lol

#

This kid thinks we don't know shit

#

He just watched a notts vid and now he is a master at discord lol

clever pasture
#

lol

worn atlas
#

hi

versed osprey
#

No

clever pasture
#

why is the e an "รฉ"

versed osprey
#

รˆ

#

ร†

clever pasture
#

ฤ™

versed osprey
#

รŠ

worn atlas
#

what

clever pasture
versed osprey
dawn timber
#

You spelled devloper wrong, genius

worn atlas
#

This is a โ€ซ message โ€ซ

steady knot
#

dรฉvlopรฉr

dawn timber
#

coulda looked it up-

#

the fuck

versed osprey
#

You are just making a joke of yourself

dawn timber
#

Is it using unicode chars?

wooden dragon
dawn timber
#

It feels like unicode fuckery

versed osprey
dawn timber
#

Called it

#

I'm smarter than I look

versed osprey
#

Ya u are

dawn timber
#

Thanks

versed osprey
#

Np hypershiggy

dawn timber
#

HOLD ON

#

LMFAO

#

you saying I look dumb?

worn atlas
#

h

#

h

#

hhhhhhh

versed osprey
dawn timber
versed osprey
#

No you look smart but you are smarter that how u look

glass oracle
#

right to left embedding

#

indicates the change in direction of text layout

proud cargo
wooden dragon
#

I made the best website

keen summit
keen summit
glass oracle
# keen summit nope

so i guess your dev script is serving files from dist and the folder in which your gltf files are in
whereas you are only serving from dist

keen summit
glass oracle
#

wdym

#

i mean it has to serve files from somewhere

keen summit
#

Well I could try putting it in public/assets I guess

#

it's static

#

ok that worked

#

well that was a dumb problem

proud storm
#

anyone got some dnd bypass pluging, so you still get desktop notifications

austere mauve
#

its called online mode

#

they want notifs

#

on dnd

#

i hav a plugin to bypass it for specific ppl

proud storm
proud storm
austere mauve
#

this plugin is ancient but i never pr'd bc katlyn wanted to port cutecord

#

maybe i should try that

proud storm
#

yeah

woven lagoon
#

hey fellas, im a total noob when it comes to even the simplest of code but im trying to make a .bat file that will find and launch discord on any pc, i have it working for mine but i can't really test it outside of mine and sandboxie isn't really working as intended for it

#

if anyone would be willing to test it would only require closing discord and running it. it should be compatible with both vanilla and vencord discord since it's the same file name

#

shouldnt have to close discord in tray or anything but if anyone knows better do share

#

also if anyone has been having issues with their vencord discord shortcuts getting deleted everytime theres an update this may help, that's what it's designed to do, should also work as a startup program but havent tested that yet either, though that's not so important to me in terms of functionality

amber basin
#

I LOVE CACHING I LOVE CACHING

#
# holy shit thats alot of caching
- name: Cache AppAndroid
  if: matrix.os == 'ubuntu-latest'
  uses: actions/cache@v3
  with:
    path: appAndroid/build
    key: ${{ runner.os }}-appAndroid-${{ hashFiles('appAndroid/**') }}
- name: Cache AppDesktop
  uses: actions/cache@v3
  with:
    path: appDesktop/build
    key: ${{ runner.os }}-appDesktop-${{ hashFiles('appDesktop/**') }}
- name: Cache genesisApp
  uses: actions/cache@v3
  with:
    path: genesis/app/build
    key: ${{ runner.os }}-genesis-app-${{ hashFiles('genesis/app/**') }}
- name: Cache genesisCommon
  uses: actions/cache@v3
  with:
    path: genesis/common/build
    key: ${{ runner.os }}-genesis-common-${{ hashFiles('genesis/common/**') }}
- name: Cache genesisDiscordApi
  uses: actions/cache@v3
  with:
    path: genesis/discord/api/build
    key: ${{ runner.os }}-genesis-discord-api-${{ hashFiles('genesis/discord/api/**') }}
- name: Cache genesisDiscordClient
  uses: actions/cache@v3
  with:
    path: genesis/discord/client/build
    key: ${{ runner.os }}-genesis-discord-client-${{ hashFiles('genesis/discord/client/**') }}
- name: Cache genesisApi
  uses: actions/cache@v3
  with:
    path: genesis/genesisApi/build
    key: ${{ runner.os }}-genesis-genesisApi-${{ hashFiles('genesis/genesisApi/**') }}```
#

now it wont spend 5m building genesisApi (a 76 line file) for ios every time

austere mauve
#

cache fans when their build mysteriously stops working on ci but not locally

amber basin
#

if that happens just delete the cache and rerun

amber basin
#

bun is a functional package manager

ashen axle
# woven lagoon
@echo off
SETLOCAL EnableDelayedExpansion

:: Define the common paths where Discord might be installed.
SET "discord_paths=C:\Users\%username%\AppData\Local\Discord\Update.exe --processStart Discord.exe
C:\Program Files\Discord\Discord.exe
C:\Program Files (x86)\Discord\Discord.exe"

:: Attempt to start Discord from the known paths.
FOR %%D IN (%discord_paths%) DO (
    IF EXIST "%%D" (
        START "" "%%D"
        GOTO End
    )
)

:: If Discord wasn't found in the common locations, perform a system-wide search.
echo Discord not found in common paths. Performing a system-wide search, please wait...

:: Use where command to search in Program Files directories. Avoiding system directories for speed.
FOR /R "C:\Program Files" %%F IN (Discord.exe) DO (
    SET discord_path=%%F
    GOTO LaunchDiscord
)
FOR /R "C:\Program Files (x86)" %%F IN (Discord.exe) DO (
    SET discord_path=%%F
    GOTO LaunchDiscord
)
FOR /R "C:\Users\%username%\AppData" %%F IN (Discord.exe) DO (
    SET discord_path=%%F
    GOTO LaunchDiscord
)

:LaunchDiscord
IF DEFINED discord_path (
    START "" "!discord_path!"
    GOTO End
)

echo Discord executable not found on the system.
GOTO End

:End
ENDLOCAL
dull magnet
#

why did u send bro chatgpt code

woven lagoon
#

Nah see I tried chatgpt and it exported the message it was unable to find the file every time

#

Though I will admit I had it regenerate the prompt so many times it did end up having some generally good points

#

You can't really ask it to generate code persay but you can ask it how to solve a problem so you can look up how to do the thing

#

Where you usually just wouldn't even know what to google

#

Or I dunno maybe it's just way better at c# or something evil like that than batch

#

(I don't know if c# ie actually that bad or not I've never touched it I just know it's a common joke that it's bad or something)

keen summit
amber mantle
#

i just ask it to rephrase docs lol

mighty topaz
#
import { ApplicationCommandInputType, ApplicationCommandOptionType, Argument, CommandContext, sendBotMessage } from "@api/Commands";
import definePlugin from "@utils/types";
import { UploadHandler } from "@webpack/common";
import { findByPropsLazy } from "@webpack";

const UploadStore = findByPropsLazy("getUploads");
const DRAFT_TYPE = 0;

const UploadHandler = findByPropsLazy("showUploadFileSizeExceededError", "promptToUpload") as {
    promptToUpload: (files: File[], channel: Channel, draftType: number) => void;
};

async function downloadVideo(url: string): Promise<Uint8Array> {
    try {
        const response = await fetch(url);
        const arrayBuffer = await response.arrayBuffer();
        const uint8Array = new Uint8Array(arrayBuffer);

        return uint8Array;
    } catch (error) {
        console.error("Error downloading video:", error);
        throw error;
    }
}

async function convertAndPostYoutubeVideo(url: string, channelId: bigint, cmdCtx: CommandContext) {
    try {
        // Debuggin with bot message
        await sendBotMessage(channelId, { content: "Downloading video. This may take a moment..." });

        const payload = {
            url,
            vCodec: "h264",
            vQuality: "720",
            aFormat: "best",
        };

        const response = await fetch("https://co.wuk.sh/api/json", {
            headers: {
                "Accept": "application/json",
                "Content-Type": "application/json",
            },
            method: "POST",
            body: JSON.stringify(payload),
        });

        const result = await response.json();

        // Debug download link with bot message to make sure this shit is working
        await sendBotMessage(channelId, { content: `Download link: ${result.url}` });

        // Upload the video - this shit is not working
        let videoArray = await downloadVideo(result.url);
        let videoFile = new File([videoArray], "youtube_video.mp4", { type: "video/mp4" });
        
        UploadHandler.promptToUpload([videoFile], cmdCtx.channel, DRAFT_TYPE);

        // Debug with bot message - I am getting this message but no upload
        await sendBotMessage(channelId, { content: "Video downloaded and ready for viewing!" });

    } catch (error) {
        // Log the error with bot message
        await sendBotMessage(channelId, { content: `Error converting or posting the video: ${error}` });
    }
}

async function executeYoutubeConverterCommand(opts: Argument[], cmdCtx: CommandContext) {
    const youtubeURL = opts.find(opt => opt.name === 'url')?.value as string;

    if (!youtubeURL) {
        await sendBotMessage(cmdCtx.channel.id, { content: "Please provide a valid YouTube URL." });
        return;
    }

    try {
        await convertAndPostYoutubeVideo(youtubeURL, BigInt(cmdCtx.channel.id), cmdCtx);
    } catch (error) {
        await sendBotMessage(cmdCtx.channel.id, { content: `Error converting or posting the video: ${error}` });
    }
}

export default definePlugin({
    name: "converter",
    description: "Handles YouTube video conversion and posting",
    authors: [
        {
            id: 214127950109343745n, // Replace with the actual author ID
            name: "Chokitu",
        },
    ],
    patches: [],
    commands: [
        {
            inputType: ApplicationCommandInputType.BUILT_IN,
            name: "youtubeconverter",
            description: "Converts and posts a YouTube video",
            options: [
                {
                    name: "url",
                    description: "URL of the YouTube video",
                    type: ApplicationCommandOptionType.STRING,
                },
            ],
            execute: executeYoutubeConverterCommand,
        },
    ]
});
#

okay, so I am trying to make a plugin that will grab a video url as parameter and will upload it as a discord video. I wrote most of the code by myself, but by the time I didn't know what to do anymore, I got the petpet code, threw on chat gpt and told chat gpt to try to mimic the upload method, probabily thats why it didn't work, but if anyone has points on why this shit is not working I would love some suggestions:

#

I am also giving up on doing the utube url check, cuz apparently this api also works for instagram reels, twitter and other stuff

#

it was chat gpt idea to use uint8array btw, since buffer and blob werent working either

chrome elbow
wooden dragon
#

how do I make it so the urls are more split apart?

glass oracle
#

or whatever amount you want

wooden dragon
#

whoa thanks

glass oracle
#

youre welcome

glass oracle
#

@quaint cipher

import { Database } from "bun:sqlite";

const db = new Database(":memory:");
db.run("PRAGMA journal_mode = WAL;");

db.run(`CREATE TABLE guilds (id STRING PRIMARY KEY, data STRING);`);
db.run(`INSERT INTO guilds VALUES ('1', '{"id": "1", "name": "test"}')`);
db.run(`INSERT INTO guilds VALUES ('10', '{"id": "10", "name": "bleh"}')`);
db.run(`INSERT INTO guilds VALUES ('2', '{"id": "2", "name": "meow"}')`);

console.log(db.query("SELECT * FROM guilds").all());
console.log(db.query("SELECT * FROM guilds ORDER BY id DESC LIMIT 2").all());
console.log(db.query("SELECT * FROM guilds WHERE id = '1'").get());
quaint cipher
#

oh idk

glass oracle
#

lol

amber basin
#

IS THAT A BUN

#

DISCORD CLIENT

#

also why the fuck are you using sqlite just to store json

pure temple
chrome elbow
#

what

pure temple
#

the man says "shiggy" i swear

chrome elbow
#

lol it's shige

glass oracle
glass oracle
# amber basin DISCORD CLIENT

nah not a discord client, something else about datamining
if i ever make a discord client it'll be in rust ๐Ÿ™

dull magnet
nova wraith
#

maybe whis cost so many strings of your profile using all features of 3y3.
hm... i want whis...
whos know how to import custom plugins using custm CSS?
bc i hate BD
|| decorations ||
|| effects ||

#

O_O

#

what happened

#

what have he done

wooden dragon
#

why are the links not rendering?

glass oracle
wooden dragon
#

OMG

#

I swear to god that return wasnt in the arrow function in the tutorial

#

thank you

glass oracle
#

posts.map((post) => { return <a href={post.slug}>{post.data.title}</a> }) or posts.map((post) => <a href={post.slug}>{post.data.title}</a>)

wooden dragon
#

yeah I made it into the () variant now

dull magnet
wooden dragon
#

I forgor how js worky

dull magnet
#

dummy forgor

#

right in rust u don't need it do u

#

just omit semicolon and it returns

wooden dragon
#

yeah

#

it optional for the last element

dull magnet
wooden dragon
#

I haven't tried that

stiff cargo
dull magnet
#

now make Blogs a heading

wooden dragon
#

blogs heading?

glass oracle
#

i assume this

gusty maple
#

I assume so as well

wooden dragon
#

oh

wooden dragon
#

footer

green vessel
#

h3 span[class*="username_d30d99"]:before {
visibility: visible;
position: relative;
margin-right: -1805px;
background: linear-gradient(to right, #4e5dd6, #e224c5);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
why doesnt this change my name color anymore?

glass oracle
#

classnames change

wooden dragon
#

cant you do username_ check

#

and ignore the hash

green vessel
keen summit
#

please fix

wooden dragon
#

nuh uh

hybrid dune
#

how should you format ternaries over several lines, and should I even be using a ternary for this

austere mauve
#

the ternary is redundant

#

reduce right will return x if its empty

#

but youd ```
x == y
? a()
: b()

hybrid dune
#

thanks

#

it's slightly faster to do this comparison than to perform reduceright on an empty array, which is why I done it

austere mauve
#

its slightly faster to not use js

hybrid dune
#

true but gamified coding fun

dull magnet
#

wtf is reduceRight

#

i never saw that before

austere mauve
#

reduce but the other way

proud cargo
#

reduceMiddle

austere mauve
#

reduces lina

dull magnet
#

the only good way to format ternaries is

condition
    ? x
    : y
#

anything else is criminal

amber basin
#

yeah

#

what about

dull magnet
#

or inline if very short

amber basin
#
condition ?
 x : y```
#

:3

dull magnet
#

DIE

#

blocked

amber basin
#

NOOOOOOOOOOOOO

austere mauve
#
cond1 ? x :
cond2 ? y :
cond3 ? z :
w
#

im right

#

@dull magnet shut up u did this too

#

esp w ts types

proud cargo
austere mauve
#

tabs horror

proud cargo
#

space indentation is a crime

#

pyramid -> :3

austere mauve
#

tab isnt whitespace?

proud cargo
#

ah mb

austere mauve
#

dum void

amber basin
#

hey void run this find and replace

proud cargo
#

ill reduceRight you to ashes rini

amber basin
#

guh it ran on my message

#

s/ / /g

#

u will

proud cargo
hybrid dune
#

tab bad bc notepad displays it wrong /s

austere mauve
#

tab fans when no consistent line length limit

proud cargo
amber basin
#

objects can have key order??

proud cargo
#

ya

#

i mean

#

iirc its not defined but most engines will give them to you in some sort of fixed order

amber basin
#

oh ew

austere mauve
#

its insertion order usually

dull magnet
#

it formats ts types so weird

dull magnet
#

hop off class

proud cargo
#

mald

proud cargo
amber basin
#

WTF

#

why is it a tab + a space

#

ew

austere mauve
#

mjxing tabs and spaces

#

see

#

SEE

proud cargo
#

see what

amber basin
#

easy solution

#

use spaces

proud cargo
#

id rather not thank you

austere mauve
#

tab fans wben i stab them

proud cargo
dull magnet
#

disable whitespace indicators

#

looks bad

proud cargo
#

shut up

#

no one asked for your opinion

stiff cargo
#

Theyโ€™re right thoughโ€ฆ

dull magnet
#

i turned on whitespace indicators once in mine

#

made me puke instantaneously

stiff cargo
#

I donโ€™t really see the point of them?

proud cargo
#

ok and?

austere mauve
#

my ide is the pretties

proud cargo
#

opinions on pudding light aquarium

austere mauve
#

puke

proud cargo
#

i should use it just to spite you

hybrid dune
#

Can barely see the green and grey text, if the text colours were changed I could see it being okay

#

Also smells like outlook

proud cargo
#

jesus christ dark high contrast is painful to look at

amber basin
#

rate my themes

stiff cargo
versed osprey
#

is there a good way to get the amount of characters that have been entered into the msg text box?

amber basin
stiff cargo
proud cargo
keen summit
#

but also looks cool

amber basin
amber basin
proud cargo
#

yikes,,

amber basin
dull magnet
#

it's funny that they allow this on their official store

stiff cargo
#

Thereโ€™s a watermark?

mighty topaz
# dull magnet

Sorry, next time I'll post it without the chat alteration

stable ridge
#

Which watermark tho

wooden dragon
#

never seen a watermark

minor jolt
#

Got screensharing to work on my steam deck plugin comfy

glass oracle
glass oracle
#
const SelectedChannelStore = Vencord.Webpack.findStore("SelectedChannelStore");
const DraftStore = Vencord.Webpack.findStore("DraftStore");
const DraftType = Vencord.Webpack.findByProps("DraftType").DraftType;

const currentChannelId = SelectedChannelStore.getCurrentlySelectedChannelId();
const currentChannelDraft = DraftStore.getDraft(currentChannelId, DraftType.ChannelMessage);
const length = currentChannelDraft.length
#

DraftType values

ApplicationLauncherCommand: 3
ChannelMessage: 0
FirstThreadMessage: 2
Poll: 4
ThreadSettings: 1
amber mantle
#

theres DRAFT_UPDATE every time you update the text input

#

sorry its DRAFT_CHANGE

glass oracle
#

oh then you can use that too if you need realtime updates

#

my method is ondemand

rocky jackal
#

why did I do this

glass oracle
#

we DO NOT need another electron app

rocky jackal
#

lmfao

versed osprey
wooden dragon
#

it does look good

#

but please

glass oracle
#

aight how do i make it so that data->categories is sorted by id

stiff cargo
glass oracle
#

i have no clue about sql, i'm just adding random keywords hoping it works blobcatcozy

stiff cargo
#

ah lol

#

Iโ€™d just try SELECT * FROM meow ORDER BY id

#

Iโ€™m pretty lost at sql aswell though so uhh

glass oracle
#

nah i dont want to sort the rows by id, rather the id of categories prop in data

glass oracle
#

getting somewhere

glass oracle
#

i got it! kinda

#

now i need to figure out how to plug that into my insert or replace statement

stiff cargo
#

woo!

glass oracle
#
WITH modified AS (
    SELECT id, json_insert(
        coalesce(
            data,
            $data
        ),
        '$.categories[#]',
        json($category)
    ) as data
    FROM meow
    WHERE id = $id
)

INSERT OR REPLACE INTO meow
SELECT id, json_set(data, '$.categories', json(categories)) as data
FROM modified, (SELECT json_group_array(json(value)) as categories FROM (
    SELECT value
    FROM modified, json_each(data->'categories')
    ORDER BY json(value->>'id')
))

this is definitely the most complex sql i'll ever write

#

it works!!

rocky jackal
#

remaking github's UI, yay

#

I also don't think they're using any frameworks

worthy frost
#

okay, so ive narrowed down the issue. and imma try a solution, if it doesnt work, ill follow up :p

#

okay, as far as i can tell, my solution works.

#

it (obviously) ISNT a good idea to check if a member has a role in a guild, before checking if that user is a member of said guild.

granite jasper
quaint cipher
#

hi uh is there an easier way to get this or is this ok

Vencord.Webpack.find(e=>e.default?.prototype?.hasOwnProperty?.("getAudioContext")).default.prototype.supports

i want to get this module

#

that code works but not sure if its ok to use

#

nvm only works on vesktop and not discord for some reason

#

got this that works both in discord and vesktop, is it ok?

let id = Vencord.Webpack.findModuleId("getAudioContext");
Vencord.Webpack.wreq(id).default.prototype.supports
#

nevermind. doesnt seem like im doing this right

dry patio
#

how do i get the patch finder thingy back

#

its gone now

#

on dev versoin

proud cargo
#

build with --watch flag

dry patio
#

epic update to keyword notify coming soon

#

it will highlight messages

#

with the keyword

#

ima try

#

camila

worthy frost
#

woah

rocky jackal
woven lion
#

please dont use other ui frameworks in vencord plugins (assuming thats what this is)

glass oracle
woven lion
#

ah in which case

#

full steam ahead

rocky jackal
#

no worries

#

I'm just messing around with github's UI

#

The app actually looks really good so far

clever pasture
#

if a=b then what is c

glass oracle
clever pasture
#

thx

glass oracle
#

writing horrible rust

stiff cargo
glass oracle
#

it's actually not fear

wooden dragon
#

is there a way to make a css only light/dark mode switch?

wooden dragon
#

fluent

dull magnet
#

with :has()

wooden dragon
#

hello vee

#

did you fix your sleep schedule

#

also themks

#

I asked chatgpt with your hint cuz I have no idea where to start

#

please dont kill me vee

#

hmmI want to have 3 mutual exclusive buttons tho thats probably only possible in js

stiff cargo
#

Radio buttons

#

Pure html

wooden dragon
#

holy shit

#

I love you board

#

thanks

stiff cargo
#

:3

wooden dragon
#

now I can make cool buttons for light/dark/system

stiff cargo
#

3 way toggle switch

#

Probably a fun css challenge

wooden dragon
#

I love how my pfp image disappears cuz of the ghitub rate limit

stiff cargo
#

I made uncheckable radio buttons once with css

#

Was fun

wooden dragon
#

uh I use astro in dev mode rn and astro has a cool feature that executes js during comptime so it tries to request github api every content update / page reload druing dev

dull magnet
wooden dragon
#

cuz I dont give it an auth token

stiff cargo
wooden dragon
#

THAT WORKS

stiff cargo
#

lol

dull magnet
wooden dragon
stiff cargo
#

The way you are doing it is pretty cool though

#

Just have to change the username and it could be someone elseโ€™s portfolio page lmao

wooden dragon
#

it back yippee

stiff cargo
dull magnet
#

blah bla bla blah blup bleh blah ... meow mrrp miau meow

Thank you for reading! โ™ฅ

wooden dragon
dull magnet
#

:has has bad browser support

wooden dragon
stiff cargo
#

Firefox loves has

#

:)

wooden dragon
stiff cargo
#

Afaik

wooden dragon
#

wait how do I remember the theme selection

#

I may be forced to use js

stiff cargo
#

lol

wooden dragon
#

I mean jsut a page transition could mess things up

#

:c

stiff cargo
#

I store the state in localstorage

wooden dragon
#

forced to use js reeee

stiff cargo
#

Not sure if thatโ€™s ideal though

stiff cargo
#

To a light mode version of that page

#

No JS

wooden dragon
#

/en/light/blog/myfirstblogpost is spooky

stiff cargo
#

lmao

#

But paranoid anti JS people will be happy

#

Or you just make a light mode

#

Everyone has dark reader anyway right?

wooden dragon
#

I try to make it 100% js free

#

except for view transitions I guess cuz it doesnt remove features if its not there

dull magnet
wooden dragon
dull magnet
#

i mean you can still do theme toggle with pure css, but use js to persist it

#

then if users don't allow js it just won't persist

wooden dragon
#

omki

#

good idea

stiff cargo
#

Unless theyโ€™ve recently fixed has

wooden dragon
#

gosh view transitions make page transitons so smooth

wooden dragon
#

why is css so hard

stiff cargo
wooden dragon
#

this is so cursed and idk what it even does

#

(I just stole it from somehwere)

keen summit
#

Because it has terrible defaults

dull magnet
#

more than just that

keen summit
#

border box?

dull magnet
#

the only reset there is the margin

keen summit
#

ic, why would you need a flex col the body though

rocky jackal
proud cargo
wooden dragon
#

so I dont have overflow on the home page

#

will probably break until I go other 100 but it works for now

stiff cargo
wooden dragon
#

is using <a> like this cursed?

desert meadow
#

not enough styles

wooden dragon
#

im prototyping

desert meadow
#

clean and lite

stiff cargo
wooden dragon
#

I love astro

#

making content based grids is so easy with it

rocky jackal
#

(Ik it's astro, but they look extremely simmilar)

#

this was stupidly simple to make

#

github sure know how to use react

austere mauve
#

horrible

#

why would u make the entire desc a link

wooden dragon
austere mauve
#

oh

#

still cursed id only make the title clickable

wooden dragon
#

hmm omki

pure temple
rocky jackal
#

colorways but on github

dull magnet
#

i do the same

wooden dragon
#

it messes up user-select :c

dull magnet
#

huh how so

wooden dragon
#

cuz it now drags the url

austere mauve
wooden dragon
#

vee lets be horrible together

stiff cargo
#

Aww :3

wooden dragon
#

oh thsnks

#

im now going the full css way with js persistance

glass oracle
trail ginkgo
#
async function ping(defer: () => Promise<unknown>, send: (content: InteractionContent) => Promise<unknown>) {
    const start = Date.now()
    await defer()
    const end = Date.now()

    await send({
        content: `Pong! \`${end - start}ms\``,
        components: [{
            type: ComponentTypes.ACTION_ROW,
            components: [createPingBtn({})],
        }],
    })
}

const createPingBtn = defineButton({
    name: "ping",
    label: "Ping again",
    style: ButtonStyles.PRIMARY,
    async handler(interaction) {
        await ping(() => interaction.deferUpdate(), content => interaction.editOriginal(content))
    },
})

defineCommand({
    name: "ping",
    description: "Check if the bot is alive",
    async handler(interaction) {
        await ping(() => interaction.defer(MessageFlags.EPHEMERAL), content => interaction.createFollowup(content))
    },
})

@austere mauve rate this api

austere mauve
#

virus

#

is this slash commands

trail ginkgo
#

defineCommand is

#

defineButton is message components

oblique lark
#

i like how js devs replace named params with just taking an object as the argument

mighty topaz
#

How do I hide a command from showing?

#

my code is working as I want, but it's showing the /command

#

nvm, found out

dull magnet
#
async function fetchDonorPfps(
    githubToken: string,
    after: string | null = null
) {
    const query = `
      {
        user(login: "Vendicated") {
          sponsors(first: 100, after: ${JSON.stringify(after)}) {
            pageInfo {
              hasNextPage
              endCursor
            }
            nodes {
              ... on User {
                avatarUrl
              }
            }
          }
        }
      }
    `;

    const res = await fetch("https://api.github.com/graphql", {
        method: "POST",
        headers: {
            Authorization: `bearer ${githubToken}`,
            "User-Agent":
                "vencord.dev (https://github.com/Vencord/vencord.dev)",
        },
        body: JSON.stringify({ query }),
    });

    if (!res.ok)
        throw new Error(
            `Failed to fetch sponsors: ${res.status}\n${await res
                .text()
                .catch(() => "Unknown Error")}`
        );

    const { data, errors } = (await res.json()) as SponsorData;
    if (errors)
        throw new Error(
            "Failed to fetch sponsors:\n" + JSON.stringify(errors, null, 4)
        );

    const {
        pageInfo: { hasNextPage, endCursor },
        nodes,
    } = data.user.sponsors;

    const avatarUrls = nodes.map(n => n.avatarUrl);
    if (hasNextPage)
        avatarUrls.push(...(await fetchDonorPfps(githubToken, endCursor)));

    return avatarUrls;
}
#

horror

dull magnet
#

this is cursed

#

skia canvas only has toDataURL()

#

i just fetch the data url xd

smoky basin
#

can u not turn it into a blob a saner way

dull magnet
#

fetch is the most straight forward way

smoky basin
#

i guess

#

wacky

dull magnet
#

otherwise i need to like trim prefix, atob, etc

#

then make response myself

#

if i fetch() i can literally just directly return its response

smoky basin
#

sure

dull magnet
#

horror

#

404

smoky basin
#

FEAR

dull magnet
#

how do i parse an image with canvaskit

#

i dont think cloudflare workers support the Image class

smoky basin
#

does canvaskit even work on workers

dull magnet
#

yes

#

it uses wasm

smoky basin
#

uh huh

dull magnet
#

OHHH

#

canvas.decodeImage

#

thank god

trail ginkgo
#

thats so real of u

dull magnet
#

it seems to work

#

okay im getting ECONNRESET lmao @trail ginkgo

#

so ig i cant just fetch all 200 urls at once

trail ginkgo
#

RIP

#

oh also

dull magnet
#

sane code actually

trail ginkgo
#

rate my interaction api

trail ginkgo
dull magnet
#

i mean its just browser canvas api xd

trail ginkgo
#

ya its good that its normal u cant even tell

#

/gen

dull magnet
#

wait

#

i just tried again and i dont get ECONNRESET

trail ginkgo
#

its probably just unreliable

dull magnet
smoky basin
#

W

trail ginkgo
#

wait huge but

dull magnet
#

why does it look so bad tho

trail ginkgo
#

the scaling interpolation lol

dull magnet
#

WHY DID THAT GUY STEAL MY PFP

dull magnet
austere mauve
#

now make clickable pngs

dull magnet
#

would using a power of 2 yield better result

trail ginkgo
#

LOL

#

LOL

#

there doesnt seem to be a straight forward like

#

.drawImageFilter = "bilinear"

#

but

#

this is crazy

dull magnet
austere mauve
dull magnet
#

doesnt look better with power of 2

trail ginkgo
#

draw image at half original res

#

then get data url and draw it again at next half

trail ginkgo
#

until ur at target res

dull magnet
#

shithub has size param

#

firer

trail ginkgo
#

nah nah nah

#

iteratively halve it

#

so much cleaner

dull magnet
#

NO

trail ginkgo
#

๐Ÿ”ฅ

#

send real grpah soon

#

also how do u choose the size of the grid

dull magnet
#

FIREEEE