#🧩-plugin-development

1 messages · Page 64 of 1

maiden ruin
#

How do I wait until a dependency is initialized before running my code?

jagged briar
#

Ideally you don’t add dependencies for a plugin

#

What is your plugin and what is the dependency

maiden ruin
dull magnet
#

elaborate

#

what are u trying to do

maiden ruin
#

I'm trying to get the album art of the song playing, get the most prominent color from it then set it as a theme or set the secondary background of discord as the color

dull magnet
#

just import the store

bitter root
#

Noobie question. I'm getting the following error when trying to access someone's Display name. This is an excerpt of what I'm trying to do

Property 'globalName' does not exist on type 'User'.

import { Message } from "discord-types/general";

let recentmessage: Message;

// ...

console.log(recentmessage.author);
const displayName: string = recentmessage.author.globalName;```


When checking with a console.log, I notice that field actually does exist, which is weird. But sometimes it also evals to null.
frosty otter
bitter root
#

Oh so globalName == server nickname? How do I get the display name? Is that possible

frosty otter
#

afaik it depends, on how you are fetching the user

#

are you just getting it from the author attribute from a message?

bitter root
#

yes I think so

kind pike
#

i tried "@webpack/common" to no avail

hushed loom
#

like this

kind pike
#

nvm im dumb

viral roost
#

just ignore the error

#

multiple plugins already do that

bitter root
#

Is there a more modern/better way or do I just have to add a fallback for null cases

#

globalName == whatever name shows up in the current server right¿

signal goblet
#

migrating a db from someone who hates the world to my stuff (thank god its on github) feels amazing

balmy sky
#

You can just type the user as any

amber basin
#

nop

#

// @ts-expect-error discord-types is outdated

#

place that comment the line before it

ripe smelt
#

does anyone know if it's possible to use a patch to change the status icon SVG? I could only find the SVG for each respective status icon getting called twice, and changing it seems to do nothing

dull magnet
#

you can do it with css

ripe smelt
#

see I tried doing that, but changing your own status seems to scrape the status icons on your profile of the color and svg attributes, so changing your own status will override your own status icon to the default SVG, and the attributes only seem to reappear for your status icons when the element that contains your status icon is refreshed (like closing and opening members tab or changing channels)

cedar marsh
#

@dull magnet
I cant figure out how to patch wreq.f.css
for some reason patchHelper can't ever find it?

dull magnet
#

you can't regex patch the webpack loader

cedar marsh
#

how did you intend for me to hook into it then?

flint bronze
#

this currently sounds like "you should do this. also doing 'this' is impossible"

dull magnet
#

🐵 🩹

cedar marsh
#

I will not

#

how do you even monkeypatch on vencord

muted thunder
#

How tf

frosty otter
#

but the property needs to be exported

#

there also is
findByCode and stuff

cedar marsh
#
findByCode('ChunkLoadError') // => null
frosty otter
#

yes

#

doesn't seem to find anything

cedar marsh
#

-# yes so please don't suggest things that you know don't work
meow

dull magnet
#

it's wreq.f.css

frosty otter
cedar marsh
dull magnet
cedar marsh
#

Vee going from whatever the numbers that spits out to /assets/[...].css is an extraordinary pain in the ass and more husk than a mutationObserver will ever be

cedar marsh
#

you clearly know what this code does while I don't

#

do it yourself :3

dull magnet
#

i don't know anything

#

i just read code

cedar marsh
#

what on earth are the validations happening above that though

proud parrotBOT
cedar marsh
#

I had no idea what I was even looking at

cedar olive
#

you can also refer to this if you want

#

every prop of wreq documented

#

it explains what wreq.k is

#

and wreq.f.css

dull magnet
cedar olive
#

lmaoo grammar

dull magnet
cedar marsh
#

sorry I currently can't think of any clean code that does what you want

dull magnet
cedar marsh
#

thanks

cedar olive
#

try to start doing it and ask for help if you cant progress

#

I will help you if you need

cedar marsh
#

okay

#

I would like to implement in a way that can be used by multiple components, so I am thinking of implementing like

cssUtil.ts

export const newStyleListeners: [(styles: string) => void] = [];
const orig = wreq.f.css
wreq.f.css = function() {
    // call each listener in newStyleListeners with the result css
    // point to orig
}

Then plugins can opt in with

start() {
  newStyleListeners.push((styles) => {
    ...
  })
} 
dull magnet
#

but a mutationobserver would probably also be okay

#

as long as u only watch head

#

and do it proerpyl

cedar marsh
#

is there anything wrong with current implementation then?

cedar olive
#

it's honestly pretty easy to do with wreq.f.css though

cedar marsh
#

because it does only watch head currently

cedar olive
#

send me your current implementation with observer

proud parrotBOT
# cedar marsh https://github.com/CodeF53/Vencord/blob/ClientThemeStyleListener/src/plugins/cli...

cssUtil.ts: Lines 17-30

export function newStyleListener(callback: (styles: string) => void) {
    const observer = new MutationObserver(mutations => {
        for (const mutation of mutations) {
            for (const node of mutation.addedNodes) {
                if (!(node instanceof HTMLLinkElement) || node.rel !== "stylesheet")
                    continue;

                parseStyleLinkNode(node).then(callback);
            }
        }
    });

    observer.observe(document.head, { childList: true });
}
cedar olive
#

okay one second

cedar marsh
proud parrotBOT
cedar olive
#

you don't lol

#

you can but no need to

cedar marsh
cedar olive
#

not an issue though since it's unlikely a chunk will get asked to be loaded more than once

#

pretty sure

#

let me just cook a way for a plugin to easily access wreq when it's loaded into vencord though

#

time for wreq listeners

dull magnet
#

whenevr u change channels

#

discord loads these

cedar olive
#

it was a guess honestly xd

#

however I think the way you are gonna do this is using the return value the promises argument of wreq.f.css

#

you can probably differ when a chunk is loading/loaded using it

cedar marsh
cedar olive
#

I meant to remove return

#

the value of the promises argument only

cedar marsh
#

promises seems like its always empty for me

cedar olive
#

yes cuz all of those are already loaded

cedar marsh
#
cssFunc = wreq.f.css
wreq.f.css = function(chunkId, promises, fetchPriority) {
  cssFunc.apply(this, [chunkId, promises, fetchPriority])
  if (promises.length === 0) return
  console.log(promises)
}

oh this works and is promising

#

I get you

cedar marsh
#

thanks

dull magnet
#

yes, it uses apply cause it has args as an array :p

#
  • .call when you have multiple arguments
  • .apply when you have an arguments array
cedar marsh
#

ahh

cedar olive
#

when a css is chunk is being loaded it returns a promise

#

that resolves when it's style tag is loaded

#

eh

#

mutation observer might be cleaner

cedar marsh
cedar marsh
cedar olive
#

you already have to do all of this just to monkey patch wreq.f.css as soon as possible

#

then you would have to see if promises is not empty

#

wait for all of them to resolve

#

obtain the full css path with wreq.p + wreq.k

#

fetch it and do all the blabla

#

and beforeInitListeners isn't even a thing anymore in future versions which means I would have to re-add a variation of it

cedar marsh
dull magnet
# cedar olive

false

function onWreqDefined(wreq: any) {
  onceDefined(wreq.f, "css", () => {
    const orig = wreq.f.css;
    wreq.f.css = function () {}
  })
}
cedar olive
#

true

#

but still lol

cedar marsh
#

I have spent 2 hours screwing with wreq.f.css and my brain hurts

dull magnet
cedar olive
#

even then it's being called twice

cedar marsh
#

evil

cedar olive
#

doesnt handle the calling twice but yeah

cedar marsh
#

vomit

cedar olive
#

in the end of the day it is what you want but is it worth

cedar olive
#

yep yep ik

#
const chunksLoading = new Set<string>();

function onWreqDefined(wreq: any) {
    beforeInitListeners.delete(onWreqDefined);

    onceDefined(wreq.f, "css", () => {
        const handleChunkCss = wreq.f.css;
        wreq.f.css = function (this: unknown) {
            const result = Reflect.apply(handleChunkCss, this, arguments);

            if (chunksLoading.has(arguments[0])) {
                return result;
            }

            chunksLoading.add(arguments[0]);

            if (Array.isArray(arguments[1]) && arguments[1].length > 0) {
                (async () => {
                    await Promise.all(arguments[1]);
                    chunksLoading.delete(arguments[0]);

                    console.log("css chunk", arguments[0], "loaded");
                    const cssFilepath = wreq.p + wreq.k(arguments[0]);

                    const css = await fetch(cssFilepath).then(res => res.text());
                    console.log(css);
                })().catch(() => { });
            }

            return result;
        };
    });
}

beforeInitListeners.add(onWreqDefined);
#

¯_(ツ)_/¯

#

that doesn't account for the initial css though

#

the base one

cedar marsh
#

neither does mutation observer

cedar olive
#

yikes

cedar marsh
# cedar olive ```ts const chunksLoading = new Set<string>(); function onWreqDefined(wreq: any...
// returns all of discord's native styles in a single string
// ! discord lazy loads css chunks, make sure to use newStyleListener as well
export async function getStyles(): Promise<string> {
    const out = "";
    const styleLinkNodes: NodeListOf<HTMLLinkElement> = document.querySelectorAll('link[rel="stylesheet"]');
    return Promise.all(Array.from(styleLinkNodes, n => parseStyleLinkNode(n)))
        .then(contents => contents.join("\n"));
}

// runs callback with styles of new style nodes added to the head
export function newStyleListener(callback: (styles: string) => void) {
    const observer = new MutationObserver(mutations => {
        for (const mutation of mutations) {
            for (const node of mutation.addedNodes) {
                if (!(node instanceof HTMLLinkElement) || node.rel !== "stylesheet")
                    continue;

                parseStyleLinkNode(node).then(callback);
            }
        }
    });

    observer.observe(document.head, { childList: true });
}

async function parseStyleLinkNode(node: HTMLLinkElement): Promise<string> {
    const link = node.getAttribute("href");
    if (!link) return "";

    return fetch(link)
        .then(res => res.text())
        .catch(() => "");
}

Feels nicer and has the inital css

cedar olive
#

like outside of your start()

cedar marsh
#

iirc that is forbidden

cedar olive
#

well yeah but you cant have a start at init and a start at domcontentloaded at the same time

cedar marsh
#

why don't I just start at init then?

cedar olive
#

you can

#

but obviously styles is going to be empty when that happens

cedar marsh
#

then we listen and develop css as stuff loads

cedar olive
#

yeah

cedar marsh
#

I will rewrite based on that then

maiden ruin
#

How do I import SpotifyStore in to my plugin? I tried doing

const store = await SpotifyStore;

then accessing the values stored but it always returns undefined or null

vast karma
#

How are you defining or importing SpotifyStore?

dull magnet
#

but yes show full code

ripe smelt
#

how would I replace this code? its the code that defines the masks for icons, I'm trying to replace them with custom masks

(s = "svg-mask-status-idle",
(0, a.jsxs)("mask", {
    id: s,
    maskContentUnits: "objectBoundingBox",
    viewBox: "0 0 1 1",
    children: [
        (0, a.jsx)("circle", {
            fill: "white",
            cx: .5,
            cy: .5,
            r: .5
        }),
        (0, a.jsx)("circle", {
            fill: "black",
            cx: .25,
            cy: .25,
            r: .375
        })
    ]
}))
#

tried this but it doesn't seem to work, so I'm probably doing something wrong:

patches: [
        {
            find: /s\s*=\s*"svg-mask-status-idle"/,
            replacement: {
                match: /s\s*=\s*"svg-mask-status-idle"/,
                replace: `
                    (s = "svg-mask-status-idle",
                    (0, a.jsxs)("mask", {
                        id: s,
                        maskContentUnits: "objectBoundingBox",
                        viewBox: "0 0 1 1",
                        children: [
                            (0, a.jsx)("path", {
                                fill: "white",
                                d: "M 0.5 0 C 0.224 0 0 0.224 0 0.5 C 0 0.776 0.224 1 0.5 1 C 0.776 1 1 0.776 1 0.5 C 1 0.224 0.776 0 0.5 0 M 0.125 0.5 C 0.125 0.293 0.293 0.125 0.5 0.125 C 0.707 0.125 0.875 0.293 0.875 0.5 C 0.875 0.707 0.707 0.875 0.5 0.875 C 0.293 0.875 0.125 0.707 0.125 0.5"
                            }),
                            (0, a.jsx)("circle", {
                                fill: "white",
                                cx: 0.5,
                                cy: 0.5,
                                r: 0.2
                            })
                        ]
                    }))`
            }
        },
vast karma
#

Just do that with css

ripe smelt
#

isn't patching be more reliable tho?

vast karma
#

Wait I don't know if you can use css to replace a circle with a path

#

But you're doing (at least) two things wrong here

#

You're replacing (s="svg-mask-status-idle",original svg) with ((s="svg-mask-status-idle",custom svg),original svg) which just doesn't do anything

#

And you're hardcoding the minified variable names, meaning it'll break within 48 hours

#

A better patch would be something like match: /"svg-mask-status-idle",/, replace: "$&$self.IdleIcon??"

ripe smelt
#

I probably should've read the patcher cheat sheet lol

#

thanks, I'll try that

ripe smelt
#

currently just trying to figure out how to make match: /"svg-mask-status-idle",/ more specific because patcher shows its matching the wrong thing

vast karma
#

/\i="svg-mask-status-idle",(?=\(0,\i.jsxs\))/ perhaps

jagged briar
#

messagelogger deleted messages should look like this

#

without all the subtext

mossy cargo
#

the closest you'll get to that is the background overlay option

dull magnet
jagged briar
#

didnt see that

vast karma
#

That's a similar style but not the same

jagged briar
#

its just barely different and its annoying me

mossy cargo
#

im using the red text but it doesn't currently work well for Subtext, Mentions, Codeblocks and Spoilers.

jagged briar
#

red background should be default imo cause you can actually tell if a message with just an image was deleted

mossy cargo
#

^ this

#

especially when i sent gifs from catbox

jagged briar
#

NOOO

#

my favorite gifs got reset

vast karma
#

Imo default should be red background plus folding

jagged briar
#

oh nvm theyre back

flint bronze
balmy sky
#

So i'm trying to make a plugin that saves channel drafts across sessions, my first idea is to save the draftstore data in the datastore on stop and load it on start. Does the draftstore have the functions for that? From what i can see there isn't a get all/set all function

dull magnet
#

Stores.DraftStore.getState()

#

but it already saves

#

to localStorage

#

it extends PersistedStore

#

which persists to localStorage

balmy sky
#

Oh it sorta works now

    async start()
    {
        const getData = await DataStore.get(dataStoreKey);
        if(!getData) return;
        
        localStorage.setItem("DraftStore", getData);
        
        DataStore.del(dataStoreKey);
    },
    async stop()
    {
        await DataStore.set(dataStoreKey, JSON.stringify(DraftStore.getState()));
    }
dull magnet
#

why are u doing this

#

im confused

#

it shouldnt be necessary

balmy sky
#

Am i stupid

#

Are drafts meant to persist across sessions?

dull magnet
#

wdym by session

balmy sky
#

Sorry, I mean if you type something in a channel (don't press send) and close/restart your client the draft disappears

hushed loom
#

@balmy sky your discord is broken, drafts persist for me

balmy sky
maiden ruin
ripe smelt
#

I'll try finding a workaround in the morning, I'm so tired I'll gonna be knocked out the minute I hit the hay

hushed loom
ripe smelt
#

the mobile status icon that shows up when someone is on mobile

hushed loom
#

oh, im really stupid

hushed loom
#

what is an ErrorBoundary

frosty otter
hushed loom
#

ah, makes sense

frosty otter
#

you can just search for ErrorBoundary in vencord src to see, how to use it

vast karma
#

Basically the react version of try/catch

red dove
#

Displaying Icons based on Permissions

haughty maple
#

is anyone else's discord canary installation fucked up rn? (Getting a popup that "Environment variables are not set." or the discord app just not loading at all.)

shrewd tundraBOT
haughty maple
#

venbotto i was just asking

ripe smelt
#

I wish native could directly print stuff to console

dull magnet
#

it can

flint bronze
#

there is nothing stopping you from printing to stdout with console in native

#

and theres nothing stopping you from calling a native function from renderer to get the webcontents and use executejavascript to send to logs there

flint bronze
hushed loom
#

is it possible to make two patches depend on eachother

flint bronze
#

replacement can be an array of replacements

#

set group to true for patches to not apply if one fails, useful if depending on another patch in the same module (for variables)

amber mantle
red dove
#

Hello, I have been working on a small thing for personal use to display an icon (specifically a silver crown but that is irrelavant for the point here) for users that have the Administrator Permission in a server. For that, I modified the forceOwnerCrown with the following patch:

    patches: [
        {
            find: ".PREMIUM_GUILD_SUBSCRIPTION_TOOLTIP",
            replacement: {
                match: /,isOwner:(\i),/,
                replace: ",_isOwner:$1=$self.isGuildOwner(e),"
            }
        }
    ],

so that I can sort users by permission they have and apply the owner crown to anyone I like. THIS ALREADY WORKS AND IS NOT MY ISSUE. However, I can only display the owner crown and nothing else because the function that plugin modifies (isOwner()) only returns a bool on wether or not to display the crown at all (or not). My general assumption is that there is a parent function that calls isOwner() to display all the information. Does anyone have this parent function and its dependencies for me to look at since I have no idea where to find it or how to decompile and deobfuscate the Discord Source Code

vast karma
#

Either extract the modules and grep, or set a breakpoint

red dove
languid field
#

does anyone know how I can see how many pings I have?

vast karma
#

Check where the ping counter gets the number from

languid field
#

I'm new to this I don't know where to look

balmy sky
#

React devtools inspect the home button

vast karma
#

In the corner

balmy sky
#

Then look at the code for the component

languid field
#

I tried to find docs for vencord but I didn't find anything useful here

Vencord Docs

Learn everything about Vencord development!

vast karma
#

Find the component, find its render function, find what it's getting the number from

languid field
#

which home button lol

viral roost
#

the one where it shows your pings?

languid field
#

hang on it might be my theme

#

you mean like from some server?

viral roost
#

like in this case i can say youre looking for ReadStateStore.getMentionCount()

#

but yeah use react devtools to see what stuff is used by a component

vast karma
#

Not useMentionCount? Or I guess it useStateFromStores it

viral roost
#

depends on what you need

#

or where you need it

languid field
#

how do i set up react devtools?
i thought i could do it on firefox so from my very limited knowlage on this i installed the plugin and it doesnt work
also in devtools on discord it doesnt appear with the components where it should

i might be really stupid lol, im sure im doing something very wrong

hushed loom
rose fiber
vast karma
#

I don't think react devtools works in firefox

languid field
#

extension also still shows the same thing

rose fiber
languid field
#

should i install a different browser like ungoogled chromium just to test?

rose fiber
#

just seems to not work on discord for some reason

languid field
#

they rewrote discord just for firefox 👍

#

ima get ungoogled chromium and shower, with my internet it should take about the same time :p

vast karma
#

I've never personally seen much use for react devtools, but lots of people swear by it

#

Native devtools have always been enough for me

hushed loom
vast karma
#

That's what I said yes

hushed loom
#

Horror

languid field
# vast karma That's what I said yes

i watched the video in pins and from what i can tell you just search thru the parts of the button looking for the one with the on click thing so it shouldnt be that hard to do the same thing without the react devtools right? if im not completely misunderstanding this (which i probably am)

languid field
dull magnet
#

how is it harder to set up 😭

vast karma
#

pnpm inject too stronk

languid field
#

ok on ungoogled chromium it works

#

is it possible that it uses ondragstart and ondragend or does it have to be onclick? i dont know enough web for this

#

because it's logical for ondraag to only happen after a bit

vast karma
#

On what, home button?

#

Why would home button use drag

languid field
#

server

#

shouldnt they be like the same tho

#

thing is i dont think home button actually displays a ping counter

#

cause when DMs pop up they pop up in a seperate thing

vast karma
#

That's true

languid field
#

alright i found a seperate on click

#

it brings me to this and now I dont know what I'm supposed to do ```js
e=>{
if (null == T)
;
else if ("string" == typeof T)
N.push(T);
else {
let {pathname: e="", state: t} = T;
N.push(e, t)
}
null != g && g(e)
}

#

surrounding code:

hushed loom
#

@languid field what are you trying to patch in the first place

languid field
#

get ping count

hushed loom
#

like total number of unread mentions?

languid field
#

yeah

#

then im thinking from there i might be able to create either a plugin or just a script i can shove into the console to connect to a waybar module so i can have my pings displayed cleanly

ripe smelt
#

how can I get the user's ID in a plugin?

hushed loom
#

theres a store for it iirc

iron epoch
vast karma
hushed loom
ripe smelt
#

ty

hushed loom
languid field
vast karma
#

I think the mobile app does show number of pings, so you could maybe try to find where that gets its info from

hushed loom
languid field
#

welp

hushed loom
#

maybe you could add a flux event for mention

languid field
#

omw to use http toolkit

#

wait small issue

hushed loom
#

because when you open discord you know how many mentions you have and then you could just keep track of the new ones

languid field
#

WAIT NO I CANT DO THISS NOOO

#

can anyone help me withh this please

hushed loom
#

with...

languid field
#

i cant connect my phone to wifi if it's connected to PC

#

i need somebody to use HTTP toolkit for me

hushed loom
languid field
#

i have no wifi

#

my PC is connected with a 6 meter usb extension cable

hushed loom
#

discords api is documented at https://discord.sex

Discord Userdoccers

You’ve found the Unofficial Discord User API Documentation! These pages are dedicated to showing you all the ways that you can use Discord to make cool stuff. It is not an official source of informati...

languid field
#

and im still barely connected

languid field
flint bronze
#

Object.values(findByProps("OPENID", "IDENTIFY")); SO GOOD

rose fiber
languid field
flint bronze
languid field
#

it does use root tho so people here might not be able to help :/

#

i cant root waydroid

#

so im just screwed ig

flint bronze
#

theres a bunch of alternatives

rose fiber
#

what's the difference to devtools network tab

languid field
flint bronze
#

from outside the container

languid field
#

yeah i tried then i failed and now i switched distros and dont have it installed so i give up on that

flint bronze
#

oh

#

you can always just add certificates from within the android environment

languid field
#

apps haven't been using user certificates for a long time

#

unless you like modify the app yourself

#

which i dont know how to do

languid field
#

i mean its safer that way ig

#

if somebody gets access to any of your devices they can just connect it to a mitmproxy instance with their certificate.
and you can do that on every OS except android (unless it's rooted)

flint bronze
languid field
#

this is just one of the easier things

#

a more complex one is to write malware (or skid malware from github xd)

flint bronze
#

im still wondering what the fuck "account.global_name.update" scope does

languid field
#

my guess is that it's user profile related

flint bronze
#

yes but

#

why is it listed here if it is "invalid"

viral roost
viral roost
#

you should try using the scope directly in the client instead of from a web browser

flint bronze
#

honestly it looks Dead anyway

#

look at wreq(713938).jW

#

not listed there

fallen sandal
#

ok ive implemented #🏥-vencord-support-🏥 message (literally just copied the whitelist code and changed a bool)

I could make a toggle for whitelist/blacklist cause from what i can imagine youd never want to blacklist something but also whitelist something else

#

the toggle makes more sense right?

balmy sky
#

Iirc other plugins that have a blacklist/whitelist just use a toggle

balmy sky
#

Looks good

fallen sandal
#

should I hide the import customrpc if its on blacklist

#

at that point youd just disable customrpc right

fallen sandal
#

also I renamed the internal setting from allowedIds to idsList which means users would lose the ids they set. Should I just leave the name as allowedIds even tho its not descriptive anymore

rocky falcon
clear parcel
#

oh ig global name is api terminology you might not know

#

global name = display name

balmy sky
#

Global name is still not in the fucking user types so like 5 of my plugins error

amber mantle
#

ts ignore u love

flint bronze
#

why would that be a permission that can be granted though

#

well

#

it was (?)

fickle jetty
#

is there a way to create an optional plugin dependency or do you just have to tell the user "hey you can install this if you want"

fickle jetty
#

alr i figured

#

ty

balmy sky
#

I just had a weird idea

#

Like 99% of the in app assets are svgs

#

So theoretically you could make a plugin that changes the color to match your themes color variants

fickle jetty
#

like built in themes or custom themes?

#

because you can change the SVGs via css

#

i don't think any of them use an img tag

balmy sky
#

I had the thought because i use the catppuccin mocha theme, and the svgs don't match the color scheme

#

But yeah it might also be possible with css

#

Just override the fill or whatever to the closest variable

balmy sky
#

Probably would be hard to do optimised tho

hushed loom
#

yea, but what would it be
there are too many SVGs for it to be a bunch of patches

balmy sky
#

True actuallyt

fickle jetty
#

so the grayscale wumpus images and stuff too

#

although that'd take either a lot more math or a lot more manual work

flint bronze
balmy sky
#

Actually it might be possible to use some type of attribute selector

#

Since svgs probably use the same color palette for the most part

balmy sky
#

Is there a simple way to get how many messages the local user has sent in a server, and additionally change the timeframe to just the last week? I had a super horror approach going on but it didn't work at all

flint bronze
balmy sky
#

I did think about that

flint bronze
#

Cool; it's the most reliable option

balmy sky
#

Is it a bad idea? i haven't really used any endpoints before

#

I mean you can spam the shit out of the search in the normal client anyway

#

My plugin wouldn't use it more than that anyway

flint bronze
#

Cool. Do it ~50-200 times in a few seconds

flint bronze
#

unless

#

do it in the background as you are going through your server prune thing

balmy sky
#

Yeah that's what i mean

#

I mean it seems to work fine

#

Is this cursed?

#

It's probably possible to filter the messages date to save making an extra request with for the recent messages too

flint bronze
#

this is cursed

#

useAwaiter exists for this BTW

#

i think

#

oh

#

nvm

#

oh maybe????

#

you could probably use that

balmy sky
#

That's a fucking thing??

flint bronze
#

Yop

balmy sky
#

I just moved it over let me test

flint bronze
#

trolley

balmy sky
#

ok the awaiting works

#

Problem is, it doesn't recall when the index changes now

#

Is there a similar thing so i can call it again when the index state changes?

flint bronze
balmy sky
#

OH WAIT

#

Yeah i'm stupid

#

It works great actually

#

Yeah i don't think you could filter it to just get the last week could

#

And sending 2 requests would probably be a problem

#

Hmm

flint bronze
balmy sky
#

Really?

#

Alright then lmao

flint bronze
#

just use promise.all blobcatcozy

balmy sky
#

I am going insane

#

I'm trying to make the min_id parameter for the recent request

#

No idea what to do

#

Pretty sure it's a snowflake, but sioajdiowadhwjadhaskjhdsaj how tf do i get exactly a week ago and then convert it to a snowflake

#

Or just get it as a snowflake in the first place

flint bronze
#

Wtf do you need min id for

#

Oh I see

balmy sky
#

Min id is the date parameter (after _)

#

It's gonna make a second request to get the message count in the last week

flint bronze
#

SnowflakeUtils.fromTimestamp(Date.now() - (7 * 24 * 60 * 60 * 1000))

#

Something like that

balmy sky
#

That works surprisingly well actually

#

Thanks vennieheart

red dove
#

is there a way to make a multi select?

#

or would I need to write a custom component for that setting?

vast karma
#

Just do a dozen checkboxes, it's what everyone does

fallen sandal
#

vesktops linux screenshare audio select modal has multi select

#

check what it uses

vapid oar
#

is this component: loading still in the app? if so, what is it called?

flint bronze
vast karma
#

I think that's the WANDERING_CUBES variant

proud parrotBOT
# vast karma https://github.com/Kyuuhachi/VencordPlugins/blob/main/MessageLinkTooltip/index.t...

index.tsx: Lines 11-33

declare enum SpinnerTypes {
    WANDERING_CUBES = "wanderingCubes",
    CHASING_DOTS = "chasingDots",
    PULSING_ELLIPSIS = "pulsingEllipsis",
    SPINNING_CIRCLE = "spinningCircle",
    SPINNING_CIRCLE_SIMPLE = "spinningCircleSimple",
    LOW_MOTION = "lowMotion",
}

type Spinner = ComponentType<Omit<HTMLAttributes<HTMLDivElement>, "children"> & {
    type?: SpinnerTypes;
    animated?: boolean;
    className?: string;
    itemClassName?: string;
    "aria-label"?: string;
}> & {
    Type: typeof SpinnerTypes;
};

const { Spinner } = proxyLazy(() => Forms as any as {
    Spinner: Spinner,
    SpinnerTypes: typeof SpinnerTypes;
});
balmy sky
#

placeholder:\i,
then replace it with whatever you want

#

Just make sure you have the right find

#

You might need to add the previous prop to the match so you don't accidentally match the parameters at the top of the function

vast karma
#

Or find where u is defined and change that

balmy sky
#

That also works

#

Free find too

molten oxide
#

Do you know what windows alternative to mpris would be?

vast karma
#

Switching to linux

hearty heart
#

A few questions.

  1. How do I cache and use data I fetched at the plugin startup (no localStorage, it's too much data)?
  2. How do I disable the plugin if the data fetching failed?
  3. What are the dependencies?
vast karma
#

Probably some of the functions in lazy

vapid oar
#
const React = Vencord.Webpack.Common.React;
const ReactDOM = Vencord.Webpack.Common.ReactDOM;

const icons = Object.entries(Vencord.Webpack.findByProps("Adg"));

const tree = React.createElement(React.Fragment, {}, icons.map(([name, icon]) =>
    React.createElement(icon, { key: name, size: 24 })
));

const sudo = document.createElement("div");
ReactDOM.render(tree, sudo);
Vencord.Webpack.Common.Clipboard.copy(sudo.outerHTML);
console.log("Copied");
vapid oar
#

whoops im blind you can just Vencord.Webpack.findByProps("AIcon")

honest stump
#

pretty cool

balmy sky
#

I did add a 2 second cooldown on the scroll button just to prevent rate limiting

honest stump
#

the thumbnail image 😭

balmy sky
#

I set that ages ago and it jumpscares me every once in a while

hushed loom
hearty heart
#

I saw that I can use native.ts files to run code in a NodeJS environment, how do I get the result of that code in my index.ts start function?

vast karma
#

Did you try calling the function and checking the return value

hearty heart
#

If it's in the normal code (index.ts)

#

I did not try native.ts yet, so I asked a theoretical question so I won't waste my time for something that is impossible

vast karma
#

So you did not try calling the native function and getting its return value

hearty heart
#

Not yet, as I'm not home atm, I asked it without trying as I want to verify if it's even possible from people's experience

#

Let me rephrase my question.
I'm encountering a CORS error when trying to access a particular API, this is a known issue we've already surfaced to them but they aren't fixing. Will moving the method that fetches the data to native.ts and calling it from index.ts resolve this issue or will I need a proxy hosted somewhere?

Welp, after some research and digging into the built in plugins (since this is not documented). I discovered VencordNative.pluginHelpers. Would appreciate if this was documented

ripe smelt
#

Is there a better way to go about applying CSS when a user's status changes? The current method I use just spam re-applies the CSS to specific elments every 1ms to keep it up to date in somewhat 'live time', but spam applying the CSS crashes Discord after a few minutes and I'm pretty sure its not the proper way to go about it. (For context, I'm making a plugin that changes status icon SVGs/masks and it works using a patch, but when a user's status changes, it seems to scrape the status element of its mask and other attributes, so to get around it, I just have a function overwrite that element's attributes)

dull magnet
#

wha?

ripe smelt
# dull magnet this?

yeah those status icons, except a patch is fine for the ones in that pop-up since their attributes never seem to change

steady knot
#

what exactly is preventing you from just doing regular css to do..whatever it is you're trying to do?

ripe smelt
dull magnet
#

what

#

don't apply css to the element

#

don't use Dom manipulation

#

you can apply global css that selects the elements

ripe smelt
#

which plugin does that so I can look at how its done properly?

steady knot
#

you could just write your css in quickcss, select the element and replace it by using a pseudoelement; or if you're already making a plugin you could probably just overwrite the svg mask

rocky falcon
ripe smelt
#

alright

ripe smelt
#

I'll try my luck with just pure CSS

steady knot
#

hmm yeah and a pseudoelement doesn't work on the rect but it works on the avatar, jsut need to place it manually

#

here's a jank example (dirty prototype css but you get the idea)

#
rect[mask="url(#svg-mask-status-online)"]
 { width: 0 }
.avatar_b2ca13:has(rect[mask="url(#svg-mask-status-online)"])::after
 { content: url("https://cdn.discordapp.com/emojis/1026533070955872337.webp?size=16&quality=lossless") !important;
 position:relative; bottom: -20px; right: -20px;}
#

it will require a decent effort to make it work in other places where status indicators are and some clever length units if you want to make it work across different scaling settings etc

#

so maybe trying to replace them with a plugin isn't the worst idea, but it definitely can be done with just css

tropic ice
rigid coral
#

I'm trying to add my own Component into the TabBar on the the Homepage where you can see your Friends. I have this REGEX and I also want to match the ]}), in the group. Does anyone know how I can do that? figured it out

vapid oar
dull magnet
#

vsp @vapid oar

balmy sky
#
const dmChannel = ChannelStore.getChannel(ChannelStore.getDMFromUserId(user?.id));
const lastMessage = dmChannel ? MessageStore.getMessage(dmChannel?.id, dmChannel?.lastMessageId) : null;

This is my current code to get the last message in a dm, but it only works if you've opened the dm in the currect session. Is there a workaround/fix for this?

cedar olive
#

cant you simply fetch the message

#

you have the channel id and the message id

balmy sky
#

I should have specified how it doesn't work, lastMessageId is just null if the channel hasn't been loaded

#

There might be a different way to do it, channelstore maybe?

cedar olive
#

but the channel object exists?

balmy sky
#

Yeah the channel object is there

cedar olive
#

I'll leave it to someone who can help better

#

I don't have my computer so I can't even test things to help

balmy sky
#

Ah fair enough

hushed loom
#

is there a method to get your friends

flint bronze
hushed loom
#

Only needed it once for a script

flint bronze
balmy sky
#

Is it possible to do a similar thing to useStateFromStores but with datastore? from what i can tell datastore isn't a flux store, but i essentially want to re render a component every time a specific value in the datastore changes

haughty maple
dull magnet
#

what's gonna happen

haughty maple
vapid oar
#

how do I access erlpack on Vesktop?

dull magnet
#

you don't

#

why do you need

vapid oar
#

trying to figure out an opcode

#

can't find it on discord.sex

dull magnet
#

Web doesn't use erlpack

vapid oar
#

oh yeah

#

it's just encoded with zlib

haughty maple
#

Thanks!

vapid oar
#

turns out that specific OP code is only processsed by mobile isn't actually sent to FluxDispatcher on PC

#

ok wait maybe im just crazy cuz the event doesn't even get sent to the websocket anymore

#

i think i mistook it for a ping message

#

yeah the event just doesn't exist oopsie!!

weary basin
#

howdy 🫡 if i'm implementing an optional feature into a plugin that requires a native script, does the entire plugin become incompatible with the web version, or can platform checks be implemented that prevent incompatible platforms from using said feature?

dull magnet
weary basin
#

can i make a setting selection not selectable if IS_WEB or do i need to implement the check within the logic

#

nevermind, seems like just adding disabled: IS_WEB works

dull magnet
#

the compiler will automatically strip unreachable code

#

so you can just use if statements / ternaries with the definitions

weary basin
#

so i should probably both remove the settings options on web and add the if statements into the logic

#

NanaThumbsUp thanks

weary basin
#

so, i added DeepL support to the translate plugin. since this violates the plugin rules and i can't create a PR, can i still post it in #1256395889354997771, or is it totally not allowed to be shared?

hearty heart
#

Is it possible to embed an iframe into a popup from a plugin?

dull magnet
weary basin
#

i actually wanted to use my pro API key anyways, so i more made this for me

#

but i noticed there were over 20 👍 reactions on the feature request

#

so i figured i would just make it happen since it seemed simple enough. but yeah, i did notice it violates the plugin rules

#

so at the very least, i wanted to share it in the feature request issue

#

assuming it's okay to share it

dull magnet
#

I think it's fine, since the plugin still works without deepl

#

it's just an option for people who have it

#

that rule is mainly about avoiding plugins that most users won't be able to use

weary basin
#

so you're saying it's fine to commit, too?

dull magnet
#

like if you made a deepl only plugin, it wouldn't be allowed

but since the translate plugin still works even without, it's fine to have

weary basin
#

yeah, i have it default to google translate still

dull magnet
#

like google translate (technically you need a key for it too), virustotal, etc

weary basin
#

yeah, that's fair. you do really need an API key for deepl though haha

dull magnet
#

but the rate limit is too strict..

weary basin
#

i can assume why it would be

#

but anyways, that's a green light to PR?

dull magnet
weary basin
#

so... wait on the pr? NanaXD

dull magnet
#

you can pr it for now

weary basin
#

okay. and while i have you, is something like this worth adding an author for the plugin? i don't really know what level/amount of contribution is worth slapping a name on it or not

dull magnet
#

basically when you add a substantial new feature

#

so yes

weary basin
amber mantle
#

i dont have them now though

fickle jetty
#

is there a way to package a node.js module into a plugin properly with webpack or smth? i'm trying to write a websocket server inside a plugin to connect with a browser extension but i can assume installing an extra dependency is a big no-no

#

i got like halfway through writing the server before i realised it was pulling the dependency from my global dependencies 😭

simple folio
#

or your phone if you're rooted

amber basin
#

it should be packaged in automatically by esbuild afaik

#

also no, we dont use webpack to bundle vencord. we modify discord's own webpack

#

we use esbuild to bundle it all into two or 3 files

#

node, renderer, preload

amber mantle
#

don't do this if you're PRing a plugin though

fickle jetty
#

no fun allowed, smh

turbid cypress
#

Anyone know if its possible with SettingsSliderComponent to change the text it says when the slider is at max? Say the slider is from 1 to 10, if it was on 10 it would say "Infinite". Maybe there is a better way of doing what im thinking

amber mantle
#

but ask v its ultimately their decision

#

what plugin are you making

fickle jetty
#

basically spotify integrations but YouTube Music

amber basin
#

lastfm rich presence + a ytm scrobbler

fickle jetty
#

yes but also listening a long in the future

amber basin
#

not possible

fickle jetty
#

that will take 10 morbillion years to get right though and i start school soon

fickle jetty
#

already wrote an entire extension to scrobble ytm efficiently

fickle jetty
haughty maple
#

OLD:

/(?<=(?:},{|\[{)type:\i\.ABu\..*?,name:")(.*?)"(.*?icon:{.*?},.*?enabled:)(?:!(\d))(?=,?)/g```
NEW:
```js
/(?<=(?:},{|\[{)type:\i\.\w{0,8}?\..{0,20},name:")(.{0,20})"(.{0,40}?icon:\{.{0,225}?\},.{0,150}?enabled:)(?:!(\d))(?=,?)/g```
Is the new match by far better?
dull magnet
#

no

haughty maple
dull magnet
#

rewrite the whole thing

hushed loom
#

what are you trying to patch

dull magnet
#
match: /name:"Twitch",color:/,
replace: 'name:"Twitch whatever",color:'
haughty maple
#

and it's based on if enabled is !0 or !1

vast karma
#

Why the replace dance when you can just call $self.whatever()

dull magnet
#
match: /name:"(\w+)"/g,
replace: "...."
#

ur match is increcibly unreadable

haughty maple
#

i mean adhd doesn't help that either

haughty maple
#

my brain has a very big feature of not working correctly!

dull magnet
#

keep it simple

#

why are you matching soooo much

#

match as little as possible

#

don't be overly precise

haughty maple
#

but i will try once more!

bronze dove
haughty maple
rocky falcon
#

how would i go about patching the same thing that another plugin patches, without conflicting with the original plugin

amber basin
#

predicate with Vencord.plugins.isPluginEnabled(name), if the predicate is false patch normally, if its true work the patch around the other plugin's

#

remember to see which plugin's patch applies first, u might have to modify the other one

#

or just make an api

hushed loom
amber basin
#

what do u want to patch

hushed loom
#

(i have a plugin that runs into the same issue)

amber basin
vast karma
#

Or write the patch in a different way, often you can put it a few statements away and it'll still work fine

rocky falcon
#

the username rendering function, but showmeyourname already patches it.
and i cant exactly edit smyn, because its for an #1256395889354997771

amber basin
#

iirc theres a way to define incompatable plugins? lemme check

rocky falcon
#

i'd rather not though

amber basin
#

then youre out of luck

#

idk what else to tell you

#

just work the patch around the code

vast karma
rocky falcon
#

vee said this, not entirely sure what they were suggesting though.

cedar olive
amber basin
cedar olive
#

first option is better since an api would likely be overkill

rocky falcon
vast karma
#

Git gud then

rocky falcon
rocky falcon
cedar olive
#

nop

honest stump
#

I think i have dementia i dont remember sending this gif

signal goblet
#

@balmy sky someone wanted this plugin and I fixed it but wha-

signal goblet
signal goblet
balmy sky
#

What even is that plugin

signal goblet
#

Sticker Blocker

balmy sky
#

Ohg

#

Yeah that's a piece of shit

signal goblet
#

Someone brought it to me because they couldn't find it

#

And they wanted it so I fixed it

#

And they are happy ig idrk

#

I see no point in it really

#

Just deal with it

balmy sky
#

It was one of my first plugins (if not actually my first) plugins using patches

#

So eh

signal goblet
#

Fair

#

TBH I just robbed clone emoji for the context menus

#

It's almost 3am and I didn't want to fix it if it was actually broken

#

Not the best find but it will do

balmy sky
#

Regex in finds?????

#

Since fucking when what

signal goblet
signal goblet
hushed loom
signal goblet
hushed loom
signal goblet
#

I use regex in finds when I don't want to do a proper find because it's late at night and I'm tired 👍

signal goblet
#

That was the point

#

I didn't have discord open either way

hushed loom
signal goblet
#

I had bps

#

1 bps *

#

I could easily make that find to a string since r.STICKER_MESSAGE uses a : and I believe l.Z.STICKERMESSAGE doesn't

signal goblet
#

I forgot why app icon is like that but I believe it.was because I would've had to do a really long find at the time

leaden fable
#

How does the extension patches discord? (I have yet to see the source code). I'm trying to make a small patch in a website's js code and can't seem to figure out how to patch the webrequest response

dull magnet
leaden fable
dull magnet
hushed loom
#

is there a way to get a channel object with the channel id and guild id

balmy sky
#

Channelstore

safe glade
flint bronze
safe glade
#

huh yeah kinda true

#

oh god I forgot about that bullshit

hoary pilot
#

is there a way to use Parser.parse(), but in what i could call a "guild context"? eg. this would show roles, mentions would have nicknames, channels wouldn't be prefixed by guild name

#

or another method that exists to do so

#

global (what i don't want)

#

guild (what i want)

dull magnet
#

look at messagelogger

#

more specifically my recent fix to ut

hoary pilot
#

ty

flint bronze
hushed loom
#

is is possible to see everything subscribed to a flux

amber basin
#

search for the event name?

flint bronze
amber mantle
#

not sure how to go about #2734

flint bronze
#

native script

amber mantle
#

great

#

i removed it for nothing then

flint bronze
#

cant you edit headers from native

amber mantle
#

yes

#

(i think so)

#

(decompiled source)

#

this shouldnt actually matter

#

1s

#

wires the only commands "limited" clients can do are SendNotification and Requestinfo or whatever we're safe

#

lmao

#

probably so random website cant mess w your overlay i guess

#

not that any would

balmy sky
#

Where can i find a function to send a message in the current channel? i found sendMessage in the discord utils but it doesn't reply to whatever you have selected as a reply

dull magnet
#

look at VoiceMessage plugin

balmy sky
#

That is

#

Definitely a function

sudden belfry
#

Alright, I give up trying to fix this myself. Why is my Native undefined when printed out and why is my native.ts not working correctly? I've checked various other plugins that do this and it all seems to be correct. I do fully restart my Discord as well.

const Native = VencordNative.pluginHelpers.PersonalBadges as PluginNative<typeof import("./native")>;

And I think due to this, I get this error whenever I try to use something from there:

TypeError: Cannot read properties of undefined
balmy sky
#

Do you have anything actually exported in native

#

Might make a difference

dull magnet
#

are you sure you fully restarted discord

#

close from tray and reopen

sudden belfry
#

I could do it again but I always quit from the tray and reopen

sudden belfry
dull magnet
#

inspect pluginHelpers in your devtools

#

you'll probably see what's wrong

sudden belfry
#

Sorry but what exactly do you mean? This is kind of my first time trying to do this stuff

hushed loom
#

go into to devtools and type VencordNative.pluginHelpers

sudden belfry
#

Ah I get it now, thanks

#

Alright fixed my issue! I guess I couldn't have any spaces within the name of my plugin and when I saw it in the pluginHelpers it looked out of place with the others. I didn't see anywhere that you couldn't though but probably should've saw and followed how the other plugins were anyways. I guess something I'll keep that in mind for the future then.

#

All that time just for that-

#

Thanks though

cedar olive
#

was your plugin name Personal Badges?

sudden belfry
#

Pretty much

cedar olive
#

you prob just had to do VencordNative.pluginHelpers["Personal Badges"] then

sudden belfry
#

Ah

#

It's fine though, I was probably gonna change it not to have a space soon anyways but thanks, guess I could also do that if I ever wanted to then

cedar olive
#

yep yep

cedar marsh
#

Discord doesn't load 100% of it's styles through webpack

cedar olive
#

yes the initial one is not through webpack

#

it's placed in the html loaded initially

cedar marsh
#

the concept of relying entirely on wreq.f.css instead of mutationObserver isn't possible then

cedar olive
#

it is for all the others beside the initial one

#

which is no big deal but we already decided to use mutation observer anyway

cedar marsh
cedar olive
#

before setting up the mutation observer query the existing css

#

after that it should all be catch in the mutation observer

cedar marsh
#

I'm not using mutation observer at this point ngl

cedar olive
#

(even the initial if it wasn't loaded yet)

#

huh?

#

you are gonna query once only

#

for the already existing ones before you start the observer

#

there are no issues with that

cedar marsh
#

I feel like what I am getting with wreq.f.css is going to be cleaner than a mutationobserver

cedar olive
#

how

cedar marsh
#

Api.Styles.styleListeners - new Set<(styles: string) => void>();

plugins\_api\styleListener.ts

// ... cleaned version of your wreq listener
for (const listener of Api.Styles.styleListeners)
    listener(styles);
// ...
cedar olive
#

hm

#

if it's gonna be an api then maybe

cedar marsh
#

basically all my plugin ideas require this api

#

I don't know how to make an API require restart if it has no patches, because techincally this one does

cedar marsh
# cedar marsh `Api.Styles.styleListeners` - `new Set<(styles: string) => void>();` `plugins\_...

start of StyleListenerAPI

const wreq = await new Promise<WebpackInstance>(r => beforeInitListeners.add(r));

const chunksLoading = new Set<string>();
const handleChunkCss = wreq.f.css;

wreq.f.css = function (this: unknown) {
    const result = Reflect.apply(handleChunkCss, this, arguments);

    if (chunksLoading.has(arguments[0]))
        return result;
    chunksLoading.add(arguments[0]);

    if (!(Array.isArray(arguments[1]) && arguments[1].length > 0))
        return result;

    Promise.all(arguments[1]).then(async () => {
        await Promise.all(arguments[1]);
        chunksLoading.delete(arguments[0]);

        const cssFilepath = wreq.p + wreq.k(arguments[0]);
        const styles = await fetch(cssFilepath)
            .then(res => res.text()).catch(() => { });
        if (!styles) return;
        for (const listener of Styles.styleListeners)
            listener(styles);
    });

    return result;
};
cedar olive
#

I'll make the proper api and include in my webpack changes pr

#

I wanna try to get it merged soon

#

but if that doesn't happen I'll port to current vencord

cedar marsh
#

okay

cedar marsh
cedar olive
#

document.querySelector lol

#

there is no escape

cedar marsh
cedar olive
#

right

#

in that case...

cedar marsh
#

requestAnimationFrame(() => document.querySelector
is cleanest solution I have thought of

cedar olive
#

can we mutation observer already there

cedar marsh
#

I can try

#

yes, trying to make a clean solution from that

cedar olive
#

if we are gonna use a mutation observer already there it's better to only use it

#

and avoid webpack patch

cedar marsh
#

also somehow using a mutation observer is slower than window.requestAnimationFrame(()=>{...})

cedar olive
#

how are you benchmarking that?

cedar marsh
#

2 plugins, one logs one the first observed mutation, the other logs on requestAnimationFrame, requestAnimationFrame always is first

cedar olive
#

are you requesting frames recursively?

cedar marsh
#

no

cedar olive
#

or the first frame generated already contains head

cedar marsh
#

first generated frame contains head

cedar olive
#

fire

#

I like that

civic elk
#

is there a way to modify/intercept requests/responses, specifically for message loading

vast karma
#

That's almost certainly the wrong layer to modify

civic elk
#

ok i tried modifying fetchMessages, but that just returns true, so i used the function it calls with my own message objects but the client doesnt seem to care and still fetches the messages in the channel from the api, any ideas?

dull magnet
#

and you are trying to do what?

supple helm
#

How would I add another sound to this? I tried installing react dev tools to opera and doing it but I have no idea what to do with what I find.

#

Are there any documentations other than just looking at plugins and the starting plugin documentation?

hushed loom
#

Use react devtools

#

Also, iirc opera doesn't play well with vencord.

supple helm
empty sundial
#

Is there an easy way to add more settings sections?

supple helm
hushed loom
empty sundial
supple helm
cedar olive
empty sundial
#

i know, also i found the stupid way to do it already :3 its less so configuring the plugin and more so a utility that id place into the discord settings + i need space which a modal cant provide

cedar olive
#

which means if you have no experience that's gonna be complicated

hushed loom
#

ping me in an hour or two

empty sundial
# empty sundial i know, also i found the stupid way to do it already :3 its less so configuring ...

for future reference (i guess i should add that you shouldnt use this for normal plugin settings ofc)

import { SettingsTab, wrapTab } from "@components/VencordSettings/shared";
import definePlugin, { StartAt } from "@utils/types";
import SettingsPlugin from "plugins/_core/settings";
import { Card, Forms, TabBar, TextInput } from "@webpack/common";

function CustomSettingsSection() {
  return (
    <SettingsTab title=":3">
      <TextInput type="text" placeholder="meow" />
    </SettingsTab>
  );
}

export default definePlugin({
  name: ">:3",
  description: "asdf",
  authors: [],
  startAt: StartAt.Init,

  start() {
    SettingsPlugin.customSections.push(() => {
      section: "mreow",
      label: "cool section",
      element: wrapTab(CustomSettingsSection, "mreow"),
      classname: ""
    });
  }
});
dull magnet
#

that's why customSections exists

empty sundial
#

oh

#

well okay 😭

dull magnet
#

so it's completely fine to use as long as there's a good reason to

dull magnet
proud parrotBOT
empty sundial
#

lmao alright but thats kinda what i thought, added because it was needed for something else and not for plugins
thats also why i thought it was discouraged

fallen sandal
#

how would i get the className of the Mutual Servers element

fallen sandal
#

nah im trying to add another entry there for group dms

cedar olive
#

look at it's component code and you will find where it adds the classes

#

or even easier actually

#

look in the html and find the class name with the hash

#

search for it in devtools and you are gonna find the module that exports them

#

then just write a filter to find that module

full stump
#

uhh how do I have the vendor developer mode on

tropic ice
#

but it doesnt seem to have a class name to differentiate it from mutual friends

flint bronze
tropic ice
#

idk
but i prefer dock right usually

flint bronze
#

Ah yes I'd like my viewport to be made significantly smaller AND have a devtools panel that is unusably small

tropic ice
#

for css stuff, it's usually fine

flint bronze
#

honestly I just toggled it

#

it isnt that bad

#

but for searching through Discord code

#

absolutely No

tropic ice
#

yeah

#

and i prefer the html being above the css

#

which only happens when it's small

hushed loom
tropic ice
#

most of the time for css, using it like tha tis fine

#

and docking as a seperate window is kinda weird in discord because pressing ctrl+shift+i when main discord is focused and devtools is already open closes devtools instead of focusing it (like it does in google chrome)

tropic ice
hushed loom
#

guhhhhh

#

i quit a long time ago

#

wiped twice blobcatcozy

tropic ice
#

skill issue

hushed loom
tropic ice
#

ew

empty sundial
tropic ice
hushed loom
karmic marsh
#

anyone know how discord fetches the list of favorite gifs? i tried monitoring network activity but it only fetches images and does not perform any other api request

empty sundial
#

there is no specific api route for gifs only

dull magnet
#
Vencord.Webpack.Common.UserSettingsActionCreators.FrecencyUserSettingsActionCreators.getCurrentValue().favoriteGifs.gifs
#

which is fetched via /users/@me/settings-proto/*

#

and returns protobuf bytes as base64

karmic marsh
#

Thanks for the support 🙏

empty sundial
#

Vencord vim keybinds plugin when 😨

vast karma
#

When someone makes one

hushed loom
#

Maybe within the next month

empty sundial
#

how do i get localStorage inside a plugin? I want to save a value

vast karma
#

DataStore

empty sundial
fading mural
#

why is this not working? (it's not even appearing in the plugin list)

#

nvm none of my userplugins are working and I am officially an idiot

fading mural
#

this is correct right

#

nvm bad capitalization

sand ember
#

why are you installing plugins with nix

vast karma
#

Presumably they use nix and want to use vencord with user plugins

hushed loom
vast karma
#

Vee is god confirmed?

hushed loom
#

nop

empty sundial
balmy sky
#

What do you mean nop

hushed loom
dull magnet
#

it's proprietary discord code why would there be docs

#

you need to reverse engineer things

rocky falcon
#

I wanna star this

balmy sky
sand ember
#

i have no idea what you are talking about

tropic ice
#

Is there a starboard?

fading mural
#

minor admin abuse

empty sundial
#

whta

#

whar

dull magnet
#

I deleted it cause it's funnier without the context

#

(also unnecessary nix yapping noone gives a shit)

empty sundial
#

i was gonna say "thats a pretty bad look you made for yourself"

balmy sky
#

The fact that the other messages were deleted is fucking hilarious

sand ember
fading mural
#

the answer is because I use nix for vencord, and I was explaining that my user plugins option only allows putting files in (not strings)

tropic ice
#

the message was deleted :(

bitter root
amber mantle
#

you had to be ther

rocky falcon
#

wait starboard is gone‽‽

swift delta
rocky falcon
swift delta
rocky falcon
swift delta
#

or, it got retired because huskboard might be coming back

#

Probably the first one though

jagged briar
#

😭 i loved starboard

rocky falcon
#

just to verify, api key's are fine, as long as they're not required?

normal wagon
#

how do i get the mesages from before? i'm trying to get all the messages, in a DM

i understand this but it only returns a certain amount of messages i wanna get the ones before the last one.

MessageStore.getMessages

hushed loom
dull magnet
#

By fetching them but that's api abuse if you fetch the entire history

#

figure it out yourself

hushed loom
#

oh, i didnt see the all the messages part, oops

normal wagon
#

@hushed loomi need the function!!!

hushed loom
#

me when im stupid

normal wagon
#

shush

#

ill figure it out

mental haven
#

I see some people noted looking to intercept events,
according to the dispatcher flow, events are divided into 3 parts.

  • Intercept (return true here means events scraped)
  • ActionDispatchers (list of events to process given event object)
  • Subscribers (list of events to post-process given event object)

In order to modify an event, a callback need to be placed somewhere on Intercept or ActionDispatcher stage. I wouldn't recommend to do the latter. However making a wrapper for "Intercepting Event" and "No Intercept Event" would be good to make a hassle free incoming event filter.

I think an extension of FluxDispatcher type definition regarding interception and how it works can be handled somewhere on utilities or similar like that? Well, thats my 2-cents regarding how it works.

flint bronze
#

can someone suggest a name for a plugin that replaces the tooltip of the mute/deafen buttons with a volume slider?

#

similar to the video player

dull magnet
#

wha

#

oh i think i know what you mean

flint bronze
#

ok time to recreate stock discord components

#

this is fine

woeful plover
#

Yay okay so

#

I want to make a dialog but only know the Alerts function is there a way to display HTML/React code

Alerts.show({
            title: "Need html",
            body: `How do I put html in a dialog like this`,
        });
flint bronze
#

Use JSX

woeful plover
#

I know but how to display it using Alerts or do I need another function

flint bronze
#

You can use Alerts.show for that

woeful plover
#

oh I tried but it didnt work

#
Alerts.show({
            title: "Get ricked lmao",
            body: `<iframe width="560" height="315" src="https://www.youtube.com/embed/X-cfWM0BC_4?si=Vfcp5PWnCHpKOxH_" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>`,
        });