#🧩-plugin-development
1 messages · Page 56 of 1
Usually not necessary
Often seems to be used just for convenience by naming the matches
as Kyuu said it's most used to name the matches, but in some cases it's used to do additional stuff with the match instead of just a simple replace
uh next question, how would i get a list of unread mentions? is there smth to get them from the inbox?
uuuuhhhhhh
im starting to think this does not check if the emoji is actually animated or not
put breakpoints on every line and see what's wrong
:p
but detection works fine for me from my experience
hmmm
how does it calculate how many normal emojis there are
if it only does the count for if it isAnimated
if (emoji.animated === isAnimated)
it counts how many emotes in the current server are the same isAnimation boolean as the emote you're cloning
so if you're cloning an animated emote it counts the animated emotes, if you're cloning a static emote it counts the static emotes


maybe its just my server thats having this bug then
static emotes (there should be 10 slots available)
animated slots (correct)
wait
it has came to my attention
i still have no idea why the counter is doing that
i was gonna assume it was because of having 10 linked twitch emojis
and that was counting towards something
unrelated i have a different idea for how i want to go about this now
how would i have something trigger (similar to preSendMessage?) when you get mentioned? im trying to make a list of message ids with mentions for this #🧩-plugin-development message so i can only highlight the ones in the list and remove the item when you reply to it, im not certain about the best way to do that but that was one of my thoughts
maybe?
if u can't figure it out invite me to ur server and ill check :p

you're trying to remove the yellow highlight from messages you reply to?
cute emote but then you click and it's this abhorrent pepe
LMAOOOOO
i dont know why half the emotes there are pepe when most of them look like 











true 
also i was right it was because of the twitch emojis
because now that i have it toggled off
yeah, and i was trying to have the default state be non highlighted and only highlight when recent so i dont have to check for every single mention if you've replied or not but im not sure if its the best way to do it
yeah there you go
how do twitch emotes even work?
are these like emotes of your twitch channel?
if you're subscribed to the person and they have this setting turned on then the person who is subscribed will be able to use these from the server (and they work without nitro)
okay so first of all you don't need to listen to any events or use preSend, the data is alresdy available
you'll want to patch discords message component, specially the part that determines whether you're mentioned, and change the boolean accordingly
oh yeah i know that, but i was confused how they're added to your server, thinking they were someone else's
but yeah those are your channel's emotes so makes sense
anyway i assume twitch emotes have a special property? like emote.managed perhaps
yep
i just fixed that
im trying to specifically keep the yellow line too

you want the yellow line but not the yellow background colour?
yea
you'd still do that the same way, patch the code that does the background and add your own logic for determining whether a message is relevant
alr, thank you (this is my first time trying to make a plugin lol)
would that be this
(sorry if this is obvious stuff 😭)
probably! idk
wh- lol
do not use or else you will be fired
never said don't touch tho 
you’re fired
someone is getting fired soon...
I may be stupid but is there a way to make a command just call a function instead of having to send a message?
yes
set it to BUILT_IN instead of BUILT_IN_TEXT
then you have to handle replying yourself
have u looked at it with react devtools to see what's passed?
or just the source code
I am still not sure how to get components
ik what i am trying to get but how to get it idk
I tried to use findComponentByCode but didn't work
here small snippet of what i am trying to get
V=r.memo(function(e){let{isActive:t,className:n,viewType:r,autoFocus:s=!1,"aria-controls":o,...l}...})
its the navButton.
I want to know what I am doing wrong and how to use it properly
@vast karma replytimestamps patch seems to be broken as a heads up
now im confused it says invisible chats button is matched to nothing as well
Not on stable from what I can tell
werid mine says the find was bad
find: ",renderSingleLineMessage:function(){return ",
that seems to work just removing the first {
Oh, makes sense
I used a slightly more liberal find for the PR'd version, which still works
thanks
Anyway I fixed the userplugin one
thanks
Thanks for reporting
im switching 2 pr rn
yup np
(also settingscog is broken but i forgot that got merged to better settings)
Yeah I removed that one from my repo since it's upstream now
yup
got reporter working 😔
already fixed most of them
aka the channeltextareabuttons use addchatbarbutton now
What the hell happened here?
me not updating stuff
Yop
Yes (besides the ones that were false reports)
I meant the patches
3ish of them were from modals not being opened
then it's not working properly
Noted
the reporter force loads everything
Wouldn't know all I did was open the modal and it loaded fine on canary and stable
So
Looks like mutualgroupdms and uservoiceshow were the mad ones
no
Wouldn't know
I'm as much confused as you
I'll check canary again brb
oh this is his own mod with bunch of third party plugins
that makes more sense lol
btw i will look at ur webpack changes on sunday nookies
im on vacation right now
its mad on canary for mutualgroupdms
2 of .Messages.USER_PROFILE_MODAL exists
same with uservoiceshow
testing please ignore this
🎉
testing please ignore this
I have committed multiple crimes against the MessageTags plugin
kk no worries
If you want to look and merge my resurrect home pr first it's probably better
way more simple changes than the webpack
but also needs your reviewing cuz it adds support for find array
oh i see
I think it's good but eh I can wait till sunday
for the first time I actually needed finds to be an array, cuz a single wasn't enough
and I'm sure it isn't enough
btw i think this is mergeable too https://github.com/Vendicated/Vencord/pull/2324
but i can't test it
sunday too unless u wanna test & merge
ohh do u mean https://github.com/Vendicated/Vencord/pull/2283
yeye
hey is there anyway to well skip or replace the a for a.jsx for user_profile_modal?
what the hell is 69386d_5
?
hmmm
is that really the only way to find it lmao
it seems unstable but ig the entire experiment is unstable
yes because home is deprecated

.default.Messages.USER_PROFILE_MODAL,children:[(0,a.jsx) is the only way I've gotten it to match. it can be trimmed to .USER_PROFILE_MODAL,children:[(0,a.jsx)
so it they remove those experiments they are removing home too probably

so just use \i\.jsxs wdym
its for the find
makes sense (they will remove in 4 years)
\i\ yells it me for not being a string
for real
you definitely don't need a find that complex
why add find array?
maybe regex instead makes more sense
as long as u keep the regex simple it shouldn't matter that much
but also ig adding regex will encourage "lazy" find values
also I have no idea how to fix the problem with checked text area and changing the inner state of it (the thing that you removed to fix cloud sync)
oh
I do
sad
that modules is like a short version of another module
i mean this find
anything I try as find will match the wrong
?
oh wait you are talking to him or me about find array?
i am saying their find is too complex
not your find
I know its 2 complex
but it finds 2 with .USER_PROFILE_MODAL,children:[(0,a.jsx
because of jsxs
send the module you are trying to match
section: O.AnalyticsSections.PROFILE_MODAL,
children: (0,
a.jsxs)(r.ModalRoot, {
transitionState: V,
className: D.root,
hideShadow: !0,
"aria-label": g.default.Messages.USER_PROFILE_MODAL,
children: [(0,
a.jsx)("div", {
ref: el,
children: (0,
a.jsxs)(C.default, {
user: Y,
profileType: R.UserProfileTypes.MODAL,
children: [(0,
a.jsx)(P.default, {
className: D.topSection,
displayProfile: z,
user: Y,
friendToken: b,
onClose: H,
isStreaming: (0,
d.default)(Q),
guildId: _,
channelId: h,
hasProfileEffect: null != eo
}), (0,
im matching in there
.AnalyticsSections.PROFILE_MODAL,children
thats for uservoiceshow rn
and that find doesn't work?
the find before
testing that find rn
that patch works
got the mutual groups working
the match was fine when I changed the find
basically the matches were fine the problem was the find was receiving 2 or more which in turn failed the patch
userVoiceShow: .AnalyticsSections.PROFILE_MODAL,children
mutualGroupDMs: .tabBarContainer
these could be made better probably
Mutual group dms has an error on the same match but uservoiceshow is fine
Without searching the literal or the file name which could change, how could I possibly find this function?
The file names aren't present anywhere else so i can't reference the filename from somewhere else. Seems impossible without using the filenames
hmm the only way is finding the number of it by matching the module that uses it
it's hard but doable
{
match: /\((\i),\{id:(\i)\.\i,"aria-controls":\i\.\i,"aria-selected":(\i)===\i\.ExpressionPickerViewType.\i,isActive:(\i)===\i\.ExpressionPickerViewType\.\i,viewType:(\i).ExpressionPickerViewType\.\i,children:"\i"\}\)/,//\]
replace: "$&,$self.testButton($1, $2, $5)"
}
testButton: (V: TabButtonComponent, U, ei: string, y) => {
is there a better of doing this?
I am passing the component instead of actually getting it using webpack
well firstly you are matching way too many things manually
others you can find using webpack searching instead
true, I am improving the patchs later, I make the functionality then fix the style
that's the problem, i am not getting how its used
can you teach me how to properly use it?
also don't start a match with a \i
noted
I am was just getting the component
it matches anything so it doesn't make sense to start with that
start with something constant
thought of that
But then is it possible to search the number? Because it is a js object literal I assumed defineplugin wouldn't be able to search for just the number like "655142:"
searching by module number? that seems worst. the patch would just work for sometime then break
r is the link that is being exported and you want
you need add a listener or patch that finds that module, matches the number inside the e() and puts in a variable you can access in your plugin
then just require it with the number
Ya I understand you could grab the number from another module. I was just saying once you have that number i thought it wouldn't be possible to use find for it
or findModuleId("closeExpressionPicker:") search the module id by code and use wreq to get it with the id
did I say something useful? @cedar olive
you just need to wreq the number
not really
aw
that's exactly what I needed
you can hardcode asset urls. they don't change
the filename is the hash of the file. they won't change unless discord changes the file. but even then, the file won't be deleted because outdated clients will still use it
Well that works as well. I only chose against it because I know the ringtone URL did change at one point
And the plugin wouldn't need to be updated, even if it's fairly simple to do so
so no? there isn't way to get the navButton component without patching
just testing modified version of messagetags i am making
messagetags if it was epic
that Brilliat, I am curious of how it works
something I can relate with in this server lol
lmao message tags can be completely replaced by text replace
i just thought of that now
Tags are simply easier to remember thanks to the /tags list command imho
Meanwhile for textreplace you either to remember all your rules or you're going to check the plugin settings many times
find: ".Messages.MUTUAL_GUILDS}", seems to work and reporter isn't mad
i wanna make a button that goes to the settings page for the plugin, but i'm not sure how to force discord to navigate to settings > plugins > plugin_name. does anyone know any plugins that have that option / know how? nvm there's examples of it in Vencord.ts but i gotta find out how to make custom sections
^ agreed
Message tags is so good because I can do / and scroll through all my tags
Text replace i have to open settings and open my plugins and so on to navigate to them all.
This is amazing
? you want to make a custom section in the vencord category?
Or do you just want to open the plugin config modal
just that, i messed up my words there
@north flame encryptcords patch seems died
Huh
Probably, I’ll have to make the rates better later
{
find: "executeMessageComponentInteraction:",
replacement: {
match: /\i\.HTTP\.post\({url:\i\.Endpoints\.INTERACTIONS,body:\i,timeout:/,
replace: "await $self.joinGroup(C);$&"
}
}
thats what I have it set for now
Pretty shit rn (easily outdated)
what does that patch do so I can test it rq
(im not good at reading them lmao)
pretty sure its when I click the button it does the group
if so it works
That patch doesn't look correct, with that await await
I think it’s actually unused and I forgot to remove it
how would I fix that then?
add an await at the start?
Easiest would be adding the await to the regex, yeah
So it's inserted before the await
so
match: /await \i\.HTTP\.post\({url:\i\.Endpoints\.INTERACTIONS,body:\i,timeout:/,
??
{
find: "executeMessageComponentInteraction:",
replacement: {
match: /await \i\.HTTP\.post\({url:\i\.Endpoints\.INTERACTIONS,body:\i,timeout:/,
replace: "await $self.joinGroup(C);$&"
}
}
Ohhh
I remember
I’m pretty sure it was used so that the join message could have custom buttons
But idk who it would be joinGroup, it should be for like “I don’t want to talk to you”
Yeah, that’s what it’s for
epicsauce
is this the patch helper
looks weird
Aside from the transparency it should look pretty normal
I don't have the diff section and also no compile button
Even if you insert something?
with some dummy data
Hey, is there a way i can put line breaks in the details field of a custom rpc? doing \n doesn't seem to work
1: Does discord support it?
2: Modify the plugin to use a TextArea or modify config manually
3: Profit
Idk if discord supports it
Highly doubt it tbh
Mb, by custom rpc i meant manually despatching it from a plugin (the way customrpc does it but not the customrpc plugin)
oh
Probably should have specified
Oh god please ignore the spaghetti code https://raw.githubusercontent.com/cheesesamwich/Tobleronecord/main/src/tobleroneplugins/RPCStats.tsx
It's so shitty 💀
But why?
Why what
Idk it seems kinda cool
Not like i'm doing anything else with my rpc since i have game activity disabled
Shoot
fuck
i can't find what i was going to reference
but
counting messages sent will NOT sync
i hope you are aware of this
They do for me
If i restart they persist
I said sync not persist
- they don't need to stick long term since they reset daily
actually vencloud is very jank for simultaneous multi-client use and needs a massive rewrite for that xd
i will not be the one to fix it
This happens when I set the applicationId of a "built in" command
actually idk if it's that or the id (command id) itself
love discord 
If anyone else experiences this, don't change your applicationId
Would anyone want a Message Tags page in the expression picker
hmmm maybe
I'm not so sure about .{0,2000}*?\], seems quite fragile
Yeah......
I just realised I need to capture some stuff from inside there
particularly that ei===
Do you really need to edit the whole list, or is it enough to insert stuff after some other specific child?
I do not, however I would like to achieve something somewhat like ContextMenuAPI
Also plugins will probably want to append to the end of that list
so i'd need to capture that junk anyway probably
I wonder why the Sounds one is not localized
Soundmoji is still an experiment
What the fuck have I done
Wonderful
So you know how you said my 2000 char match was fragile?
You were right
2000 chars was matched the next ]
better
Oh, you didn't even make it nongreedy?
Someone knows a lot more about regex than I do
blehhhhh this has better performance
i think
nah its fine anyway
-
- {0,100} are greedy by default, meaning they match as much as possible
if you make them nongreedy (by appending ?) they will match as little as possible
I figured that out
I think you an even make ? nongreedy, though it's not common
i will start making everything non-greedy
inb4 "that has a lot of impact on performance"
lol what
if any, it will be better for performance
we husk very hard
Does textreplace not do it well enough?
it has advanced wegex to make aww my messages as uwu as possibwe uwu
Some needs to make a plugin to un-uwuify things
Now should I wait or break more stuff
huh?
no nevew :3
dont u dawe uwu
i made it mowe uwu uwu
shee if u can shpot fe diffewence owo
That's so meanie >.<
H-how dawe y-you un uwuify things, the uwu cult wiww not awwow y-you (* >ω<)

quests 
Is it possible to have my game activity disabled for everything but one game/custom rpc? i don't want my game activity activity enabled, but id like to have my message stats plugin displaying
check ignore activities settings
dispatching LOCAL_ACTIVITY_UPDATE bypasses rpc and activity settings
function PopupText(props: { event: any, children: string; }) { // https://paste.pythondiscord.com/B2XQ
const [opacity, setOpacity] = useState(1);
const { event } = props;
useEffect(() => {
const fadeOut = setInterval(() => {
setOpacity(prevOpacity => {
if (prevOpacity <= 0) {
clearInterval(fadeOut);
// Perform any cleanup here, such as removing the component
return 0;
}
return prevOpacity - 0.1;
});
}, 100);
// Cleanup function to clear the interval when the component unmounts
return () => clearInterval(fadeOut);
}, []); // Empty dependency array means this effect runs once on mount
return (
<Text
onClick={(event: any) => event.preventDefault()} // so when the text is pressed it doesn't close popups
style={{ opacity: opacity, position: "absolute", left: event.clientX + "px", top: event.clientY + "px" }}
className="text-popup"
>
{props.children}
</Text>
);
}
is there a way to make every text spawns, fade away and gets deleted after fading away?
I have no idea what i am doing in react
I thought of getting the element by id and doing some fade out animation but what if two texts spawned? what would happen?
wanted to put small feature but... (work in prograss)
Don't use setInterval for this, use spring useTransition (not to be confused with react useTransition)
how useTransition would help exactly?
Maybe useSpring rather than useTransition, I don't know the apis particularly well
Can i attach an image in a command response?
Doesn't patpat do that?
Not really, it just uses UploadHandler.promptToUpload
So i guess the only way would be to use the BUILT_IN command type and manually input all the text then send
sorry if this should be obvious :] im trying to find where the dm channels get updated when a new message comes in; it seems like theres a check that doesnt update the channel list if the order hasnt changed and i need to overwrite that. ive been looking and poking around and just cant figure out where exactly its happening. if anyone has help to spare itd be much appreciated 
i need plugin ideas
why do you need to override that check?
anyway it's most likely via a useStateFromStores call
which is a hook that takes an array of stores and subscribes to them
so for example it subscribes to DMStore and MessageStore
for un-hiding unread channels. if the channel would be at the top of the channel list and gets a new message it doesn't update, so it stays hidden until you change channels
this is for PinDms collapse feature?
yes
hey, anyone know how to send a GET request to a user profile?
thankies!
can someone send the discord patching guide (it was a github markdown file and i think it was called "reversing discord guide" or something
i can't find it anymore
i think vee made it
not that one
it was different
it mentioned like
module numbers
like 517100
oh wait
it was that
ty
im feeling like thered be a better way, but is this an appropriate fix?
flux: {
CONNECTION_OPEN: init,
MESSAGE_CREATE: ({ channelId, optimistic }: { channelId: string, optimistic: boolean; }) => {
if (optimistic) return;
const channel = ChannelStore.getBasicChannel(channelId);
const selectedChannel = ChannelStore.getBasicChannel(SelectedChannelStore.getChannelId());
if (channel.guild_id || selectedChannel.guild_id || channel === selectedChannel) return;
forceUpdate();
}
},```
absolutely not no
got it 
is there a way to get userid from the logged in user in the renderer process
i could use that to fix a pretty wacky bug with vesktop streams
you cant start a stream if you're watching another stream because the go live button checks if there's more than one stream
because there is it tries to run some code that modifies a current stream
which of course fails miserably
all i have to do is change the if statement to check if any of the current streams have the current userid as their streamUserId
are you saying its a bug in our code
yeah but i think i have an idea of how to fix it
i was just asking here because plugin people probably know more about userid stuff lol
I want to check if a specific user id exists as an account
elaborate
why
that'll do it
Do not use ApplicationCommandInputType.BUILT_IN_TEXT
Reason: it sends the raw command
only if u dont return anything
huh
BUILT_IN_**TEXT** is for commands that send text
Oh
like /echo

if u dont return any content, it takes the current content
if u want to manually handle sending stuff, use BUILT_IN instead
what if I return {content: ""}
it will error probably
#🤖-bot-commands
i'm actually intentionally testing @worldly oxide
it parses invalid commands and sends a "i don't have permission to send messages" error 
...you can easily see how I accidentally stumbled upon this
i will not continue the testing as i have confirmed that
i will test my actual messagetags stuff in #🤖-bot-commands now
you will husk
hm
i wonder
okay one of you nerds should be able to answer this
my gf sent me this and if you paste it apparently discord crashes
why the hell does it do anything other than just
paste as plaintext
it makes discord use 100% cpu
i assume it confuses discord parser cause it's trying to both parse as url and channel mention, which makes it get stuck in an infinite loop
so bug in discord's parser
but this is just my somewhat educated guess :p
lol why, just don't paste that thing

fair it just seems dumb that its even an issue
you can read it just fine
just cant type it
apparently
ahhhhhhhh
i assumed it was an issue where it tried to embed
disable preview markdown as you type
I love Windows
I think you should be more concerned about using an account named "Admin" and the path of your projects folder
Yeah what type of psychopath puts their projects in documents
Actually
What type of psychopath puts ANYTHING in documents
hey man
i code on linux in all honesty...
Vendicated proposed changes and idk if i was supposed to use the "commit changes" button so i did them and made one commit instead 🤷♂️
I put most of mine in ~/stuff
(there are github projects and non-github projects, makes stuff easier to find)
You can do proposed changes using the commit button
But it's gonna make one commit per proposed change
Yeah I was told by a friend that 1 commit is better in some situations
Anyways now constants.ts is conflicting again :<, gotta fix
Wait hold on a minute i can edit files IN GITHUB? Shocked.
I may be too organised
No that's awesome, keep on
how
m thinkin of making aplugin that prevents discord from automatically setting your status to Idle when u re afk, does such plugin exist already?
literally in development at the moment
afaik
what would be the best way to change the keyboard shortcuts used for navigating channels? (the ones that are alt+up etc. by default)
change to do what
I assume they mean rebind them (?)
just add "adds the ability to easily" ez
"Adds a download button to voice messages"
yes
where do you store your projects?
~/Coding
ok
~/Documents/Coding
idk why I use Documents as my user folder 😭
i have never used any of the dedicated stuff folders like documents, pictures, videos

don't like em
ok so it turns out the context menu properties for embedded images are actually really annoying but anyway it works
https://github.com/Vendicated/Vencord/compare/main...MachineMuse:Vencord:mediaDownloader
you have the same issue of "saving a jpg instead of the gif" if you go through the original 'save as' option as well
might be better to just patch the whole damn thing to add a property with the proxy url and original url
i've been using ~/workspace/ since before those dedicated stuff folders were standardized 🤣
XP era
should i just use the native settings object kinda brute force or is there a better way or is it not implemented yet
so you said this a couple weeks ago
i saw those changes in main, but i wasn't sure if you intended to do more with them
since the NativeSettings object doesn't have the same type signature and it doesn't seem to auto-populate with plugin-specific settings objects
it's fine if i just need to add my plugin to it directly, but i wanted to make sure that's the correct procedure
ah i see
yes the native settings don't handle defaults currently but it's easy to add
perhaps you would like to implement it analogously to renderer?
hm, so those defaults are just set with definePluginSettings when the plugin definition is read? i'm not sure how it gets the list of plugins to read in.
either way it looks like that happens in the renderer so i'd need to add IPC events for that too, which doesn't seem right since it exposes the same attack vector
i can just do it properly in the plugin's native module i guess
nono
😵💫 i don't really understand how it gets populated in the first place
oh, i found it i think
yes, I can do this
well you wouldnt need to do any of that stuff
const DefaultSettings = {
...
}
const settings = loadSettings();
mergeDefaults(settings, DefaultSettings);
export const settings = new SettingsStore(settings);
ok, that works. something like this? https://github.com/Vendicated/Vencord/compare/main...MachineMuse:Vencord:nativeSettingsImplementation?expand=1
so u know how when you hold down shift it quick deletes a message?
would i use a patch for that or an api request to make it happen on all occasions
patch
I also like to nouns
real
:) hold this
i cant find like
any good info
so
how exactly does the start and stop functions of a plugin work
do they just run when the plugin is loaded or something?
yeah
They run on startup, or when the plugin is toggled on or off
you probably need to use this if u wanna port volumebooster https://developer.mozilla.org/en-US/docs/Web/API/GainNode/GainNode
oh i know
mhm
any ideas how we can get AudioNodes for clients in vc?
or at least how to get clients in vc
i already have the audiocontext and audiodestinationnode
is there any your git repo or branch for it?
not yet
im only gonna work on it on my laptop so i wont push it until its ready probably
ohh okay
maybe will be good idea to include this volume booster plugin as default work of Vesktop?
ohoohohohohoho
im getting somewhere
userid of each speaking user is here
hm
by default
discord has one audiocontext
not one per user
phuck
hmm
i have to find out where it gets the audio stream from and patch it before its handed into the audiocontext
i wonder if i can use the ssrc
nvm nope
hmm
curious
there's only ever one mediastreamtrack for audio
but yet it can still change individual user volume?
For a plugin, when enabled, I want to create a new tab under a currently existing section in settings. For example, under "Vencord", add a new tab under "Cloud". How could I implement that? I've only been able to get it to where I can create a separate section or a lone tab, but I haven't been able to figure out how to implement a new tab button under a currently existing section.
There is a customSections in the _settings plugin, but it doesn't seem to be used anywhere, including startupTimings which adds a section more directly
Lmao
@scenic stirrup did you see "localVolumes" property of conn? Looks like it stores settings per userId with double value of volume from 0 to 200
yeah
we can use it and maybe we need to change volume here when user in plugin changes volume
yeah but i want to figure out how volume is actually done
because the plugin used to be able to go up to 1000%
so i want to recreate that
**index.ts: **Lines 40-49
const customSettingsSections = (
Vencord.Plugins.plugins.Settings as any as { customSections: ((ID: Record<string, unknown>) => any)[] }
).customSections;
customSettingsSections.push(() => ({
section: "Vesktop",
label: "Vesktop Settings",
element: SettingsUi,
className: "vc-vesktop-settings"
}));
All the sections added by Vencord (ie startupTiming, Cloud, Updater, etc.) seem to be using "find" for discord assets and then add a section using replace. The issue I'm running into is sections added by Vencord can't be found in discord assests (at least from what I'm seeing)
so I'm not exactly sure what I'm supposed to be putting for find in this case
How am I supposed to do it for the main Vencord sections since push wouldn't be an option here?
https://github.com/Vendicated/Vencord/blob/main/src/plugins/_core/settings.tsx#L68-L124
**settings.tsx: **Lines 68-124
customSections: [] as ((SectionTypes: Record<string, unknown>) => any)[],
makeSettingsCategories(SectionTypes: Record<string, unknown>) {
return [
{
section: SectionTypes.HEADER,
label: "Vencord",
className: "vc-settings-header"
},
{
section: "VencordSettings",
label: "Vencord",
element: require("@components/VencordSettings/VencordTab").default,
className: "vc-settings"
},
{
section: "VencordPlugins",
label: "Plugins",
element: require("@components/VencordSettings/PluginsTab").default,
className: "vc-plugins"
},
{
section: "VencordThemes",
label: "Themes",
element: require("@components/VencordSettings/ThemesTab").default,
className: "vc-themes"
},
!IS_UPDATER_DISABLED && {
section: "VencordUpdater",
label: "Updater",
element: require("@components/VencordSettings/UpdaterTab").default,
className: "vc-updater"
},
{
section: "VencordCloud",
label: "Cloud",
element: require("@components/VencordSettings/CloudTab").default,
className: "vc-cloud"
},
{
section: "VencordSettingsSync",
label: "Backup & Restore",
element: require("@components/VencordSettings/BackupAndRestoreTab").default,
className: "vc-backup-restore"
},
IS_DEV && {
section: "VencordPatchHelper",
label: "Patch Helper",
element: require("@components/VencordSettings/PatchHelperTab").default,
className: "vc-patch-helper"
},
...this.customSections.map(func => func(SectionTypes)),
{
section: SectionTypes.DIVIDER
}
].filter(Boolean);
},
?
this is how you do it
How would I access React.createContext earlier than the start function for the plugin? I have a React component that depends on a discord component which I have wrapped in a context provider so I can pass state a lot more easily, but the context isn't created early enough and crashes the client because it doesn't exist when the discord component is being created. My code is a bit jank, as well, and could probably do with some of it being turned into a source patch, but it's a rather complex thing to patch with a regex patch.
Some code for context: ```tsx
patches: [
{
find: ""ChannelTextAreaBars"",
replacement: {
match: /"ChannelTextAreaBars"}),(\i)=[];/g,
replace: ""ChannelTextAreaBars"}),$1=[];$self.addBars($1);",
},
},
],
async start() {
TranslationContext = createContext({ original: "", translation: "" });
let textArea = findComponentByCode(",renderAttachButton:eb,renderAppLauncherButton:eG,renderApplicationCommandIcon:ew");
let render_original = textArea.type.render;
textArea.type.render = function (e: any) {
let [state, setState] = useState({ original: e.textValue, translation: "" });
if (e.textValue != state.original) {
setState({
original: e.textValue,
translation: translation.process(e.textValue)[1],
});
}
return <TranslationContext.Provider value={state}>
{render_original(...arguments)}
</TranslationContext.Provider>;
};
},
addBars(bars: any[]) {
if (!TranslationContext) {
return;
}
let state = useContext(TranslationContext);
if (state.original == state.translation) {
return;
}
bars.push(
<Flex style={{ padding: "0.45rem 1rem", lineHeight: "16px", color: "white", gap: "1rem", alignItems: "center" }}>
<span>{state.translation}</span>
</Flex>
);
}
// on top level
const getContext = makeLazy(() => createContext({ ... }));
useContext(getContext());
Thank you, that does seem a lot better.
My only other problem now is that I think my function hook is also made a bit late.
thats why u dont use monkey patch
use a proper patch
that patch sounds like a pita, tbh
thanks for the help ```js
function filterForChatTextArea(m: any) {
if (typeof m != "object" || typeof m.type?.render != "function") {
return false;
}
let search = /,renderAttachButton:\w{2},renderAppLauncherButton:\w{2},renderApplicationCommandIcon:\w{2}/g;
return search.test(Function.prototype.toString.call(m.type.render));
}
waitFor(filterForChatTextArea, (m) => {
let TranslationContext = getContext();
let render_original = m.type.render;
m.type.render = function (e: any) {
let [state, setState] = useState({ original: e.textValue, translation: "" });
if (e.textValue != state.original) {
setState({
original: e.textValue,
translation: translation.process(e.textValue)[1],
});
}
return <TranslationContext.Provider value={state}>
{render_original(...arguments)}
</TranslationContext.Provider>;
};
});
found it
:)
will do that tomorrow
is it a terrible idea to make a patch that inserts an import and calls it...
context: trying to make an option that hijacks the download hover button for attachments and redirects it to the configured media downloader plugin instead of opening it in the browser
Yes
Very much
this is because i figured out how to make it appear on images relatively easily, but they just open the image in browser
Just make a function in the plugin and reference said function instead of trying to do whatever you're trying to do from entirely within the patch
do you not have to import the function to reference it
No
oh thats relatively easy then
Define it in the plugin definition then $self.whateverYouWant
NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
i was able to create a gain node on a specific user's audio stream
so i think ive got it

classic
where do i get a specific users audio stream
i want to know (for future reasons)
uhm
so
i am being very x y
uh
i want to stop connecting everything to one output
and give every user their own output
i want to do virtual surround sound or hook specific people up to certain speakers
if i have more then ~4 people in vc
and they are all yapping
it is very hard to focus on someone
@dull magnet, i'm super sorry to bother you again but do you still have plans to review https://github.com/Vendicated/Vencord/pull/2161/ ?
I just remembered that the pr existed because i remembered to update my fork because i wanted to check if there were any vencord updates xd
This feature is inspired by https://github.com/Puyodead1/replugged-stafftags
It took me 3 hours to figure out how to do this in Vencord and I'm so glad I did because it looks just so much bette...
Oh i really like this!
They get around to reviews eventually
👍
i feel like i can't use vencord without it
i cant use discord without vencord
hello, i am trying to make a plugin and i made the folder inside userplugins, did pnpm inject and pnpm test but the plugin doesnt start, the json output doesnt mention it and the command i put doesnt work either (i copied it from friend invites to test)
this is the code
import { ApplicationCommandInputType, ApplicationCommandOptionType } from "@api/Commands";
import definePlugin from "@utils/types";
export default definePlugin({
name: "Auto Join VC",
description: "This plugin is absolutely epic",
authors: [
{
id: 0n,
name: "Your Name",
},
],
patches: [],
// Delete these two below if you are only using code patches
start() {
console.log("asd");
},
stop() {},
commands: [
{
name: "create friend invite",
description: "Generates a friend invite link.",
inputType: ApplicationCommandInputType.BOT,
options: [{
name: "Uses",
description: "How many uses?",
choices: [
{ label: "1", name: "1", value: "1" },
{ label: "5", name: "5", value: "5" }
],
required: false,
type: ApplicationCommandOptionType.INTEGER
}],
execute: async (_, ctx) => {
}
}
]
});
did you enable it
ye thats the thing i dont know how
i asked that in support too
where do i enable it?
in the plugin settings? doesn't show up
how could i make the current user join a vc?
hold a gun to their head and tell them to
thats one way i guess
Is there a way for a plugin to download files externally (like from github) after being enabled?
yeah
just use fetch or something
and if you want to save it to the user's system you need a native.ts file
thank you
What am I doing wrong?
import { createWriteStream } from "fs";
export const saveFile = (data: Blob, filename: string) => {
const filePath = `path/to/save/${filename}`;
const stream = createWriteStream(filePath);
const reader = new FileReader();
reader.onload = function () {
stream.write(Buffer.from(this.result as ArrayBuffer));
stream.close();
};
reader.readAsArrayBuffer(data);
};
I keep getting this error whenever I try to import from fs or fs/promise here
X [ERROR] Could not resolve "fs"
src/userplugins/extraPlugins/native.ts:9:29:
9 │ import { readFileSync } from "fs";
╵ ~~~~
The package "fs" wasn't found on the file system but is built into node. Are you trying to bundle
for node? You can use "platform: 'node'" to do that, which will remove this error.
1 error
Build failed
Build failed with 1 error:
src/userplugins/extraPlugins/native.ts:9:29: ERROR: Could not resolve "fs"```
works on my machine... what command are you using to build it?
do you have fs?
no wait
I'm stupid
tried both pnpm build and pnpm watch
function getDominantColor(imageUrl: any) {
if (imageUrl) {
const ctx = document.createElement("canvas").getContext("2d", { willReadFrequently: true })!;
const src = imageUrl;
imageUrl = new Image();
imageUrl.crossOrigin = "";
imageUrl.src = src;
ctx.imageSmoothingEnabled = true;
ctx.drawImage(imageUrl, 0, 0, 1, 1);
return ctx.getImageData(0, 0, 1, 1).data.slice(0, 3);
} else {
return [0, 0, 0];
}
}```
im using this method to get the dominant color from the album art, but doesnt always return the dominant color
- it either still returns #000000 or takes long to actually get the color
- even if it got the color, it changes to #000000 quickly (the spotifycontrols plugin is sending multiple requests?)
discord has a function for that
for grabbing dominant color? im not sure how to find that
wondering if i can have any tips to prevent the color from going blank
the fact it works on your machine but not on mine is weird though
I tried reinstalling Vencord from git again and it still didn't work for me
What command are you using
for the reinstall: git clone https://github.com/Vendicated/Vencord
cd Vencord
for the build: pnpm build and pnpm watch
i didnt test your code but my plugin does the exact same thing, and yea mine isnt a userplugin thats the only other difference i can see
unless theres more context to yours that is missing
I just had such a horrible/amazing idea
A theme that procedurally generates using the color of the song you're currently listening to
someone was looking for that too
ok i just struggled for half an hour
I can't even fucking get the album cover data 💀
did u pnpm i lol
of course
i was wondering if its possible to remove the limit of discord only storing up to -2500 chars in the send message input? if so, how tf would i do that. kinda new to this so im not exactly sure where i should be looking
no i don’t think that’s possible, i also i think a slip message plugin is consider Api abuse
You can probably remove the client-side max limit, but it won't do you any good
exactly my point, with the split message plug-in
After my PR is reviewed and some changes are made, do I need to use the re-request review button or no?
basically you can click it and something will happen
i modified the spotifycontrols plugin instead to output the color, thats how i did it
not sure why it becomes blank after a while / doesnt output correctly
I'm stumped with the Native.ts. I keep getting errors regarding node related imports. I'm pretty sure its just a matter of me not being familiar with Native.ts but I cannot figure out what the problem is. Would appreciate any help/guidance.
src/userplugins/extraPlugins/native.ts:8:21: ERROR: Could not resolve "child_process"
src/userplugins/extraPlugins/native.ts:9:20: ERROR: Could not resolve "electron"
src/userplugins/extraPlugins/native.ts:10:15: ERROR: Could not resolve "fs"
src/userplugins/extraPlugins/native.ts:11:30: ERROR: Could not resolve "path"
Native.ts:
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { exec } from "child_process";
import { app } from "electron";
import fs from "fs";
import { extname, join } from "path";
interface Plugin {
name: string;
downloadUrl: string;
description: string;
tags: string[];
}
export function installPlugin(plugin: Plugin): void {
const targetDirectory = join(app.getPath("userData"), "userplugins");
if (!fs.existsSync(targetDirectory)) {
fs.mkdirSync(targetDirectory, { recursive: true });
}
let command;
if (plugin.downloadUrl.includes("/blob/")) {
const rawUrl = plugin.downloadUrl.replace("github.com", "raw.githubusercontent.com").replace("/blob/", "/");
command = `curl -L "${rawUrl}" -o "${join(targetDirectory, plugin.name + extname(rawUrl))}"`;
} else {
command = `git clone "${plugin.downloadUrl}" "${join(targetDirectory, plugin.name)}"`;
}
exec(command, error => {
if (error) {
console.error(`Error downloading the plugin: ${error.message}`);
return;
}
console.log(`${plugin.name} has been successfully downloaded to ${targetDirectory}`);
});
}
ExtraPluginsTab.tsx:
are you trying to import the file from index
that's now how it works
look at other plugins using that file for an example
you need to access its exports via the VencordNative global
Yeah that's what I meant, just removing the client limit
but why there would be absolutely no point in doing that, it literally won’t do you good ?
understood! if it will get checked either way then there's no point sending a useless notification
well if im writing out a really long message then its a pain when you switch channels and come back and boom its wiped a bunch of the stuff you wrote
i mean, yeah its definitely a niche annoyance. but i find it to be very annoying nonetheless
what the fuck are you talking about
there is no 2500 chars limit
no the limit is 4500
or 6500 if you have nitro
hence -2500
beyond that it wont save
switch channels
as in, draft saving?
yes
ah
I see
yeah'
4500 limit
with nitro
hmm
AH
this is it
it is literally just in DraftStore lmfao
Error in handlePush TypeError: patch.find.every is not a function
at patchFactories (patchWebpack.ts:190:42)
at Array.handlePush (patchWebpack.ts:85:13)
at shared.eb18f7955c6b0fd48757.js:1:65
What the hell is going on here?
update
will bother #👾-core-development
Is there any way to turn off webSecurity?
or some other method to send cross-origin requests?
you could do it with a .native plugin, but that would make it not work on the website
if you do it from native.ts that will work
i'm trying to insert more icons into the top toolbar. i found that vencordtoolbox already does this, i took the patch from there and i don't know how to make my plugin not conflict with vencordtoolbox. is there any way?
**index.tsx: **Lines 138-146
patches: [
{
find: "toolbar:function",
replacement: {
match: /(?<=toolbar:function.{0,100}\()\i.Fragment,/,
replace: "$self.ToolboxFragmentWrapper,"
}
}
],
as I understand it replaces s.Fragment with its own icon, but I don't understand the logic at all, why it replaces exactly that and how to make a more universal patch
shouldn't it just work, because the patch uses $self.function ?
The patches conflict with each other
ok
How would i go about checking the users embed permissions in a specific channel id?
not sure how in the client code but in the api all that stuff is on the channel object, also note that denied SEND_MESSAGES also implicitly denies EMBED_LINKS
in the api all that stuff is on the channel object
nah, its just that your OOP discord library provides those methods :p
ok true lol but it's the js api library...
How can i patch a message components content as a string? i'm probably being stupid but whatever component i look in, the content gets passed as an array of components (usually spans)
what are you trying to achieve that would need this specifically opposed to say, adding a markdown rule
(i say cluelessly as modifying markdown rules is an entire ordeal without webpack interop)
I'm making a version of the message encryption plugin that does it automatically and replaces the original message content
find: ".ChatInputTypes.EDIT,content:"
you can probably just directly modify it here and skip a bunch of bullshit
literally just add to the children of that fragment wherever you want your button to be
idk why toolbox is over-engineering things
i have a horrible confession
I drafted up an idea for a plugin for someone in here a few days ago and just forgot about it
@dull magnet thanks for reminding me to open my editor lmao
tbh slate is a horrible cursed mess i refuse to do anything with it
this is fine yes
where is this???
vesktop feature
oh
it isnt
i am loading it from my desktop
on my laptop
because i need to test with a touch screen
how patch helper opens exactly? isn't it by pnpm watch?
yeah but you can also do pnpm run build --dev if u want
@cedar olive Could you re-review https://github.com/Vendicated/Vencord/pull/1639 ?
not really, its just that it and simplemarkdown are meant to be static and not modified at runtime
oh i didnt mean like bad code
just cursed mess to actually work with
i wonder where slash commands permissions are retrieved from
prob here
how about you add plugin to fake move someone's message to another channel
but idk
does the client even know that stuff
the client gets sent all commands even those which it doesn't have permission to use
so it would need to
ohh
can see it now 
for some reason this thing wasn't showing for a command i'd disabled for everyone on a server i am admin on but i'm not admin in vencord and it shows now .. weird
yea thanks applicationcommandstore looks like the place!
although you probably need to fire a request if it's not yet loaded
fire? idk
🔫
it has been less than 1 hour since the topic of "explicitly requesting slash command metadata" has been relevant
(see that voice channel bot config pr and my idea of use slash commands for it)
i will make a whole plugin then give up (never submit PR to upstream)
not even to #1032200195582197831
should i add a tab to the guild permissions window
i know
it doesn't really make a lot of sense to display it in the channel menu
should i use an ErrorBoundary around the tabs component or for each tab
when in doubt, do both'
eh
just put error boundary around the tab contents and the modal itself
@pure temple if you're around PermissionsViewer, could you review my PR? it's been needing a re-review since last year.
i don't have write perms
just a review would be nice
it refactors some of the rendering logic so that'd affect what you're probably doing
i'm not that competent with this stuff lol
i just found it weird you were asking me
but sure i could give thoughts if any
it's been needing a re-review since last year
![]()
![]()
![]()
![]()
I'm trying to find the navigation id of images in messages
but I can't find it
nvm
what
# 1
function playSound(url) {
var a = new Audio(url);
a.play();
}
# 2
const audioElement = document.createElement("audio");
audioElement.src = settings.store.quality === "HD"
? MOYAI_URL_HD
: MOYAI_URL;
audioElement.volume = settings.store.volume;
audioElement.play();
which way is better?
I want to play a sound without it being delayed
Would it be possible to cache loaded gifs in favourites for next time? i'm sick of this shit taking 20 years to load everything 😭
@dull magnet since discord are now calling bots "app", i'm updating my moreusertags pr to use the new string
so that it uses the same text as the vanilla client does
https://github.com/Vendicated/Vencord/pull/2161
here it is if you need a convenience link(™)
This feature is inspired by https://github.com/Puyodead1/replugged-stafftags
It took me 3 hours to figure out how to do this in Vencord and I'm so glad I did because it looks just so much bette...
I have a question. If I use a patch from someone else's plugin, what would be the proper way to credit them?
adding a comment with their name is probably the best way
making a plugin to access quests easier
horror
trying to load the quest chunk with this code (this is just the necessary stuff), but it doesn't find it
[...]
const requireQuests = extractAndLoadChunksLazy(["getLevelAndMarkUsed:"]);
[...]
export const openQuestsModal = () =>
requireQuests().then(() => openModal(props => <QuestsModal {...props} />));
the modal and stuff alr works
but crashes, if the chunk wasn't loaded alr
use openModalLazy
still not working
export const openQuestsModal = () =>
requireQuests().then(() => openModalLazy(() => Promise.resolve(props => <QuestsModal {...props} />)));
(adjustements made by copilot, so....)
or
the string I use to find the chunk is wrong
lemme try a different one
......
true
lol we're doing the same thing 💀 the difference is i want to make it a home tab ( https://github.com/Vendicated/Vencord/pull/2364 )
the problem is i cannot find the way for setting content of home tab (the thing on screenshot)
I saw your plugin and making it with a modal, because the current state of your plugin is, that it just opens the gift inventory
try searching for route in this channel or #👾-core-development
saw someone discussing that a while ago
hmm okay. i'll check
search might be bad..
yea that's why i want to make it the way like i'm saying above. it just feels like very lazily made plugin to me and i can do better than this
okay, thanks. i'll check them out
ok, so either I am dumb as hell, or idk....
trying this now, which doesn't work
no
.
from what I saw in EmoteCloner this is my understanding, on how it works
very lost now..
export const openQuestsModal = () =>
requireQuests().then(() => openModalLazy(async () => {
return modalProps => (
<QuestsModal {...modalProps} />
);
}));
this my current code
and it is failing
because of these errors
no
emoteCloner isn't fetchData().then(data => openModalLazy(())
can you maybe help me instead of just saying no?
im helping u by telling u to look at examples
hoping you can figure your mistake out yourself
note how every usage of openModalLazy has its promise call inside the Lazy
that's the point of the function
**index.tsx: **Lines 282-283
openModalLazy(async () => {
const res = await fetchData();
**CreateCategoryModal.tsx: **Lines 130-132
openModalLazy(async () => {
await requireSettingsMenu();
return modalProps => <NewCategoryModal categoryId={categoryId} modalProps={modalProps} initalChannelId={channelId} />;
this was very helpful
thank you
for some reason VSCode Search couldn't find that
only issue now is, that the find for the quest chunk is not successful
ok got it working. i'll put the actual content now lol
nice
How do rpc timestamps actually work? i thought they were just unix timecodes but no matter what i do, i can't get the session length to go above 24 hours
try to add 000
Exactly the same thing
i thought they were snowflakes?
i think it's fine like that..
though i might also add something on top of the page
only question is
does it crash if the module isn't loaded?
what code are you using for that
so what string
to match in the module
because I was struggling with that
const requireSettingsMenu = extractAndLoadChunksLazy(['name:"UserSettings"'], /createPromise:.{0,20}Promise\.all\((\[\i\.\i\(".+?"\).+?\])\).then\(\i\.bind\(\i,"(.+?)"\)\).{0,50}"UserSettings"/);
``` here to require settings menu
```ts
const QuestsComponent = findComponentByCodeLazy(".useQuests)({fetchPolicy:\"cache-and-network\"});(0"); // No nessessary props to include
``` here for quests component (probably can be done better but i'm too silly to find out  )
const requireQuests = extractAndLoadChunksLazy(["isQuestExpired:"]);
used this
but the string to find is wrong
lol i used the one from above that ven sent
?
'
he didn't send a string for that
but here's requireSettingsMenu
ohhhhhhhhhhh
the second one can be done easier by just using const component = findComponentByCode(".questsContainer");
that's amazing
were you trying to add your own page here? if so, i am curious, how do you feel about an api to do add pages to here
if you figure out how to get the original top bar (or recreate it) please do tell me
find the component
i highly doubt the component is separate from the page content
considering how it is actually rendered
think I found it
try to find it with the classname
but without the __3337a part
yeah i know how to find classname references
ok
oh so you can also find it that way-
oh well. at least i know now 
I sure do hope my Homepage plugin concept isn't stuck in the hell that is my desktop 
Homepage plugin?
what does it do?
i was trying to recreate the inbox but as like a full page feed thing
hmm in the meanwhile i'll try to create this plugin. https://github.com/Vencord/plugin-requests/issues/350
doesn't seem to be THAT difficult, just patching media modal (rest of the stuff like src, size etc. are already there) and adding some context menus. the first one is already done by me partially 
Plugin Description Image utilities style image saving (pre-define a location)> Right click image > Save Image to > {FolderName} Existing Plugin for other mod https://github.com/mwittrien/B...
alos tried doing that one, but gave up, because I couldn't find the navigation id (necessary for context menu patches) if embedded images
would making a plugin to bypass automod be not allowed
(by inserting invisible unicode characters between letters)
most of the time there's reason why's there automod on the server
why would you want a plugin that bypasses it
to be creepy or racist prolly
most likely
no this one server blocks a shit ton of words and i need it for troll
like they block ”this“




