#š§©-plugin-development
1 messages Ā· Page 71 of 1
similar to flux events
export default definePlugin({
onBeforeSendMessage(channelId, msg) {
// do stuff
}
})
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ā¦
What is it?
it adds a customizable āfingerprintā to the end of messages
yeah that definitely can be done with textreplace
š ik
find: ^(.*)$
replace: $1\n\n> This message was sent by your mother.
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?
And thatās why the plug-in isnāt done yet, itās still a very early draft
this is similar to iphones adding the "sent from an iphone" at the end of an email
This message was sent by TheAnnoying
i forgot i have it on š
This message was sent by TheAnnoying
Youāll see one thing and you hop on a fucking bandwagon
You gotta wait it out
Iām still on my initial commit
To me it seems just
what
obnoxious?
Yes, it can be done via text replace but i plan on adding an option where it can be toggled on and off
I also plan on being able to allow people to blacklist servers or channels so no matter what it just never happens there
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
remove the word silly from this
not to main, but thatās kind of the whole point of #1256395889354997771
new plugins feel really rare these days
eeal
the post titled "How to Install plugins from here / How to submit plugins" only shows you how to install plugins
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
in my opinion if you make a plugin like this I would much rather have it format the text in a neater way where it's similar to the (edited) mark but at the bottom of your message
so that it isn't annoying to look at
almost as if I exactly just said āI have plansā
markdown footer? but places like here have rules against that (because it gets really... really... really annoying quickly
wouldn't having it as normal text also be annoying
yes
i didn't think of a markdown footer i just thought of somehow changing it with css
nobody else would see that
but that's pretty much what i was imagining yes
other people with the plugin
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)
vp invisiblechat
Encrypt your Messages in a non-suspicious way!
Samm-Cheese
desktop only
i did something similar in my kitten speak plugin
I should really stop developing my code on canary
Flip the script and add black/whitelists to textreplace 
Iāve seen the code for textreplace and never in my life will I touch that
@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
why so many buttons
not enough honestly
this is all i have
you need more
also, someone recommended to me what about just dropping the āSent Viaā part an just making a Signature plugin
which doesnāt sound like a bad ideaā¦
so many toggles
i can add more
i think it's fine š
nah Iāll add one more that doesnāt actually do anything. Itās just there.
how do you customize the text
I forgot to mention but I've uploaded my version of this as a friend asked for it. There's bits that need tidying but I kinda overhauled it a bit
https://github.com/lolsuffocate/vc-customTimestamps
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
yeah that's fair
Just kinda slotted in a header for it, it's a bit jank
won't making it bold would make it look much better? + appealing
Probably, I threw it together while I was at work so I could share it with the friend lol
small change to the svg
yeah thats not how the api works but thats how the API should work
good old // @ts-ignore
nah im just kidding i found a different way

dont husk me iāve seen the code for IconViewer
this isnt horrible for the reason you think
the price you pay for userplugin support 
use .splice instead of filter
stop() {
const { customSections } = Vencord.Plugins.plugins.Settings;
customSections.splice(customSections.indexOf(this.insertSettings), 1);
}
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
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
Mutating props is illegal though
that's why i asked my original question
i don't know how to patch this better
this isn't a smart patch
Find the part that says children: t.name or similar, and change that to children: $self.memfrob(t.name)
$self is replaced with a reference to your plugin object
It's in your plugin object if you define it
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
Sure, but you are not allowed to mutate props
is this not prop mutating as well though?
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
are we assuming i have something similar to:
function something(e){
let { children: t } = e
}
ohh
that makes more sense
No, I'm talking about ```js
function(e){
return (0, x.jsx)(T.qW, { children: t })
}
I didn't think of changing what's returned
(I changed my patch)
and you were right, it is using children: something
Prob best to just patch the stoee
what
store
Stove

that still doesn't give me a lot of info
i don't really know what the store is
I disagree
making the have dirty data will affect many other places
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
you need general javascript knowledge (and then you can easily figure out typescript)
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
patches are the one thing i have not figured out yet
real shit š
I can code a plug-in, but donāt fucking ask me to make a patch
id like to think im fairly good with patches, ping me with any questions you have 
personally for me, it was actually easier to learn TypeScript and then move to JavaScript
idk what you even mean by that 
i learned javascript making a discord bot, so typescript wasnt too difficult for me.
Typescript was somehow easier for me to comprehend than JavaScript
i did choose a fairly easy idea for my first plugin though. i made a chat bar button that sends a random picture of my cat.
I have helped write portions for plug-ins before, but I think the first one I did that I could actually apply my name to was probably [WriteUpperCase](#1291571765029376061 message) or Signature Which signature yes can be done via TextReplace I just made it because I was bored and it was a good learning experience)
I see the user plugin submissions are about as slow as prs
@hoary pilot @hoary pilot
I opened it 10 days ago 
why is it not allowed to mutate props? this method seems to work much better than my other option
Try doing channel.name += "!" and you'll see
You will see
Told ya
oh god
Because it's mutating the input
what the hell
And then that mutated input is passed when it's rendered next
nice stuff overall
And it mutates it again and again
but the mutation im doing is different
im not adding anything im just removing emojis
doesn't visually look different every moment
thing is this function has like
function something(e){
let {channel: t} = e;
return ...whatever
}```
so it's harder to change what's returned
and easier to just change the data it's getting
Yeah and it's easier to open a door with an axe than with a key
But has more side effects
I don't see any way to change that whatever without mutating
wait i'll show you exactly what it is
You are currently doing t.foo = func(t.foo), right?
it's inside one of the ...p, ...v or ...e
exactly
You can for example change that to t = {...t, foo: func(t.foo)}
Because that does not mutate anything
who said that?
It only changes a local variable
React docs
kyuuhachi
you can mutate props just fine
oh wait you're THE vencord person
just if it has side effects then you're likely better off not doing that
my prop editing simply removes emojis from all channel names
why do you want to do that
because some servers get really annoying with it
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
in the react component selection thing I specifically selected the outer most channel element
in this case it shouldn't be hard to just patch where it renders the channel name line
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
"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"
this is exactly what im doing so far
is it that bad?
it's actually nice I can see the patched code like that
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
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
if you link to a channel in another guild for example, it won't automatically update
where could I edit the actual data? i would prefer that as well
this does change the data; it just does it at the wrong place
do you mean changing the actual data discord receives?
yes but vee doesn't recommend doing that
won't i need another patch for that thing specifically
isn't the only way to change the name everywhere just to somehow edit the data discord receives?
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)
Presumably that would be in a GuildStore or ChannelStore or GuildChannelStore
yes
I thought those were just for getting data
i don't really know much about the stores
you'd probably want to do something on the connection ready flux events for example if you were to do that
It's called a store because it stores stuff there 
Yes, and if you want to change the data that is gotten, where would you do that
are these stores a vencord thing or a discord thing
discord thing
Discord of course
oh
though a few plugins implement their own
I thought it was vencord who is collecting the data and just making it more accessible
No, those stores are where discord stores its own data
so any data that discord uses comes from there
yeah so I should edit the data in the store
no you shouldn't
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
not really
i would rather remove the emojis from everywhere that channel name is used
you really shouldn't
but that means i need to write multiple patches
Oh no the horror
i don't see what's so wrong with manipulating the data discord uses
im just editing a string
because the whole point is to not make data dirty
that data is not only used in ui stuff
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
it will mess up other things too
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
where does t come from?
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
Yeah sorry, I took the i out and missed the e smh
I tried it and all my channels look naked
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"
}
what exactly are you trying to do
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
this one?
you have weird patch anyway, why dont you add your component to the array instead?
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
š aināt no shot that plug-in would be approved for official, maybe you could get it in #1256395889354997771 tho

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
Also, why you think so?
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.
because iāve seen the original pr
https://github.com/Vendicated/Vencord/pull/730
Why it was unapproved?
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
if it's rewritten maybe
oh ok
but it needs to be hardly reworked
I'll try my best
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
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
Hm, I need to do it clean and use files as less as I could to do so
Yeah, I've been using this plugin for too long, it was crashing almost every update. I'm on canary build tho
But I loved this plugin much, so I'm gonna try
well i know how to write javascript, i've done it at a professional level but there has been a lot more to it
like figuring out what does what
this is what i'm struggling with too
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
no
your client does not have access to that information and would be a massive privacy problem
The best you can do are NSFW VCS which are a stock feature
I see
alright thank you
how do i make it so a command doesnt send the comamnd text in chat
don't use BUILT_IN_TEXT type
if you use that, it automatically sends the return value
use BUILT_IN
alr ty
vesktop?
nah, the api im using for a plugin doesnt like me
whyd it take you 50 years to type that
?
how would u make it so that sending messages send as replys replying to messages not just normal messages
use https://discord.sex for more info
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...
i just saw
i got timed for saying the website
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.
don't use dom manipulation
and your replace must return a string of code
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')
])
}`;
}
}
]
});
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
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);
}
}
]
Have you looked at how patches are used in the hundreds of other plugins
where args are -> createelement
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) })"
}
}]
});
And why are you making children a function when it wasn't before?
children:, props => is not valid syntax, either
so just replace: " $self.addVCLabel($&) "?
Check with patch helper that what you're doing looks right
do you understand that match and replace is a simple text replace on Discord's code?
discordsCode.replace(match, replace);
patches: [{
find: "renderChannelName(){",
replacement: {
match: /(?<=\.channelName,children:)[^,]+/,
replace: "$self.addVCLabel($&)"
}
}]
That is what I'm doing.
patch helper? (nvm, found it)
just use a custom component
š
š
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.
nah just keep it hidden
thats what ive done with my plugins
or use datastore
if it doesnt need to be synced
index.tsx: Lines 213-215
}).withPrivateSettings<{
ignoredActivities: IgnoredActivity[];
}>();
you have to handle defaults manually on those
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
index.tsx: Lines 217-219
function getIgnoredActivities() {
return settings.store.ignoredActivities ??= [];
}
do those just sync with settings sync but are not shown to the user
however try using disabled: true first
lsp tells me thats not a prop
oh I was sure it existed?
might not be on bool
you can store any type on it (as long as it's JSON serializable)
thats what the setting is
yea thats what i did for customfoldericons as i wanted them to sync
you might be able to set an empty patches are to force a restart on plugin enable
much better than using Datastore
I hate it
PinDMS should be using that for categories
i tried using datastore without knowing what useawaiter was
and it was not a fun time
I mean for Datastore most times you should just have a local cache
and update Datastore on change
yea, but that was also like my first time ever using react š
thats what i did 
i just init'ed it on plugin start
i hate when yall people start with the nerd talk
plugin dev
nerd talk
mfw
š #š§-off-topic-iceman-only
(Auto-response invoked by @hushed loom)
@swift delta ^^
try that
patches: []
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
do you still have the hidden setting?
as of now this, but the api is shit so Iāve got a bot scraping so I can build my own
https://nekos.life/api/v2/img/goose
@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
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
wip 
good plugin
maybe replace the green placeholder with a preview of if it was placed there set to half opacity or something like that
sir are you using comic sans in your code editor
and if so
why
nvm I just forgot to apply css
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,
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
Itās the default font across my whole system
@azure fossil do you have react devtools enabled
i think i disabled them last time cause it was crashing me
and i forgor how to enable
how do i replace fetch messages function? I need to process all messages before displaying them
tried this one doesnt work
SHIT
thats fetchmessage
welp
still didnt work
hey how did you end up doing it?
never mind, it works
Now stop hardcoding the variable names, and remove those pointless whitespace checks
yes i realized that
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
showspotifyembeds
i want to add an embed to all messages that have a spotify link and do not have the embed for that link
the embeds are implemented like default embeds, just with a custom renderer
may I suggest taking a look at https://github.com/lolsuffocate/Vencord/blob/showMessageEmbeds/src/plugins/showMessageEmbeds/index.tsx
i know that they are implemented as default embeds
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
i would recommend removing the e from your find
you might have to find a different find though
why?
i assume because its a minified variable that can change
that's a random variable name that could change
could or couldnt doesnt matter right now
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
once as in
- first time loaded on client
- when recieved from gateway
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
i think the getter doesn't make sense for what you're trying to do
where exactly
in here
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
certainly not
i bet it is also likely the fetch local messages functions in this module have something to do with it
it works
okay
it works as in
the method works
but only once
im doing it like the other plugin
which works normally
what other plugin
mssglgg
i want to make another plugin, but i have no ideas
look at suggestions
i got an idea
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
wdym value in JavaScript
trying to do a feature where you can set a min contrast value for RCE
evaluate to "check for errors"?
evaluate to get the value of this
to check the contrast
don't think so
not really
@cedar olive solved it
i just asked github copiliot to do it for me
and it provided working code 
@swift delta remember that settings question you had last night
const settings = definePluginSettings({
mySetting: {
type: bool,
desc: "123",
default: true
}}, {
mySetting: {
disabled: () => true
}
});
interesting
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;
}
}
}
]
}]
Aināt no shot that actually works
you want to add an emoji to every channel name?
because im trying to do the exact opposite
I DMed you. Maybe we can work together š
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
I am not really sure what you mean but I think IconViewer does that in saveIcon function.
#1293357944498556969 message it was by suffocate. could be helpful for your case?
Thanks, but it was just easier to recreate the function in js
nobody?
Some store
Look on the stores object with console shortcuts enabled
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*
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
Already looked into it. I dont find anything
thanks
still no one?
Im searching and searching but dont find anything that I can use.
hooks just need to be in the context of rendering a component
they can be placed anywhere in the code
does this not count as the rendering context
I might be wrong but I'm guessing you just need to be currently rendering a component to be able to use a hook (inside a function call that renders a component)
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
yeah
i really didnt want to have to move everything up, but i think i have to and just use a var
you want the top level component to get re-rendered?
what's wrong about it
I mean, does this not work?
doesnt
throws the error where it says hooks can only be at the top level
its stored as a variable, then that is passed as a child
dont think hooks are valid there either
not always called
that's weird tho, you are overwriting the color right?
here
yea but i also need to pass a ref to get the computed background color
unless there is some other way to do that
i dont really see how that's not working
nah you can definitely use one there
still don't understand how I can process messages that are getting added to cache
I'm not super confident I've done this in the best way, if anyone has any feedback I'd appreciate it
https://github.com/Vendicated/Vencord/pull/3048
I kinda just threw together what worked but I don't know that it's the way to do it
Don't know much about the drop logic, but I can take a look at the patches later
You probably want to use useCallback on those callbacks
To make sure you get the same function object when it rerenders
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
Huh
Couldn't drop in though, that could maybe be cool but too niche to do anything with
I would expect that without useCallback, that global drag listener wouldn't be cleared properly
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
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
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
Yeah, you can see it in the preview gif
bit more in depth here as well
Also the PR mentions a conflict in contants.ts, I assume there's no point resolving that until it's gonna be merged?
doesnt matter
it can be resolved at any point
Cool, I'll just leave it
Can someone help here?
your replace function makes zero sense
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
thats not the problem.
currently Im searching where the channels are stored.
try to look at other functions to figure it out
there are tons of plugins that retrieve channels
Thats what Im doing currently.
Currently im looking into ChannelStore
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
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]]: _
expand the prototype
Yeah ik, there is "getChannel" but it requires channelID.
there is more than just getChannel
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__()
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 ^^
@unkempt kindle This should help you on your task š
you mean that I dont use patches?
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
I was thinking todo it on addChangeListener.
if (ChannelStore.addChangeListener) {
ChannelStore.addChangeListener((newState) => {
but then I though, its abit overkill (spam).
so this is like editing the actual store data
As I said, I'm new
also
im not exactly sure .getMutableGuildChannelsForGuild is a function
there's a ByGuild one
I dont know what you are talking about?
Mine works fine for me.
and yes, it updates:
Removed VC from the bubble.
And if its unlimited it shows like this:
revolutionary new idea
i already had the idea to shove an ad in the sidebar itself
on the right sidebar
HORROR
ooh
Still got the patch?
I can prob check membercount plugin
will once the PoC is completer
any other ideas for places?
gonna change all the user/server icons hopefully
expression picker
force onboarding steps to show and add an ad there

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
how are you meant to find the functions a store has. discord dev tools just showing me "Store is missing __getLocalVars method." for everything
Just inspect the object in browser dev tools
inspect the store?
It's a js object
how am I meant to find the store in the browser dev tools
Vencord.Webpack.Common.GuildStore
Whaddya mean kinda
it is shit*
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
only useful for changing the settings it has on it
how should I find stores then
The useful ones are already in common
if you really want a list of all stores enable console shortcuts plugin
the one I need isnt. well maybe I need a different one and am on a wild goose chase 
and then
type Stores.
in the console
if you know the name already
oop
I deleted your message in accident
nuckyz hates me
anyways as I was saying
if you know the name already
why do you want a list
you have to webpack find it
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
const StreamerModeStore = findStoreLazy("StreamerModeStore")
in your plugin
or Vencord.Webpack.findStore("StreamerModeStore")
in the console
worked nice
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
do you have streamer mode always enabled or is detected obs or something
I have obs open to test this
yeah that's why
discord auto enables streamer mode if it detects obs
yeah so im looking for a way to detect streamer mode at start
does it not trigger when discord detects obs
it triggers if you manually enable/disable it
I have the dispatcher tab in discord dev tools open and it doesnt
RUNNING_STREAMER_TOOLS_CHANGE
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);
}
}
cursed but it looks like it works
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
react hooks 
did you ever get a working proof of concept
Didnāt get it into avatars, and I tried looking into simply worming google adsense in, but it seems to be locked to the specific site you set (and I donāt own discord.com, soā¦)
aww i cant get milkshake and online casino ads in my discord client 
looks to just be a csp issue now
What a shame
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
Hey so uh, with pnpm watch, how do I actually make that inject into my client?
Just run pnpm inject once
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
pnpm build --watch
dont remember where I found this but it says thats the command https://gist.github.com/sunnniee/28bd595f8c07992f6d03289911289ba8#setting-things-up
oh I see pnpm watch is a shortcut for pnpm build --watch
oh interesting:
WebpackRequire was not initialized, running modules without patches instead.
oh wait
me stupid
forgor to update my fork
lmao
doesn't work for me
and how would the text appear like that if you just changed the channel name?
i'm trying to do this with the channelstore but i can't seem to get the data
The code that you saw just changes the channelname.
The code that you see on the screenshot is different.
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__()
For your purposes you were more on the right track when you were looking to patch this #š§©-plugin-development message
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
i understand that changing the text rendered would be a much safer approach
and that changing the data in the store is not really a good solution
but when i look at other patches, they seem to always include some string that won't really change and they seem like such great patches. my patches rely on variable names and i feel like they could break at any moment
Some patches are horrific
That's kinda just how it is, I think the find I provided back then would be fine for the foreseeable
Just a big pile of symbols
If it breaks it just means searching for the module again and trial and erroring a better one
But as long as they work, that's not an issue
Yes ^^
in that example, what would you select?
"onMouseLeave:o,children:t"?
because that seems like a really bad select
That's really bad yeah
I just did this
that's what i selected when i did try out that one
and it worked
but i was not happy with that
why specifically the .scrollWidth&&(null) part
It just seemed like the most unique part of the module without variable names in it
btw how did you display it like this
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
It's a wip upgraded version of the companion extension
is this a jetbrains ide
Yeah but sadan is working on the vscode version
https://github.com/Vencord/Companion/pull/9
https://github.com/Vendicated/Vencord/pull/2791
it's slower
Yeah I figured
i should have still allowed finds to be array
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
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
Basically fallback regex
yeah
It's really simple and powerful
just gotta write the order in the array correct
i don't understand why matching the } was needed
but it doesn't work without it
is there a way to wipe a specific plugin's settings
Yeah it matches this otherwise
Oh yeah that too lol
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
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.
pindms?
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
š #š„-vencord-support-š„
(Auto-response invoked by @iron epoch)
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
you can just do all: true in the patch, they show either one depending on an experiment
oh nice
ive been cooking for so long I might have overcooked š
lol
anyone know what component this is?
sorry for the many questions, I am new to this
is that like streamer mode
yeah I originally just wanted to add streamer mode detection
then I got carried away
I tried Menu.MenuItem but it doesn't render
you mean a dropdown?
figured it out since
š
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();
}
});
CollapsibleCodeblocks plugin next
?remind tomorrow
Alright @hushed loom, in 1 day: ā¦
Lsp in code blocks plz
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
- 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 infindunless absolutely necessary) - use capture groups
()to use that string in your replacement with$1,$2etc - since
hisn'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.
hdoesn'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 ofh.
Also /url: n/g will very likely match nothing whatsoever, since there are no spaces in the minified code
Also your replace will throw a error as your template string is in the wrong place
Thank you all. Your advice helped me
I'm sooooo flippin cloise!
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}
adcord?
is the image string base64?
href
oh that makes much more sense lmao
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
It's funny how as you move around Discord, the ads naturally just pileup in the correct places (where google adsense usually places them)
ok dmed it to you
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.
API docs?
Sorry?
Doesn't look like it
you have a link to that?
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
nvm I hallucinated this
damn ok
Then followup question, is there a way to prevent vencord commands from sending a response to chat
Why not just do an ephemeral "done"?
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
do BUILT_IN instead of BUILT_IN_TEXT
omg it worked I love you
I spent so long fucking around with registerCommand, execute, and _handleCommand the other night over this
thoughts?
i don't really get this
what is Pluralkit
i don't know what DID is
I'll let someone who actually has it describe it
what
are carrot and johny webhooks?
they are pluralkit webhooks yes
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 
I once did something similar with really hacky css for some people lol
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
fuck
should've read this earlier, silly me
now what
like discord settings or vencord settings
vencord settings
FluxDispatcher.dispatch and FluxDispatcher.subscribe I imagine
dispatch a custom event for your plugin and subscribe to it
You can use useSettings, it's a react hook for settings changes
I sent a DM to vending.machine
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
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
rules say no
what do you need their api for
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
which account is active is a public thing, I can use the API without a key for that
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
yeah that might work
not sure how intercepting the message would work though
yeah my thoughts too
probably gonna have to find the component that handles sending messages
overall it'd kinda suck tho bc
the person would need to have their privacy settings set to public
why
for me to be able to query which members they even have
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
the posting rules of #1256395889354997771 dont mention anything about an api key
just that you gotta add a disclaimer an external api is used
I'll try to remove the requirement for an API key for now
but it will still use the public API
You can use the MessageEventsAPI and add a pre-send listener
ClearURLs uses it
ooooo ty
what are you making
I've already described that -J
the webhook represents which identity is active
ahh
@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
Pretty cool
Maybe you should add something near or in place of the username/icon in the bottom left for the active proxy
thats one way of doing it
i agree; do note that I am not the target audience for this plugin, but I think the way it's implemented is too inconvenient to access
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
fellow zen user
is the selector only used to append the different endings to messages and from there some discord bot does it?
Yes
if you want to be super thorough you should probably check if adding the prefix and suffix will cause the message length to exceed the limit lol
Yeah I thought of this but was unsure how Iād stop them sending. Then I forgor
I'd probably just truncate the message however many characters you need at that point
lol
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
@hushed loom, <t:1732816659:R>: ā¦
how would u check if ur the group owner or not
you can get the currently focused channel with SelectedChannelStore.getChannelId(), the current user ID with UserStore.getCurrentUser().id, and the group owner ID with ChannelStore.getChannel("id").ownerId
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
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)]}}}"```
Why are you modifying the output of .jsx rather than the input
im not allowed to mutate props
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
im now doing the channel name at the top and there really is no other place it's stored in
wait this is really cursed
It's pretty standard for BD plugins I think, since they don't have as sophisticated mechanisms
I was gonna work on some markdown related bits but a new implementation soonā¢ļø might be cool

They're putting rust in the client?

so the new discord bundle config, hashes the language files?
how do I get that hash?
e.g STATUS_MENU_LABEL
If it's in a find or patch, there's a magic syntax for it
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
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
Its lazy loaded
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
so something like this?
const { OpenCustomStatusModal } = mapMangledModuleLazy("this.renderCustomStatusInput()",
{
OpenCustomStatusModal: filters.byCode("\"CustomStatusModal: user cannot be null\"")
}
);
is my only choice is to get the module by id?
No
so find by module id it is