#🧩-plugin-development

1 messages Ā· Page 71 of 1

dull magnet
#

tbh we should add more sugar for these apis

#

similar to flux events

#
export default definePlugin({
  onBeforeSendMessage(channelId, msg) {
    // do stuff
  }
})
swift delta
#

I feel like my chances of getting this put into #1256395889354997771 is small to nonexistent because it’s on the technicality (just like my other one) that it can be done by txt replace but not well…

humble tulip
#

What is it?

swift delta
#

it adds a customizable ā€˜fingerprint’ to the end of messages

unkempt kindle
#

yeah that definitely can be done with textreplace

swift delta
unkempt kindle
#

find: ^(.*)$
replace: $1\n\n> This message was sent by your mother.

flint bronze
#

If there's an easy toggle option somewhere in the UI that isn't buried in settings then I'd say it's viable as an alternative to textreplace for this application

#

but also

#

why?

swift delta
unkempt kindle
#

this is similar to iphones adding the "sent from an iphone" at the end of an email

This message was sent by TheAnnoying

unkempt kindle
swift delta
#

You’ll see one thing and you hop on a fucking bandwagon

#

You gotta wait it out

#

I’m still on my initial commit

flint bronze
#

To me it seems just

flint bronze
#

obnoxious?

swift delta
#

Yes, it can be done via text replace but i plan on adding an option where it can be toggled on and off

flint bronze
#

Okay then I'd say that makes sense

#

generic toggleable text transform plugin when

swift delta
#

I also plan on being able to allow people to blacklist servers or channels so no matter what it just never happens there

unkempt kindle
#

does vencord accept silly plugins or do they not do that anymore

#

idk whether i should post my plugin in unofficial-plugins or wait it out and someday submit it as an official one

flint bronze
swift delta
cedar olive
#

5$ and I will get your silly plugin added in record time

#

(eeal)

flint bronze
#

new plugins feel really rare these days

swift delta
unkempt kindle
#

the post titled "How to Install plugins from here / How to submit plugins" only shows you how to install plugins

swift delta
#

still, though it’s not done yet I still have a lot of plans for the plug-in that would give it justifiable reason why it would be better then doing it via text replace

unkempt kindle
#

so that it isn't annoying to look at

swift delta
#

almost as if I exactly just said ā€œI have plansā€

flint bronze
#

markdown footer? but places like here have rules against that (because it gets really... really... really annoying quickly

unkempt kindle
flint bronze
#

yes

unkempt kindle
#

i didn't think of a markdown footer i just thought of somehow changing it with css

flint bronze
#

nobody else would see that

unkempt kindle
#

but that's pretty much what i was imagining yes

unkempt kindle
#

another disgusting thing you can do is somehow use invisible unicode characters to encode the text at the end of the message and then only people with the plugin will see that rendered as normal text (a markdown footer or whatever)

shrewd tundraBOT
unkempt kindle
#

i did something similar in my kitten speak plugin

swift delta
#

I should really stop developing my code on canary

humble tulip
swift delta
#

@unkempt kindle @flint bronze
Yes i told y'all i have plan

#

I even plan on making it so I can be done toggle via a command

rocky lynx
#

why so many buttons

swift delta
#

not enough honestly

rocky lynx
#

this is all i have

swift delta
#

you need more

swift delta
#

which doesn’t sound like a bad idea…

swift delta
unkempt kindle
#

i think it's fine 😭

swift delta
#

nah I’ll add one more that doesn’t actually do anything. It’s just there.

unkempt kindle
#

how do you customize the text

swift delta
humble tulip
steady knot
#

ooh

#

you should pr

humble tulip
#

Yeah maybe

#

I tried separating the calendar formats a bit from the different timestamp types so it's a bit clearer what it means, it confused me for a little bit lol

steady knot
#

yeah that's fair

humble tulip
#

Just kinda slotted in a header for it, it's a bit jank

iron epoch
humble tulip
#

Probably, I threw it together while I was at work so I could share it with the friend lol

swift delta
flint bronze
# swift delta

yeah thats not how the api works but thats how the API should work

swift delta
#

nah im just kidding i found a different way

flint bronze
swift delta
flint bronze
iron epoch
dull magnet
#
stop() {
  const { customSections } = Vencord.Plugins.plugins.Settings;
  customSections.splice(customSections.indexOf(this.insertSettings), 1);
}
swift delta
#

@iron epoch

unkempt kindle
#

I am trying to write a patch that will edit all channel names
I wrote this one but i know it's not good since it uses variable names + it only works with text channels
i really don't know what else I could do though

patches: [
    {
      find: "function w(e){let{channel:t,guild:n,disableSorting:",
      replacement: [
        {
          match: /(function w\(e\){)(let{channel:t,guild:n,disableSorting:)/,
          replace: `$1e.channel.name='test';$2`,
        },
      ],
    },
  ],```

i used the components tab to select a channel and view the source
#

my end goal is to remove emojis from channel names
somehow need to be able to use the e.channel.name variable in my code which i don't know how i'll do

vast karma
#

Pass arguments[0] to your function

#

Or just capture the variable name

unkempt kindle
#

i've thought about it and i can just run the logic in discord and not in my code

#

just instead of
$1e.channel.name='test';$2
i can just do
$1e.channel.name=e.channel.name.match(/whatever/)[0];$2

vast karma
#

Mutating props is illegal though

unkempt kindle
#

this isn't a smart patch

vast karma
#

Find the part that says children: t.name or similar, and change that to children: $self.memfrob(t.name)

unkempt kindle
#

what is $self.memfrob

#

what is $self

vast karma
#

$self is replaced with a reference to your plugin object

unkempt kindle
#

oh nice

#

is a memfrob function magically part of my plugin object

vast karma
#

It's in your plugin object if you define it

unkempt kindle
#

when i searched earlier for the place to patch I did see a few elements that had a children prop but i really didn't know what that meant about it

#

so I preferred looking for something with a channel prop that has the channel info

vast karma
#

Sure, but you are not allowed to mutate props

unkempt kindle
vast karma
#

That's just changing the output

#

e is passed to your function, and you are not allowed to change it

#

You are free to change the returned jsx elements however you want

unkempt kindle
#

are we assuming i have something similar to:

function something(e){
  let { children: t } = e
}
unkempt kindle
#

that makes more sense

vast karma
#

No, I'm talking about ```js
function(e){
return (0, x.jsx)(T.qW, { children: t })
}

unkempt kindle
#

I didn't think of changing what's returned

unkempt kindle
#

okay it works nice

#

now just to removing the emoji part

unkempt kindle
#

and you were right, it is using children: something

hushed loom
unkempt kindle
#

what

humble tulip
#

store

vast karma
#

Stove

hushed loom
#

Guhh

#

Store

humble tulip
unkempt kindle
# hushed loom Store

that still doesn't give me a lot of info
i don't really know what the store is

cedar olive
#

making the have dirty data will affect many other places

inner monolith
#

I have an idea for a banger plugin that I'm going to try making

#

would work well with fake nitro and fix a big issue

#

and is fairly simple although I've realised simple = still hard when reverse engineering discord for me

#

I wonder if i should make an electron app first to figure out how discord works first

flint bronze
#

the electron code is very rarely touched when making a vencord plugin

#

you need to understand how to look at minified webpack code and edit it with regex

rocky lynx
#

patches are the one thing i have not figured out yet

swift delta
#

I can code a plug-in, but don’t fucking ask me to make a patch

hushed loom
#

id like to think im fairly good with patches, ping me with any questions you have blobcatcozy

swift delta
hushed loom
rocky lynx
#

i learned javascript making a discord bot, so typescript wasnt too difficult for me.

swift delta
rocky lynx
swift delta
rocky lynx
#

I see the user plugin submissions are about as slow as prs

hushed loom
rocky lynx
#

I opened it 10 days ago husk

unkempt kindle
#

why is it not allowed to mutate props? this method seems to work much better than my other option

vast karma
#

Try doing channel.name += "!" and you'll see

unkempt kindle
#

that'll just add ! to everything

#

what's wrong with that

vast karma
#

You will see

unkempt kindle
#

oh god what is going on

#

why did it add it 3 times

#

it's adding it more

vast karma
#

Told ya

unkempt kindle
#

oh god

vast karma
#

Because it's mutating the input

unkempt kindle
#

what the hell

vast karma
#

And then that mutated input is passed when it's rendered next

unkempt kindle
#

nice stuff overall

vast karma
#

And it mutates it again and again

unkempt kindle
#

but the mutation im doing is different

#

im not adding anything im just removing emojis

vast karma
#

Perhaps your mutation is idempotent

#

But you are still mutating input

unkempt kindle
#

doesn't visually look different every moment

unkempt kindle
#

and easier to just change the data it's getting

vast karma
#

Yeah and it's easier to open a door with an axe than with a key

#

But has more side effects

unkempt kindle
#

wait i'll show you exactly what it is

vast karma
#

You are currently doing t.foo = func(t.foo), right?

unkempt kindle
#

it's inside one of the ...p, ...v or ...e

unkempt kindle
vast karma
#

You can for example change that to t = {...t, foo: func(t.foo)}

unkempt kindle
#

how would that be any better

#

i can do that

vast karma
#

Because that does not mutate anything

vast karma
#

It only changes a local variable

vast karma
unkempt kindle
dull magnet
#

you can mutate props just fine

unkempt kindle
#

oh wait you're THE vencord person

dull magnet
#

just if it has side effects then you're likely better off not doing that

unkempt kindle
dull magnet
#

why do you want to do that

unkempt kindle
#

because some servers get really annoying with it

dull magnet
#

if you're changing the name just inside the component, that's fine

#

if you're changing the name in the global channel structure, that's bad

unkempt kindle
#

in the react component selection thing I specifically selected the outer most channel element

dull magnet
#

in this case it shouldn't be hard to just patch where it renders the channel name line

unkempt kindle
#

I also tried simply changing the text itself from the inner most element that stores the text and that worked but it didn't change the text at the top which the first method does do

#

ignore the ! that was a test

vast karma
#

"Don't change props, ever" is much easier to say and to follow than "only change props if you are certain that it is idempotent and that the values aren't shared with anything else"

unkempt kindle
#

this is exactly what im doing so far
is it that bad?

#

it's actually nice I can see the patched code like that

flint bronze
#

this is overwriting the name everywhere when it is rendered in the sidebar

#

this is shared globally

#

which is Probably a Problem

#

the real issue is how inconsistent it is

vast karma
#

If you want to globally change the name, sure, but don't do that from a rendering function

#

Either change the rendering or change the data

flint bronze
#

if you link to a channel in another guild for example, it won't automatically update

unkempt kindle
flint bronze
unkempt kindle
flint bronze
unkempt kindle
flint bronze
#

thats the easiest way though as vee said, there are side effects

#

you're best off not directly overwriting that channel prop; it seems like you're patching that too early (if you want to edit what is rendered)

vast karma
#

Presumably that would be in a GuildStore or ChannelStore or GuildChannelStore

unkempt kindle
flint bronze
#

you'd probably want to do something on the connection ready flux events for example if you were to do that

flint bronze
vast karma
unkempt kindle
#

are these stores a vencord thing or a discord thing

flint bronze
#

discord thing

vast karma
#

Discord of course

unkempt kindle
#

oh

flint bronze
#

though a few plugins implement their own

unkempt kindle
#

I thought it was vencord who is collecting the data and just making it more accessible

vast karma
#

No, those stores are where discord stores its own data

unkempt kindle
#

so any data that discord uses comes from there

#

yeah so I should edit the data in the store

humble tulip
#

obligatory screen record music

cedar olive
#

you want to remove the emojis from the sidebar channel names

#

then do what people have been saying and edit where that is rendered

#

and not the channel structure name

#

or else you are gonna "corrupt"/make dirty the data that is used all across your discord client for the channel name

#

it's much easier to just find where that channel.name is being used and replace it there

unkempt kindle
cedar olive
#

you really shouldn'tblobwob

unkempt kindle
vast karma
#

Oh no the horror

unkempt kindle
#

i don't see what's so wrong with manipulating the data discord uses

#

im just editing a string

cedar olive
#

because the whole point is to not make data dirty

#

that data is not only used in ui stuff

unkempt kindle
#

oh shoot

#

that might be true

#

yeah i see how that could be problematic

#

if i want to simply change the text that's rendered then i could change this children thing here but that doesn't feel like an effective patch because there's no function name or some specific text or indicator that will most likely not update soon

#

that means I will have to select some part around the children thing as well

dull magnet
#

imagine editing a channel with emoji in its name

#

you will change the name even if you dont want to

#

it will likely mess up the message search channel filter too

humble tulip
#

The .scrollWidth&&(null= in there is unique and I doubt it'd change since it's just pretty simple logic to tell if the channel name is being cut off

#

And t is just a string

dull magnet
#

e is a minified variable

#

dont use

humble tulip
#

Yeah sorry, I took the i out and missed the e smh

#

I tried it and all my channels look naked

fathom talon
#

Hey guys, does someone could help me with regex to account panel?

/((?:.*)(?<=function) .{0,8}?(?={).)(.{0,1000}ACCOUNT_PANEL.{0,1000}\)]}\))(})/
#

I need to fix that block of code

{
        find: "Messages.ACCOUNT_A11Y_LABEL",
        replacement: {
            match: /((?:.*)(?<=function) .{0,8}?(?={).)(.{0,1000}ACCOUNT_PANEL.{0,1000}\)]}\))(})/,
            replace: "$1return $self.replacedUserPanelComponent(function(){$2}, this, arguments)$3"
}
bronze dove
#

what exactly are you trying to do

fathom talon
#

I'm trying to fix patch that adds button to user panel next to screenshare button

#

I replaced in "find" to "#{intl::ACCOUNT_A11Y_LABEL}" hope it works

bronze dove
#

this one?

fathom talon
#

Yeah, I got it work

bronze dove
#

you have weird patch anyway, why dont you add your component to the array instead?

fathom talon
#

Oh, nvm. That's not my plugin at all. I talked to Phil, he's owner. He gave me advice where to look up, so I managed to fix his patch tho

#

I'll rewrite his plugin from a scratch soon and maybe try to submit it to Vencord official

swift delta
#

šŸ’€ ain’t no shot that plug-in would be approved for official, maybe you could get it in #1256395889354997771 tho

fathom talon
#

xd

#

I don't know atm what's rules for it

#

gonna look for submitting and other stuff

#

btw I would post it anyways, official or unofficial so

fathom talon
#

I won't submit old fixed plugin, I want to do a new one from a scratch

#

It's for screenshare extra options like bitrate, keyframes interval, codec, framerate, etc.

swift delta
fathom talon
#

Why it was unapproved?

swift delta
#

this is a discord colorways kind of thing where it’s so large and it requires such maintenance that it probably wouldn’t be approved

cedar olive
#

if it's rewritten maybe

fathom talon
#

oh ok

cedar olive
#

but it needs to be hardly reworked

fathom talon
#

I'll try my best

cedar olive
#

have a look at some other plugins to see how many files they use

#

decor for example but some others too

#

it shouldn't go too far away from that

#

or else it stars to get really messy

swift delta
#

I used to have the plug-in, and yes, if it’s rewritten that’s a different story but still as of right now I know if one thing breaks on that it turns into a crash looper especially canary and ptb

fathom talon
#

Hm, I need to do it clean and use files as less as I could to do so

fathom talon
#

But I loved this plugin much, so I'm gonna try

inner monolith
#

like figuring out what does what

inner monolith
swift delta
cyan pendant
#

I just had the idea of creating a plugin that mutes everyone (vc-wise) unless they are age verified (that being over 18), can anyone tell me if thats theoreticaly possible to make

oak sundial
#

no

#

your client does not have access to that information and would be a massive privacy problem

hushed loom
hushed loom
#

how do i make it so a command doesnt send the comamnd text in chat

dull magnet
#

don't use BUILT_IN_TEXT type

#

if you use that, it automatically sends the return value

#

use BUILT_IN

hushed loom
#

alr ty

indigo ferry
swift delta
indigo ferry
swift delta
thick sparrow
#

how would u make it so that sending messages send as replys replying to messages not just normal messages

hushed loom
#

use https://discord.sex for more info

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...

thick sparrow
thick sparrow
#

thanks

thick sparrow
#

i got timed for saying the website

terse pagoda
#

Hey šŸ™‚

I'm new in plugin dev.
Currently Im trying to add back the voice channel counter.
Therefor I try to display the text "VC" for example on the right of every voice channel.
I already figured out, that every text channel uses <a href> and every voice channel uses <a role="button">.

This is my current code but it dont display anything.

import { React, useEffect } from "@webpack/common";
import definePlugin from "@utils/types";

const addVCText = () => {
    useEffect(() => {
        const voiceChannels = document.querySelectorAll('a[role="button"]');
        
        voiceChannels.forEach((channel) => {
            const vcTextDiv = document.createElement('div');
            vcTextDiv.style.color = "#ff0000";
            vcTextDiv.textContent = "VC";
            
            const childrenDiv = channel.querySelector('.children_d8bfb3');
            if (childrenDiv) {
                childrenDiv.appendChild(vcTextDiv);
            }
        });
    }, []);
};

export default definePlugin({
    name: "VoiceChannelVC",
    description: "Adds a 'VC' text next to voice channels",
    authors: ["Devs.Nieme"],

    startTime: 0,

    patches: [
        {
            find: "renderConnectionStatus(){",
            replacement: {
                match: /(?<=renderConnectionStatus\(\)\{.+\.channel,children:)/,
                replace: (match: string, group: string) => {
                    addVCText();
                    return match;
                }
            }
        }
    ]
});

I dont know where the problem is to display that.

dull magnet
#

and your replace must return a string of code

terse pagoda
# dull magnet don't use dom manipulation

ok, I use it from react then and it should return a string of code but still it dont show anything :/

    patches: [
        {
            find: /\.channelName,children:.*\)/,
            replacement: ({ args }) => {
                return `{
                    ...${args[0]},
                    children: React.createElement('div', {
                        style: { display: 'flex', alignItems: 'center', gap: '4px' }
                    }, [
                        ${args[0]}.children,
                        React.createElement('span', {
                            style: { color: '#ff0000', fontWeight: 'bold' }
                        }, 'VC')
                    ])
                }`;
            }
        }
    ]
});
vast karma
#

Where do you think this React would be defined

#

Just call a function on $self

#

And what's with that ({args}) => syntax? That function gets the regex matches, nothing else

terse pagoda
# vast karma And what's with that `({args}) =>` syntax? That function gets the regex matches,...

issnt that what React.createElement does?
I mean, I mentioned the replacement: ({ args }) there.

even if I do it with self, it wont show up.

    onLoad() {
        this.addVCLabel = (originalCode: string) => {
            return originalCode.replace(
                ".channelName,children:",
                ".channelName,children: (props => ({ ...props, children: [props.children, ' (VC)'] })), children:"
            );
        };
    },

    patches: [
        {
            find: /\.channelName,children:.*\)/,
            replacement: function (match) {
                return this.addVCLabel(match);
            }
        }
    ]
vast karma
#

Have you looked at how patches are used in the hundreds of other plugins

terse pagoda
terse pagoda
# vast karma Have you looked at how patches are used in the hundreds of other plugins

yes, I looked at "callTimer":

    patches: [{
        find: "renderConnectionStatus(){",
        replacement: {
            match: /(?<=renderConnectionStatus\(\)\{.+\.channel,children:)\i/,
            replace: "[$&, $self.renderTimer(this.props.channel.id)]"
        }
    }]```
and thats how I did it at the start.

```js
    onLoad() {
        this.addVCLabel = (channelName: string) => `${channelName} (VC)`;
    },

    patches: [{
        find: ".channelName,children:",
        replacement: {
            match: /(?<=\.channelName,children:)/,
            replace: "$&, props => ({ ...props, children: $self.addVCLabel(props.children) })"
        }
    }]
});
vast karma
#

And why are you making children a function when it wasn't before?

#

children:, props => is not valid syntax, either

terse pagoda
#

so just replace: " $self.addVCLabel($&) "?

vast karma
#

Check with patch helper that what you're doing looks right

dull magnet
#

do you understand that match and replace is a simple text replace on Discord's code?

#
discordsCode.replace(match, replace);
terse pagoda
terse pagoda
hushed loom
#

just use a custom component

swift delta
hushed loom
#

also why do you want something like this

#

curious about the use case

swift delta
#

I dont how to explain it

#

just forget this question

hushed loom
#

😭

cedar olive
#

perhaps

swift delta
# hushed loom curious about the use case

I have a settings option that’s required for the plug-in to function so I have it hidden, but it does this weird thing. So I was wondering if there’s a way to show it but not actually let people interact with it.

hushed loom
#

thats what ive done with my plugins

#

or use datastore

#

if it doesnt need to be synced

cedar olive
#

you could also use privateSettings

proud parrotBOT
cedar olive
#

you have to handle defaults manually on those

swift delta
# hushed loom if it doesnt need to be synced

it does need to be synced and it’s also a restart: required so the moment you turn on the plug-in it prompt you to restart, even though the plug-in doesn’t have any patches so it shouldn’t prompt you

proud parrotBOT
hushed loom
cedar olive
#

however try using disabled: true first

hushed loom
cedar olive
#

oh I was sure it existed?

hushed loom
#

might not be on bool

cedar olive
swift delta
hushed loom
cedar olive
#

you might be able to set an empty patches are to force a restart on plugin enable

cedar olive
#

I hate it

#

PinDMS should be using that for categories

hushed loom
#

and it was not a fun time

cedar olive
#

I mean for Datastore most times you should just have a local cache

#

and update Datastore on change

hushed loom
#

yea, but that was also like my first time ever using react 😭

hushed loom
#

i just init'ed it on plugin start

swift delta
#

i hate when yall people start with the nerd talk

hushed loom
shrewd tundraBOT
cedar olive
#

patches: []

swift delta
# cedar olive <@929208515883569182> ^^

I mean, yeah I can try that. Still left with this weird thing though, which is what I’m hoping I can fix by showing it but not actually letting people use it.

#

Where it shows a Settings column, but there’s nothing in there

hushed loom
#

wait i need that plugin

#

what api does it use

cedar olive
#

do you still have the hidden setting?

swift delta
#

@hushed loom bro just husks to husk some times

#

I swear to God, I will put you my block list so you can’t reaction me

swift delta
# cedar olive do you still have the hidden setting?

I need to do some work on the plug-in, but as of right now, the settings option being enabled is required for the plug-in to even work, even if restart required isn’t actually tied to that Settings option

humble tulip
flint bronze
#

maybe replace the green placeholder with a preview of if it was placed there set to half opacity or something like that

humble tulip
#

I need to sort out the flickering

unkempt kindle
#

and if so

#

why

humble tulip
amber basin
#

can i ask what #{intl::GUILD_OWNER} means? updating an old plugin and found that bc moreuserdecorations patches the same module

#

used to use .Messages.GUILD_OWNER,

cedar olive
#

it's basically a macro

#

it gets transformed automatically to the hashed version of the GUILD_OWNER message string

#

but also with a little more to make it a find and not match the translations file

#

run Vencord.Util.canonicalizeMatch("#{intl::GUILD_OWNER}") to see what it becomes

hushed loom
hushed loom
#

@azure fossil do you have react devtools enabled

azure fossil
#

i think i disabled them last time cause it was crashing me

#

and i forgor how to enable

hushed loom
azure fossil
#

dumb me was searching in discord dev options

#

alr

#

wait

past jackal
#

how do i replace fetch messages function? I need to process all messages before displaying them

past jackal
#

tried this one doesnt work

#

SHIT

#

thats fetchmessage

#

welp

#

still didnt work

#

hey how did you end up doing it?

#

never mind, it works

vast karma
#

Now stop hardcoding the variable names, and remove those pointless whitespace checks

past jackal
#

i realized that its not the same in the source

#

cause i copied what i saw in the source

#

which was something like this

#

also now

#

i have an issue where if i open a channel second time

#

nothing happens

#

doesnt pass through fetch messages

#

it works only ones

#

i tried this and it didnt work

flint bronze
#

why do you need a getter

#

besides what are you trying to do?

past jackal
#

i want to add an embed to all messages that have a spotify link and do not have the embed for that link

flint bronze
#

the embeds are implemented like default embeds, just with a custom renderer

past jackal
#

i already did everything

#

i just need

#

to make it work with cached messages

#

it works once and then when i reopen the channel its gone

flint bronze
#

you might have to find a different find though

rocky lynx
#

i assume because its a minified variable that can change

flint bronze
#

that's a random variable name that could change

past jackal
#

its 2:30 am right now

#

all i want is to make it work

#

the fact that there is some variable that i can just replace with regex is really not bothering me right now

#

i have tested it before building , its there

#

it simply works only once

flint bronze
#

once as in

  • first time loaded on client
  • when recieved from gateway
past jackal
#

yeah first time it loads

#

then it doesnt do anything, not triggered

#

after i click another channel basically

#

im not sure what other function needs to get patched here

flint bronze
past jackal
#

where exactly

flint bronze
past jackal
#

and what should i do instead

#

i noticed theres getMessages()

flint bronze
#

move the messages: into the lookbehind and remove everything but the $self.editMessages($1,this) from the replace

#

does it work then?

#

i don't actually know if the getter will have anything to do with it or not

past jackal
#

certainly not

flint bronze
#

i bet it is also likely the fetch local messages functions in this module have something to do with it

past jackal
#

it works

flint bronze
#

okay

past jackal
#

the method works

#

but only once

#

im doing it like the other plugin

#

which works normally

flint bronze
#

what other plugin

past jackal
rocky lynx
#

i want to make another plugin, but i have no ideas

thick sparrow
thick sparrow
#

a ring all plugin

#

adds a button to the context menu of a group

#

and rings everybody who isnt in a call

#

or isnt currently being ringed

hushed loom
#

is it possible to evalulate css and get the value in javascript

#

(this is prob xy)

cedar olive
#

wdym value in JavaScript

hushed loom
#

trying to do a feature where you can set a min contrast value for RCE

cedar olive
#

evaluate to "check for errors"?

hushed loom
#

to check the contrast

cedar olive
#

don't think so

hushed loom
#

guhhhhh

#

any ideas on how to go about getting the value of that

cedar olive
#

not really

hushed loom
#

@cedar olive solved it

#

i just asked github copiliot to do it for me

#

and it provided working code blobcatcozy

hushed loom
#

@swift delta remember that settings question you had last night

#
const settings = definePluginSettings({
mySetting: {
  type: bool,
  desc: "123",
  default: true
}}, {
  mySetting: {
    disabled: () => true
  }
});
rocky lynx
#

interesting

terse pagoda
#

How do I get every channel to have for example a emoji to his name?
Currently Im trying to get every channel via placeholder-channel-id and VIEW_CHANNEL match.

    patches: [{
        find: '"placeholder-channel-id"',
        replacement: [
            {
                match: /if\(!\i\.\i\.can\(\i\.\i\.VIEW_CHANNEL.+?{if\(this\.id===\i\).+?threadIds:\[\]}}/,
                replace: (match, channel, object) => {
                    logger.info("Match: ", match);  
                    logger.info("Channel: ", channel);
                    
                    if (typeof channel === "object") {
                        logger.info("Object:", JSON.stringify(channel, null, 2));
                    } else {
                        logger.error("Is not a Object:", channel);
                        return match;
                    }
                }
            }
        ]
    }]
swift delta
unkempt kindle
unkempt kindle
terse pagoda
meager palm
#

im gonna make a pluralkit helper plugin
i need help because obviously ive never written a plugin so

for starters im thinking of somehow replacing webhook messages with real psuedo-accounts and making it so when you click on the username/avatar the actual account pops up

#

i think i need to use the flux thingy right

iron epoch
hushed loom
hushed loom
#

Look on the stores object with console shortcuts enabled

past jackal
#

how to play a ping sound?

iron epoch
# past jackal how to play a ping sound?

I think pings are triggered by a message listener, try searching by the event name to find the function that triggers the ping sound, I think there is a plugin named keywordnotify that does the same thing

#

unoffical plugin*

humble tulip
#

I think keyword notify just intercepts the message create event and adds a mention to the message object to do that, I don't think there's anything specific to play the ping

terse pagoda
terse pagoda
hushed loom
#

might be stupid, but why can i use a hook here

#

webpack module 421399

cedar olive
#

hooks just need to be in the context of rendering a component

#

they can be placed anywhere in the code

hushed loom
#

does this not count as the rendering context

cedar olive
#

so like when react starts rendering your component they store that somewhere in the code and when you call the hook it uses the context of whatever is currently saved

#

aka the function currently being called

#

that has to be how because there's no other way they would know what component the hook belongs to

cedar olive
hushed loom
#

i really didnt want to have to move everything up, but i think i have to and just use a var

cedar olive
#

you want the top level component to get re-rendered?

hushed loom
#

no

#

trying to patch the username and its rendered in a weird way

cedar olive
#

what's wrong about it

cedar olive
hushed loom
#

throws the error where it says hooks can only be at the top level

hushed loom
cedar olive
#

oh yeah you gotta patch this

hushed loom
#

not always called

cedar olive
#

that's weird tho, you are overwriting the color right?

cedar olive
hushed loom
#

unless there is some other way to do that

cedar olive
#

i dont really see how that's not working

cedar olive
past jackal
#

still don't understand how I can process messages that are getting added to cache

humble tulip
#

I kinda just threw together what worked but I don't know that it's the way to do it

hushed loom
vast karma
#

You probably want to use useCallback on those callbacks

#

To make sure you get the same function object when it rerenders

humble tulip
#

Thank

#

I'll try that out later

humble tulip
#

I just tried wrapping them all in useCallback, the only thing that changed was that the dragOver handler ended up being shared between main and thread sidebar chats so you could reorder one with a dragged attachment from the other

vast karma
#

Huh

humble tulip
#

Couldn't drop in though, that could maybe be cool but too niche to do anything with

vast karma
#

I would expect that without useCallback, that global drag listener wouldn't be cleared properly

humble tulip
#

I call dragAndDropVars when the attachment list component is rendered so I think it only creates those vars within that context each time, so they're kept within that scope

#

This is with useCallback ^

#

Oh wait it does happen without as well, my bad

#

I swear it didn't happen when I tested the first time lol

humble tulip
#

Turns out it's because I wasn't unsetting heldItem on drop so bringing the attachment over meant the other list just assumed the last heldItem was still held

vast karma
#

Maybe a stupid question, but you've checked that it actually affects the order they're uploaded in, right?

#

And isn't just affecting the rendering

humble tulip
#

Yeah, you can see it in the preview gif

humble tulip
#

Also the PR mentions a conflict in contants.ts, I assume there's no point resolving that until it's gonna be merged?

hushed loom
#

it can be resolved at any point

humble tulip
#

Cool, I'll just leave it

dull magnet
#

your replace must be a string

#

typeof channel === "object" makes no sense. your channel variable is a string

#

this is just not how patches work

#

code.replace(match, replace)

#

your replace should not contain any logic

#

its only purpose is returning a string with the new code

terse pagoda
dull magnet
#

try to look at other functions to figure it out

#

there are tons of plugins that retrieve channels

terse pagoda
dull magnet
#

yes that's right

#

you should figure it out within 10 seconds if you look at what methods are available on ChannelStore

#

they have intuitive names

terse pagoda
# dull magnet they have intuitive names

ChannelStore: euaddChangeListener: e=>{this.listeners.add(e)}addConditionalChangeListener: ʒ (t)addReactChangeListener: e=>{this.listeners.add(e)}removeChangeListener: e=>{this.listeners.delete(e)}removeReactChangeListener: e=>{this.listeners.delete(e)}__getLocalVars: undefined_changeCallbacks: i {listeners: Set(0), add: ʒ, remove: ʒ, addConditional: ʒ}_dispatchToken: "ID_22"_dispatcher: h {_defaultBand: 2, _interceptors: Array(2), _subscriptions: {…}, _waitQueue: Array(0), _processingWaitQueue: false, …}_isInitialized: true_mustEmitChanges: undefined_reactChangeCallbacks: i {listeners: Set(147), add: ʒ, remove: ʒ, addConditional: ʒ}_syncWiths: (2) [{…}, {…}][[Prototype]]: _

dull magnet
#

expand the prototype

terse pagoda
dull magnet
#

there is more than just getChannel

terse pagoda
#
addChangeListener: e=>{this.listeners.add(e)}
addConditionalChangeListener: ʒ (t)
addReactChangeListener: e=>{this.listeners.add(e)}
removeChangeListener: e=>{this.listeners.delete(e)}
removeReactChangeListener: e=>{this.listeners.delete(e)}
__getLocalVars: undefined
_changeCallbacks: i {listeners: Set(0), add: ʒ, remove: ʒ, addConditional: ʒ}
_dispatchToken: "ID_22"
_dispatcher: h {_defaultBand: 2, _interceptors: Array(2), _subscriptions: {…}, _waitQueue: Array(0), _processingWaitQueue: false, …}
_isInitialized: true
_mustEmitChanges: undefined
_reactChangeCallbacks: i {listeners: Set(183), add: ʒ, remove: ʒ, addConditional: ʒ}
_syncWiths: (2) [{…}, {…}]
[[Prototype]]: 
_
constructor: class eu
getAllThreadsForParent: getAllThreadsForParent(e){return l().values(w).filter(t=> {…}
getBasicChannel: ʒ getBasicChannel(e)
getChannel: ʒ getChannel(e)
getChannelIds: ʒ getChannelIds(e)
getDMChannelFromUserId: ʒ getDMChannelFromUserId(e)
getDMFromUserId: ʒ getDMFromUserId(e)
getDMUserIds: ʒ getDMUserIds()
getDebugInfo: getDebugInfo({return{loadedGuildIds:Array.from(B).sort(b.default.compare),pendingGuildLoads:Object.keys(G).sort(b.default.compare),guildSizes:Object.keys(D).sort(b.default.compare).map(e=> {…}
getGuildChannelsVersion: ʒ getGuildChannelsVersion(e)
getInitialOverlayState: ʒ getInitialOverlayState()
getMutableBasicGuildChannelsForGuild: ʒ getMutableBasicGuildChannelsForGuild(e)
getMutableDMsByUserIds: ʒ getMutableDMsByUserIds()
getMutableGuildChannelsForGuild: ʒ getMutableGuildChannelsForGuild(e)
getMutablePrivateChannels: ʒ getMutablePrivateChannels()
getPrivateChannelsVersion: ʒ getPrivateChannelsVersion()
getSortedPrivateChannels: getSortedPrivateChannels(){return l()(L).values().sort((e,t)=> {…}
hasChannel: ʒ hasChannel(e)
initialize: ʒ initialize()
loadAllGuildAndPrivateChannelsFromDisk: 
ʒ loadAllGuildAndPrivateChannelsFromDisk()
[[Prototype]]: 
Object
constructor: 
class _
emitChange: ʒ emitChange()
getDispatchToken: ʒ getDispatchToken()
getName: ʒ getName()
initialize: ʒ initialize()
initializeIfNeeded: ʒ initializeIfNeeded()
mustEmitChanges: mustEmitChanges(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:()=> {…}
registerActionHandlers: registerActionHandlers(e,t){this._dispatcher.register(this.getName(),e,e=> {…}
syncWith: syncWith(e,t,n){if(this.waitFor(...e),null!=n){var r,i;let a,s=0,o=()=> {…}
waitFor: waitFor(){for(var e=arguments.length,t=Array(e),n=0;n<e;n++)t[n]=arguments[n];let r=t.map((e,t)=> {…}
[[Prototype]]: 
Object
constructor: ʒ Object()
hasOwnProperty: ʒ hasOwnProperty()
isPrototypeOf: ʒ isPrototypeOf()
propertyIsEnumerable: ʒ propertyIsEnumerable()
toLocaleString: ʒ toLocaleString()
toString: ʒ toString()
valueOf: ʒ valueOf()
__defineGetter__: ʒ __defineGetter__()
__defineSetter__: ʒ __defineSetter__()
__lookupGetter__: ʒ __lookupGetter__()
__lookupSetter__: ʒ __lookupSetter__()
__proto__: (...)
get __proto__: ʒ __proto__()
set __proto__: ʒ __proto__()
dull magnet
#

it has everything you need

terse pagoda
# dull magnet it has everything you need
import definePlugin from "@utils/types";
import { Devs } from "@utils/constants";
import { Logger } from "@utils/Logger";
import { ChannelStore } from "@webpack/common";
const logger = new Logger("AddVCLabelToChannels", "#ff0000");

export default definePlugin({
    name: "AddVCLabelToChannels",
    description: "Adds Usercounter back to every voice channel",
    authors: [Devs.Nieme],

    start() {
        logger.info("AddVCLabelToChannels Plugin gestartet!");

        const channels = ChannelStore.getMutableGuildChannelsForGuild('?');
        const channelArray = Object.values(channels);
        for (const channel of channelArray) {
            if (channel.type === 2 && !channel.name.includes("(VC)")) {
                channel.name = `${channel.name} (0/${channel.userLimit_}VC)`;
                logger.info(`Ƅndere Namen von Kanal ${channel.id} zu ${channel.name}`);
            }
        }
    },

    stop() {
        logger.info("AddVCLabelToChannels Plugin gestoppt!");
    }
});

First of all, thank you @dull magnet.
That worked fine.
Now I need to figure out how to get GuildId and how much are currently connected to the channel ^^

terse pagoda
vast karma
#

Okay that's not dom manip, I'll give you that

#

But it's not much better

terse pagoda
vast karma
#

More that you're editing data rather than appearance, and that it'll trigger only when discord starts and not when, say, a new channel is added

terse pagoda
unkempt kindle
terse pagoda
unkempt kindle
#

also
im not exactly sure .getMutableGuildChannelsForGuild is a function

#

there's a ByGuild one

terse pagoda
#

and yes, it updates:

#

Removed VC from the bubble.
And if its unlimited it shows like this:

north flame
#

revolutionary new idea

flint bronze
north flame
#

all attachments turn into ads

flint bronze
#

on the right sidebar

flint bronze
north flame
#

ooh

north flame
flint bronze
#

I never made it

#

I had the idea

north flame
#

I can prob check membercount plugin

flint bronze
#

yes

#

do that

flint bronze
#

put a real ad there please

#

i need to see it

north flame
#

will once the PoC is completer

#

any other ideas for places?

#

gonna change all the user/server icons hopefully

flint bronze
north flame
flint bronze
#

good

#

you should be husking

quick zephyr
#

do I have to do something special to get the "components" option to show up in dev tools after enabling it in the settings and restarting

#

ah ran the repair installer and it shows up

quick zephyr
#

how are you meant to find the functions a store has. discord dev tools just showing me "Store is missing __getLocalVars method." for everything

vast karma
#

Just inspect the object in browser dev tools

quick zephyr
#

inspect the store?

vast karma
#

It's a js object

quick zephyr
#

how am I meant to find the store in the browser dev tools

vast karma
#

Vencord.Webpack.Common.GuildStore

cedar olive
#

why does everyone use discord devtools

#

it's kinda shit

vast karma
#

Whaddya mean kinda

cedar olive
#

it is shit*

quick zephyr
#

I searched this channel for how to find stores and of only 2 results 1 is useless and 1 says to use the dev tools

cedar olive
#

only useful for changing the settings it has on it

vast karma
#

Yes, dev tools

#

Not discord's fake shit

quick zephyr
#

you

#

thats the only result I found on how to find store names lol

cedar olive
#

they just wanted the button for it

#

not to find stores

quick zephyr
#

how should I find stores then

vast karma
#

The useful ones are already in common

cedar olive
#

if you really want a list of all stores enable console shortcuts plugin

quick zephyr
#

the one I need isnt. well maybe I need a different one and am on a wild goose chase Shrug

cedar olive
#

and then

#

type Stores.

#

in the console

#

if you know the name already

#

oop

#

I deleted your message in accident

quick zephyr
#

nuckyz hates me

cedar olive
#

anyways as I was saying

#

if you know the name already

#

why do you want a list

#

you have to webpack find it

quick zephyr
#

I didnt want a list I wanted a way to find the list of stores to find a store I need since you said using the discord dev tools to find it (which is what I did to find StreamerModeStore) is wrong

cedar olive
#

const StreamerModeStore = findStoreLazy("StreamerModeStore")

#

in your plugin

#

or Vencord.Webpack.findStore("StreamerModeStore")

#

in the console

quick zephyr
cedar olive
#

then to find the methods

#

look in the prototype

quick zephyr
#

IT'S THERE

#

.enabled

#

discord does this fun thing where it dispatches STREAMER_MODE_UPDATE when you enable/disable streamer mode except on startup if it's pre-enabled. so I needed a way to check if streamer mode was on at startup

#

thanks for the help :D

#

oh goodie it doesnt actually work cause it returns false at start and enabled streamer mode with a delay

cedar olive
#

do you have streamer mode always enabled or is detected obs or something

quick zephyr
#

I have obs open to test this

cedar olive
#

yeah that's why

quick zephyr
#

discord auto enables streamer mode if it detects obs

cedar olive
#

it takes time to detect

#

anyways how are you using that data

quick zephyr
#

yeah so im looking for a way to detect streamer mode at start

cedar olive
#

what do you need enabled for

#

and how doesn't STREAMER_MODE_UPDATE work?

quick zephyr
#

STREAMER_MODE_UPDATE doesnt trigger at launch

#

idk why

cedar olive
#

does it not trigger when discord detects obs

quick zephyr
#

it triggers if you manually enable/disable it

#

I have the dispatcher tab in discord dev tools open and it doesnt

cedar olive
#

RUNNING_STREAMER_TOOLS_CHANGE

quick zephyr
#

yeah and 1 other event

#

im looking into them

#

STREAMING_UPDATE is the other

#

it seems to be null when streamer mode is disabled and undefined when it's enabled

#

looks like it's gotta be this setup

flux: {
    STREAMER_MODE_UPDATE(details) {
        handleStreamerMode(details.value);
    },
    RUNNING_STREAMER_TOOLS_CHANGE() {
        handleStreamerMode(StreamerModeStore.enabled);
    }
}
flint bronze
quick zephyr
#

yep but luckily it looks like I wont even need to do that. ill be able to just access StreamerModeStore.enabled in the function which gets called everytime discord refreshes the display or however it works under the hood

flint bronze
#

react hooks blobcatcozy

flint bronze
north flame
flint bronze
#

aww i cant get milkshake and online casino ads in my discord client husk

north flame
#

Wait holy moly I may have found a way

#

Will test in a bit

north flame
#

looks to just be a csp issue now

vast karma
#

What a shame

north flame
#

will check it later

#

honk mimimi time now

quick zephyr
#

is it possible to have two dropdowns in a row in the settings without a label or description on the 2nd so they appear grouped under the same setting

acoustic nest
#

Hey so uh, with pnpm watch, how do I actually make that inject into my client?

vast karma
#

Just run pnpm inject once

acoustic nest
#

alr

#

hmmm inject doesn't appear to work

#

I see no changes, even after fully restarting discord

#

it's a flatpak distribution if that changes anything

quick zephyr
#

pnpm build --watch

acoustic nest
#

yeah I did all that, no changes

#

it even says it's patched, the inject tool

quick zephyr
#

oh I see pnpm watch is a shortcut for pnpm build --watch

acoustic nest
#

oh interesting:

#

WebpackRequire was not initialized, running modules without patches instead.

#

oh wait

#

me stupid

#

forgor to update my fork

#

lmao

unkempt kindle
unkempt kindle
#

i'm trying to do this with the channelstore but i can't seem to get the data

terse pagoda
terse pagoda
# unkempt kindle i'm trying to do this with the channelstore but i can't seem to get the data

ChannelStore:

addChangeListener: e=>{this.listeners.add(e)}
addConditionalChangeListener: ʒ (t)
addReactChangeListener: e=>{this.listeners.add(e)}
removeChangeListener: e=>{this.listeners.delete(e)}
removeReactChangeListener: e=>{this.listeners.delete(e)}
__getLocalVars: undefined
_changeCallbacks: i {listeners: Set(0), add: ʒ, remove: ʒ, addConditional: ʒ}
_dispatchToken: "ID_22"
_dispatcher: h {_defaultBand: 2, _interceptors: Array(2), _subscriptions: {…}, _waitQueue: Array(0), _processingWaitQueue: false, …}
_isInitialized: true
_mustEmitChanges: undefined
_reactChangeCallbacks: i {listeners: Set(183), add: ʒ, remove: ʒ, addConditional: ʒ}
_syncWiths: (2) [{…}, {…}]
[[Prototype]]: 
_
constructor: class eu
getAllThreadsForParent: getAllThreadsForParent(e){return l().values(w).filter(t=> {…}
getBasicChannel: ʒ getBasicChannel(e)
getChannel: ʒ getChannel(e)
getChannelIds: ʒ getChannelIds(e)
getDMChannelFromUserId: ʒ getDMChannelFromUserId(e)
getDMFromUserId: ʒ getDMFromUserId(e)
getDMUserIds: ʒ getDMUserIds()
getDebugInfo: getDebugInfo({return{loadedGuildIds:Array.from(B).sort(b.default.compare),pendingGuildLoads:Object.keys(G).sort(b.default.compare),guildSizes:Object.keys(D).sort(b.default.compare).map(e=> {…}
getGuildChannelsVersion: ʒ getGuildChannelsVersion(e)
getInitialOverlayState: ʒ getInitialOverlayState()
getMutableBasicGuildChannelsForGuild: ʒ getMutableBasicGuildChannelsForGuild(e)
getMutableDMsByUserIds: ʒ getMutableDMsByUserIds()
getMutableGuildChannelsForGuild: ʒ getMutableGuildChannelsForGuild(e)
getMutablePrivateChannels: ʒ getMutablePrivateChannels()
getPrivateChannelsVersion: ʒ getPrivateChannelsVersion()
getSortedPrivateChannels: getSortedPrivateChannels(){return l()(L).values().sort((e,t)=> {…}
hasChannel: ʒ hasChannel(e)
initialize: ʒ initialize()
loadAllGuildAndPrivateChannelsFromDisk: 
ʒ loadAllGuildAndPrivateChannelsFromDisk()
[[Prototype]]: 
Object
constructor: 
class _
emitChange: ʒ emitChange()
getDispatchToken: ʒ getDispatchToken()
getName: ʒ getName()
initialize: ʒ initialize()
initializeIfNeeded: ʒ initializeIfNeeded()
mustEmitChanges: mustEmitChanges(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:()=> {…}
registerActionHandlers: registerActionHandlers(e,t){this._dispatcher.register(this.getName(),e,e=> {…}
syncWith: syncWith(e,t,n){if(this.waitFor(...e),null!=n){var r,i;let a,s=0,o=()=> {…}
waitFor: waitFor(){for(var e=arguments.length,t=Array(e),n=0;n<e;n++)t[n]=arguments[n];let r=t.map((e,t)=> {…}
[[Prototype]]: 
Object
constructor: ʒ Object()
hasOwnProperty: ʒ hasOwnProperty()
isPrototypeOf: ʒ isPrototypeOf()
propertyIsEnumerable: ʒ propertyIsEnumerable()
toLocaleString: ʒ toLocaleString()
toString: ʒ toString()
valueOf: ʒ valueOf()
__defineGetter__: ʒ __defineGetter__()
__defineSetter__: ʒ __defineSetter__()
__lookupGetter__: ʒ __lookupGetter__()
__lookupSetter__: ʒ __lookupSetter__()
__proto__: (...)
get __proto__: ʒ __proto__()
set __proto__: ʒ __proto__()
unkempt kindle
#

how did you get that

#

did you just log it

humble tulip
#

The t in your screenshot there is the text rendered on the channel list, so you just want to manipulate t and you're good

unkempt kindle
vast karma
#

Some patches are horrific

humble tulip
#

That's kinda just how it is, I think the find I provided back then would be fine for the foreseeable

vast karma
#

Just a big pile of symbols

humble tulip
#

If it breaks it just means searching for the module again and trial and erroring a better one

vast karma
#

But as long as they work, that's not an issue

terse pagoda
unkempt kindle
#

because that seems like a really bad select

vast karma
#

That's really bad yeah

humble tulip
#

I just did this

unkempt kindle
#

that's what i selected when i did try out that one
and it worked
but i was not happy with that

humble tulip
unkempt kindle
#

why specifically the .scrollWidth&&(null) part

humble tulip
#

It just seemed like the most unique part of the module without variable names in it

unkempt kindle
humble tulip
#

You can use regex in finds so you could just \i but most don't seem to use that so I dunno if it's less preferred

humble tulip
unkempt kindle
#

is this a jetbrains ide

humble tulip
humble tulip
#

Yeah I figured

cedar olive
#

i should have still allowed finds to be array

humble tulip
#

I only found out vencord was even a thing a few months ago so I'm by no means an expert on anything lol, take everything with a grain of salt

cedar olive
#

even if regex is more powerful you can still mix a string and then a regex

#

to avoid actually having to check the regex in 99% cases

#

which would make it pretty much no difference in speed

humble tulip
#

Basically fallback regex

cedar olive
#

yeah

#

It's really simple and powerful

#

just gotta write the order in the array correct

unkempt kindle
vast karma
#

Probably it found some other children: without it

#

Such as the children:n=>

unkempt kindle
#

oh wait yeah

#

i see

quick zephyr
#

is there a way to wipe a specific plugin's settings

humble tulip
#

Yeah it matches this otherwise

humble tulip
unkempt kindle
#

part of the reason i preferred the ChannelStore method is that i did not find a way to edit this
from the components tab i couldn't even get a prop with this text

sinful valve
#

Hello! Not sure if I can ask this in this channel, butttttttt does anyone know if there is already a plugin for categorizing your friends/chats? Because I want to create one if there isn't any yet. What I mean by categorizing is: being able to create categories, expand/ hide them and add/remove friends/chats from it.

This is thee general idea and concept, so is there anything like this already? Thank you.

acoustic nest
#

How do I find the right string for contextMenus

#

I want to add a menu option to the current user profile popup on the bottom left

#

is that even considered a context menu

humble tulip
#

Inspect element and look at the id of the menu

#

But no, that's not a context menu

acoustic nest
#

hey folks I'm trying to inject into the profile menu but it seems there's two modules for it, and they're both damn near equivalent in code and differ only very slightly, this is making it very hard to write a find for it.

#

search for PRESS_SWITCH_ACCOUNTS and you'll find both

#

I'd appreciate some help

#

\[\(0,\i\.jsx\)\(\i\.\i,\{id:"switch-accounts seems to work for now

bronze dove
acoustic nest
#

oh nice

quick zephyr
#

ive been cooking for so long I might have overcooked šŸ˜”

acoustic nest
#

lol

#

anyone know what component this is?

#

sorry for the many questions, I am new to this

quick zephyr
#

rate the cooking degree (modifying showMeYourName)

acoustic nest
#

is that like streamer mode

quick zephyr
#

yeah I originally just wanted to add streamer mode detection

#

then I got carried away

acoustic nest
quick zephyr
acoustic nest
#

figured it out since

quick zephyr
#

šŸ‘

terse pagoda
# unkempt kindle part of the reason i preferred the ChannelStore method is that i did not find a ...

This is my current code:

import definePlugin from "@utils/types";
import { Devs } from "@utils/constants";
import { ChannelStore, SelectedGuildStore } from "@webpack/common";
import { findStoreLazy } from "@webpack";


let unsubscribeGuildChange;
let unsubscribeChannelChange;

const VoiceStateStore = findStoreLazy("VoiceStateStore");
const GuildStore = findStoreLazy("GuildStore");

const getUserCountInChannel = (channelId) => {
    if (!VoiceStateStore) {
        return 0;
    }

    const voiceStates = VoiceStateStore.getVoiceStatesForChannel?.(channelId);
    if (!voiceStates) {
        return 0;
    }

    return Object.keys(voiceStates).length;
};

export default definePlugin({
    name: "LabelToSelectedGuild",
    description: "Adds Userlimit back to discord voice channels",
    authors: [Devs.Nieme],

    start() {
        const processChannels = (guildId) => {
            if (!guildId) {
                logger.warn("No selected guild found!");
                return;
            }

            const channels = Object.values(ChannelStore.getMutableGuildChannelsForGuild(guildId));
            const voiceChannels = channels.filter(channel => channel.type === 2);
            const guildName = GuildStore.getGuild(guildId)?.name || "Unknown";
            
            for (const channel of voiceChannels) {
                if (channel.type === 2) {
                    const userCount = getUserCountInChannel(channel.id);
                    const userLimit = channel.userLimit || "āˆž";
                    const newLabel = `${userCount}/${userLimit}`;

                    const channelElement = document.querySelector(`[data-list-item-id="channels___${channel.id}"]`);
                    if (channelElement) {
                        const childrenDiv = channelElement.querySelector(".children_d8bfb3");

                        if (childrenDiv) {
                            let labelDiv = childrenDiv.querySelector(".custom-vc-label");
                            if (!labelDiv) {
                                labelDiv = document.createElement("div");
                                labelDiv.className = "numberBadge_d8bfb3 numberBadge_df8943 base_df8943 eyebrow_df8943 baseShapeRound_df8943";
                                labelDiv.style.fontWeight = "100";
                                labelDiv.style.padding = "4px";
                                labelDiv.style.color = "#bbb";
                                labelDiv.classList.add("custom-vc-label");
                                childrenDiv.prepend(labelDiv);
                            }

                            labelDiv.textContent = newLabel;
                        }
                    }
                }
            }
        };

        const onGuildChange = () => {
            const guildId = SelectedGuildStore.getGuildId();
            const guildName = GuildStore.getGuild(guildId)?.name || "Unknown";
            processChannels(guildId);
        };

        const onChannelChange = () => {
            const guildId = SelectedGuildStore.getGuildId();
            const guildName = GuildStore.getGuild(guildId)?.name || "Unknown";
            if (guildId) {
                processChannels(guildId);
            }
        };

        unsubscribeGuildChange = SelectedGuildStore.addChangeListener(onGuildChange);
        unsubscribeChannelChange = ChannelStore.addChangeListener(onChannelChange);

        onGuildChange();
    },

    stop() {
        if (unsubscribeGuildChange) unsubscribeGuildChange();
        if (unsubscribeChannelChange) unsubscribeChannelChange();
    }
});
humble tulip
#

CollapsibleCodeblocks plugin next

hushed loom
fathom pivotBOT
#

Alright @hushed loom, in 1 day: …

vast karma
#

Lsp in code blocks plz

worn void
#

Hi. I apologize if this question seems silly, because I just started learning about plugin development today, and I can't find any documentation on how to create plugins.
What is the point: As I realized, the plugin can simply replace a line in the js code discord with regex, and I started using this code to search for the line I need and replace the value in one of the variables in it:

patches: [
        {
            find: "={url:n,e",
            replacement: {
                match: /url: n/g,
                replace: `url: "${h}"`
            }
        }
    ]

But the result that I wanted (replacing the image on my screen demo preview) doesn't work. Could you please help me to find a solution to the problem or materials that will help me to understand the problem. Thank you very much in advance

jagged briar
#
  • your find uses variable names, which you should not use as discord's minifier changes variable names every update basically.
  • we use a special regex indentifier for variable names, \i (don't use in find unless absolutely necessary)
  • use capture groups () to use that string in your replacement with $1, $2 etc
  • since h isn't in your matched code, you can't actually use it in your replacement. try adding lookbehinds or just extending your match to get that variable.
  • your just replacing strings of code. h doesn't actually exist in your plugin's code, but in discord's code. thus you should replace ${h} with a capture group that captures the variable name of h.
vast karma
#

Also /url: n/g will very likely match nothing whatsoever, since there are no spaces in the minified code

hushed loom
#

Also your replace will throw a error as your template string is in the wrong place

worn void
#

Thank you all. Your advice helped me

north flame
#

do not add ads to every div

flint bronze
#

do it

north flame
#

works better if I target navs

north flame
#

I'm sooooo flippin cloise!

north flame
#

Ok it's working now, if anybody wants to DM me some ads to include, feel free, must follow {title: string, image: string, href: string}

tropic ice
north flame
tropic ice
#

oh that makes much more sense lmao

north flame
#

working image

#

What I need is to find an API that returns close enough data

tropic ice
#

ok I have one but don't have the image yet because I'm on mobile and am lazy
the image will be a ss of a yt vid though

north flame
#

It's funny how as you move around Discord, the ads naturally just pileup in the correct places (where google adsense usually places them)

tropic ice
#

ok dmed it to you

quick zephyr
#

Is there a way to include stickers in a command's response?

export interface CommandReturnValue {
    content: string;
    /** TODO: implement */
    cancel?: boolean;
}

I tried adding stickers and stickerIds to this but neither worked.

north flame
#

API docs?

quick zephyr
#

Sorry?

quick zephyr
#

you have a link to that?

quick zephyr
#

you definitely can include stickers in bot interaction responses. ive done it before

#

I just cant get it to work with vencord's built-in implementation

quick zephyr
#

damn ok

#

Then followup question, is there a way to prevent vencord commands from sending a response to chat

north flame
#

Why not just do an ephemeral "done"?

quick zephyr
#

Cause that's clunky. If I use SendMessage to send the sticker it'd weird to have a 2nd message sent even if it's ephemeral

cedar olive
quick zephyr
#

omg it worked I love you

#

I spent so long fucking around with registerCommand, execute, and _handleCommand the other night over this

acoustic nest
unkempt kindle
#

i don't really get this
what is Pluralkit

acoustic nest
#

it's an accessibility tool for people with DID

#

is DID the right term?

unkempt kindle
#

i don't know what DID is

acoustic nest
#

I'll let someone who actually has it describe it

unkempt kindle
#

what

humble tulip
#

Dissociative identity disorder

#

I mean just google pluralkit tbh, probably easiest

quick zephyr
acoustic nest
#

they are pluralkit webhooks yes

quick zephyr
#

ah so managed by pluralkit ok

#

cause I was gonna say could you just intercept the message on send and call the webhook instead of send, copy, delete. but if you dont control the webhook then FaunaShrug

steady knot
acoustic nest
#

How do I make my plugin detect settings changes?

#

It connects to an API so like, if the user's PK token changes then I kinda need to know

#

should've read this earlier, silly me

#

now what

quick zephyr
acoustic nest
#

vencord settings

quick zephyr
#

FluxDispatcher.dispatch and FluxDispatcher.subscribe I imagine

#

dispatch a custom event for your plugin and subscribe to it

humble tulip
#

You can use useSettings, it's a react hook for settings changes

acoustic nest
#

I really hope I can somehow get an exception or smtn

#

it'd really suck if not

#

I've already been told by several plural people that this would be so useful to them

#

but it needs their API key to work

humble tulip
#

I don't think an exception will be made for a built in plugin but maybe it could be in #1256395889354997771

#

External APIs are allowed there but I don't know about keys

acoustic nest
#

rules say no

quick zephyr
#

what do you need their api for

acoustic nest
#

switching fronters

#

I need to tell pluralkit to switch through their API

quick zephyr
#

Could you instead detect which account is active, intercept the message, append the prefix for that account (such as message -> {message}), send the message and have it work the same

#

achieves the same goal of not having to prefix everything manually

acoustic nest
#

which account is active is a public thing, I can use the API without a key for that

quick zephyr
#

I meant which is active on the client

#

cant pluralkit detect the identity based on wrappers? saw that on their site

#

like sending {hello} and [hello] would send as different identities

acoustic nest
#

yeah that might work

quick zephyr
#

not sure how intercepting the message would work though

acoustic nest
#

yeah my thoughts too

quick zephyr
#

probably gonna have to find the component that handles sending messages

acoustic nest
#

overall it'd kinda suck tho bc

#

the person would need to have their privacy settings set to public

quick zephyr
#

why

acoustic nest
#

for me to be able to query which members they even have

quick zephyr
#

ah

#

do it manually. prompt them for a name and the wrapper to use for the message and save that to settings I guess

#

name is just for display in the account picker. wrapper will be handeled by the pk bot

quick zephyr
#

just that you gotta add a disclaimer an external api is used

acoustic nest
#

I'll try to remove the requirement for an API key for now

#

but it will still use the public API

humble tulip
#

ClearURLs uses it

acoustic nest
#

I've already described that -J

unkempt kindle
#

oh wait yeah

#

i just don't really get how the webhook thing is related to DID

quick zephyr
#

the webhook represents which identity is active

unkempt kindle
#

ahh

flint bronze
#

@acoustic nest what is stopping you from implementing it using discord oauth to get the api key automatically

#

is that possible? or against their ToS

acoustic nest
#

idk wym but I need a pluralkit api key

#

either way, got it working

humble tulip
#

Pretty cool

#

Maybe you should add something near or in place of the username/icon in the bottom left for the active proxy

flint bronze
flint bronze
humble tulip
#

I meant as an easier way to see what's currently active but that too

#

But yeah I am also not the target user lol

unkempt kindle
unkempt kindle
# acoustic nest

is the selector only used to append the different endings to messages and from there some discord bot does it?

acoustic nest
#

Yes

quick zephyr
acoustic nest
#

Yeah I thought of this but was unsure how I’d stop them sending. Then I forgor

quick zephyr
#

I'd probably just truncate the message however many characters you need at that point

acoustic nest
north flame
# acoustic nest

Ngl it looks more complicated/slower than just manually putting ā€œC:<message>ā€

#

And I’d assume the users who need this aren’t the type to just forget their prefixes

fathom pivotBOT
#

@hushed loom, <t:1732816659:R>: …

thick sparrow
#

how would u check if ur the group owner or not

hoary pilot
unkempt kindle
#

i remembered like people already made a plugin to remove emojis from channel names
couldn't find it so i thought it was just a dream but now i've noticed two plugins that do that in #1032200195582197831
so apparently im not the only one who wants that

unkempt kindle
#

how bad is this

replace: "$1{...$2, props: {...$2.props, children: [ ...$2.props.children.slice(0,2), $self.strip($2.props.children[2]), ...$2.props.children.slice(3)]}}}"```
vast karma
#

Why are you modifying the output of .jsx rather than the input

unkempt kindle
#

im not allowed to mutate props

vast karma
#

Stop doing silly things and do normal things instead

#

Like modifying the code that does the rendering

#

Modifying the react trees isn't quite as illegal, but it's still better to edit the rendering where it happens

unkempt kindle
vast karma
#

It's pretty standard for BD plugins I think, since they don't have as sophisticated mechanisms

humble tulip
#

I was gonna work on some markdown related bits but a new implementation soonā„¢ļø might be cool

vast karma
#

They're putting rust in the client?

iron epoch
#

so the new discord bundle config, hashes the language files?
how do I get that hash?

#

e.g STATUS_MENU_LABEL

hushed loom
#

Hashintlkey or smth

#

There’s a function that you can use via console shortcuts

vast karma
#

If it's in a find or patch, there's a magic syntax for it

iron epoch
#

I am trying to get this component but I am not sure how to approach this case.
trying to get e in this context. I think e is a component that renders the custom status model

quick zephyr
#

I think you click on the - to the left to break on update then click on the modal in discord and it'll find it for you or smthn

hushed loom
#

Find the module for it and write a patch

#

If you want to use it in your own code, look there's a function to load lazy modules by the code where they're used

iron epoch
#

is my only choice is to get the module by id?

iron epoch
#

so find by module id it is

hushed loom
#

Nope

#

On mobile rn

#

Let me find the code