#🧩-plugin-development
1 messages · Page 58 of 1
show code
i suspect you're accessing webpack modules too early
plugins run very early at a point where discord hasn't loaded yet
so if you use React.forwardRef on the top level it will fail
which do you want cause its really all split up
just how you declare the component
yep there's yor issue
you are using react on the top level, where it's not ready yet
wrap the react.forwardref call inside LazyComponent(() => {})
const CanvasComponent = LazyComponent(() => React.forwardRef(..
thanks it works now
actually idk if that actually works cause lazy component doesn't forward ref itself
you could inline require the file
or
const getCanvasComponent = makeLazy(() => React.forwardRef())
// use
const CanvasComponent = getCanvasComponent()
<CanvasComponent />
yeah actually referencing it now
nah was a self bot lol
anyone with e-z bio or some shidd in their bio is a skid doing that stuff

If you are writing a plugin that depends on another plugin, how do you handle that import, considering the user may have installed the plugin in either the "plugins" or "userplugins" directory?
Currently I am using a very hacky try/catch to import from both locations, but I'm wondering if there's a common way to handle this?
For example
import { somethingINeed } from "plugins/foobar/something";
The above would fail if the user had installed "foobar" plugin into the userplugins directory.
the easiest way to do this would be to just add the method you need to share between plugins to definePlugin and then just use window.Vencord.Plugins.YourPlugin?.yourMethod in the other plugin. typescript yells at you for this but you can ignore it, and i'm pretty sure some official plugins do this too
yes
Does that mean the "foobar" plugin in my example above would need to be updated?
That may be an option if so, thanks regardless, I will look into this method.
im back again trying to make a plugin, but im still struggling to make a patch
im trying to get the chat box, and try to add a simple onClick to it, but Im not getting very far =/
any tips for a noob on how to properly make a patch?
Im using the companion, it is pretty nice, it says it found 3 matches, which is not good, is there a way to jump to those matches in the dev tools?
ctrl shift f
when i run pnpm test it throws an error for invalid plugin because authors contains non-property access expressions, however my authors array is correct. does this mean it is possible* my plugin acting up?
i followed the current Plugins Guide
authors: [
{
id: 240125663619579905n,
name: "vegard",
},
],
authors: [Devs.vegard]
I managed to patch an element of the text box to place a onKeyUp event on it.. but Im trying to modify the content of the text input
so far I wasn't successful, changing the DOM does not really work well
ComponentDispatch.dispatchToLastSubscribed("INSERT_TEXT", {
rawText: text,
plainText: text
});
seems to work ok for adding text, but I actually want to remove the text...
findByProps("ComponentActions").ComponentActions
perfect, that was exactly what I was looking for
turns out CLEAR_TEXT exist
thx bro
sorry if this is annoying but i'd just like to remind you about my pr real quick
I want to create a shortcut with the keys ctrl + enter but this key combination sends the message.
I tried document.addEventListener("keydown", onKeydown); on start() and then e.preventDefault(); but it seems to be sending the message anyway
any idea of how to prevent the message from being sent when pressing this combination?
what do you actually want to achieve
Im making a grammar checker. when I type, it creates a box with the corrected text.
I want to transfer the text from the preview to the chat box when I press ctrl + enter.
it already works fine if I use a different shortcut that does not involve the key "enter" just because the enter key currently sends the text no matter what
if you wanna do it with your approch could try ```js
function onKeydown(e) {
// [...]
e.preventDefault();
e.stopImmediatePropagation();
// [...]
}
document.addEventListener("keydown", onKeydown, true);
vee probably has a better idea though
@dull magnet is this good enough? :3
getAvatarStyles(src: string) {
return Object.fromEntries([128, 256, 512, 1024, 2048, 4096]
.map(size => [`--avatar-url-${size}`, `url(${src.replace(/\d+$/, size.toString())})`])
);
},
actually sorry for the ping, I'll just push it and let you review it :D
What's the best way to let the user upload a file? i tried checking the way decor let's you upload decorations but it just uses a component from discord, whereas i only want a way to do the prompt
Look in src/utils/settingsSync.ts
I'm trying to use a library that requires nodejs 19 or higher for a plugin, running node --version says my version is already 19 but i still get an error when trying to build (Could not resolve "node:fs"), do project node versions exist? I've tried using a bunch of different versions (18, 19, 20, 21, 21) but i assume that vencord itself is just configured to use a different one and i don't know how to change it (in which case i'm pretty screwed)
My brain is NOT big enough for this shit
youre likely importing it in the browser side
browser cant use fs, etc
oh yeah dont use that library
you really dont need it
use fetch()
the docs are a bit confusing so i'll give u some pointers:
you need to use FormData
and send these params
Note: for anonymous uploads, simply don't supply a userhash.
File Uploads
reqtype="fileupload" userhash="####" fileToUpload=(file data here)
where for fileToUpload you'll want a blob with the bytes
This is super helpful, thanks 
The request is getting blocked by CORS 😭
damn
yeah you'll have to send it from nodejs then
but you still dont need the library
you can just copy paste your code to nodejs and itll work fine
native.ts file is how u can run code in nodejs
look at how other plugins use that file
all of them
ok i have everything set up with native but my plugin isn't in VencordNative.pluginHelpers, is there something i need to do to register it or smth?
restart discord fully
I am not very smart damn
For some reason if i build with the plugin in the folder, vesktop just doesn't open- if i run it from console instead this is the error log i get, i assume i did something wrong (code here)
if i had to guess cause your calling a function from index in native.ts
also dont do this
you dont want to load native every time you click the button
Hm yeah, maybe. If i move the fileToBlob function to native.ts instead the line that defines native throws an error
Can't read the error for the life of me tho
dont export it
Gfd
Alright i'll test that now
Well it opened
That's surely a good sign 💀
I now get this error when handleButtonClick gets called, i think it's an issue with the native upload function? i updated the gist with the new code
(just for future reference, it doesnt make a difference, it's a static object)
Fair enough
the error is pretty self explanatory. whenever you pass an object via ipc (what VencordNative does for you under the hood), everything you pass as arguments and return value gets cloned because its a different process
you're passing a File object which i guess cant be cloned
pass raw blob / UInt8Array via ipc
raw 
your fileToBlob should be in index.ts
Uhhh so yeah i just move filetoblob to index then pass the blob to native instead?
yes
make sure you full restart
Real
I am updating an old PR and now find out that two components I need are lazy loaded. My old method of fetching these was using a plaintext patch that assigned the two components to $self, but that doesn't work anymore due to said lazy loading. What's the best method to do this now? Is it possible to force-load a module?
The components won't load until you open the settings views in which they're visible at least once, which isn't exactly ideal.
**CreateCategoryModal.tsx: **Line 36
export const requireSettingsMenu = extractAndLoadChunksLazy(['name:"UserSettings"'], /createPromise:.{0,20}Promise\.all\((\[\i\.\i\(".+?"\).+?\])\).then\(\i\.bind\(\i,"(.+?)"\)\).{0,50}"UserSettings"/);
**CreateCategoryModal.tsx: **Lines 129-133
export const openCategoryModal = (categoryId: string | null, channelId: string | null) =>
openModalLazy(async () => {
await requireSettingsMenu();
return modalProps => <NewCategoryModal categoryId={categoryId} modalProps={modalProps} initalChannelId={channelId} />;
});
How do I figure out the arguments here?
basically whenever there's a lazy loaded chunk, some other module will have code for loading said chunk
it looks something like
Promise.all([n.e(1234), n.e(765)]).then(n.bind(...)) ```
you need to find the part in the code that does such loading of the module you need, find it via the first argument and then use a regex to capture the loading code (the function has a default regex that works for many cases)
yep that's it
so the first argument is an array of finds that will end up finding the module containing this piece of code?
if you need more help you can bug nuckyz about it, he wrote that function and tbh i never used it
yep
there's also jsdoc on the func that'll probably help
alright, thanks for the pointers, I'll see if I can figure it out :)
basically the 5609 here is the id of the chunk that needs to be loaded and 336231 is the entry module id
so the function has you match those and then loads the chunk(s) and requires the module for you
right so I don't have to worry about 5609 myself right
the module that contains this snippet is 619326, that's the one I should be writing my finds for, yes?
just double checking
yes
I think the default regex might work for this snippet in particular
at least it looks like it
nevermind, appears I'll have to make one based on the one in pinDms since it looks similar
well, that seems to do it I suppose
can u just copy paste the one from that
it might work if you need just the settings too
it loads the colour swatches
actually yeah you just want the colour picker stuff right?
you can just copy paste allat from pinDms
right yeah
there's another one I need however, will figure it out
need the profile modal still
hah, and just like that we're back in action
coolio
ah, yes, this again
@dull magnet I remember you giving me a solution to disable mouse interactions (setting pointer-events to none on a parent div), but that doesn't work
do you have any other wild guesses?
pretty sure events go from lowest element to highest
so it will prefer clicking the lowest element (in the tree)
though, adding !important also fixes it... 
oh does it?
ahh yeah okay so you also set it on all children makes sense
@dull magnet Updated the PR, could you check?
does anyone know why this item isnt being patched to the context menu
this is my code btw
also ignore the console logs and other stuff
ima remove that later
help would be very appreciated <3
guys is dom manipulation acceptable if i want to render a component on top of everything else on discord
not sure where to patch
like createroot then render
like that
yes
pog
https://react.dev/reference/react-dom/createPortal might be of interest for doing that without dom manipulation
this will come in useful eventually
that's so cool lmao
Is it ideal to patch over existing Store data to remove hidden embedded strings (like FakeProfileThemes' 3y3 system) or to remove them from wherever it's rendered?
If the former, how should I do that?
I'm planning to hide data inside channel topics
I dont understand what you want exactly
I would rather not have end users able to see the hidden 3y3-like data in my idea
If you're wondering what I'd use this data for, I want to build a way to replace the channel icons
Bump 
but why would those have 3y3 data?
that's using the old way the api worked
So I can store custom channel icon identifiers in there
- const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => () => {
+ const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => {
it wouldn't be the same 3y3 format
oh
it depends honestly
but probably where it's rendered
do it first, fix the issue of those later
where even is channel topic rendered other than the obvious places
forum channels
those too
yeah thats what I mean
i realized my mistake...
ya'll know how to install a user plugin on vesktop?
Not support channel + Dev install are not supported
check pin in #1032200195582197831 , thats all you got
alr mb
dw about it, just use the correct channel next time
Bump, still trying and failing to fix 
that was easy 
can I somehow render custom emojis without getting the emoji url and wrapping it in some random img tag
I don't know the discord internal API well, but could we hook to any endpoint to check the unread/pings of the account switcher to display a little badge?
nevermind, idk what i expected honestly
How can I debug a plugin more easierly?
(like there is an issue in fakenitro where if you use the default discord emoji in a non embed channel the popout for no perms appears, i think the issue is https://github.com/Vendicated/Vencord/blob/f74da73086b2b361490e028c999c80b3ac2ba76a/src/plugins/fakeNitro/index.tsx#L812 here, but idk how to check for native emoji)

Real and true
true asf
I feel you
so relatable
congrats, if only my plugin aren't whole codebase itself. lol
you love making one branch and commit everything to it directly
goddamn you are right
trust me, git was designed for feature branches
I am awful when it comes to isolation features
ok so heres how it works
basically when you want new plugin
you make new branch
do not branch off that unless you need to attempt modifications to that plugin
or you could go back and branch off older commits if you regret something
basically
branch for major changes to stuff
once you are happy with it
you merge into your actual branch with everything
so what you saying, that I should keep my plugins in separate branches and merge them when they are complete?
yes
I will make sure to remind myself when I use git next time. thanks
git please be logical, do what I want for once
impossible
-._.-
so i figured out adding buttons to messages pretty easily, but is there a way to only add a button on specific messages? like how the edit button only shows up on your own messages? or delete on messages you have permission to delete? (if sm1 responds, please ping me tyty)
you can return null
ty; 2nd question, is there a way to call async promises inside start()?
sure why not
ah i didnt realize i could just.. make it async lol
just make it not run too long
I believe no, as that would require connecting to the gateway. also, https://docs.discord.sex/
yes but what's the problem with that?
I feel like constantly connecting and disconnecting whenever you open the account switcher may be seen as sus from discord's end? not sure about that though
if there is an endpoint I don't know about though, then it's probably somewhere in those docs
why not just stay connected the whole time to be able to receive notifications from other accounts?
honestly amazed that this is not a feature in discord already
that's an alternative
like not even a badge, nothing
the closest endpoint is https://docs.discord.sex/resources/user#get-recent-mentions but that's only the past 7 days, it doesn't include unread DMs, and it relies on people clearing their inboxes
Yeah that was what i was thinking!
Yes but thats not useful neither for dm or unread
it sounds like an interesting idea tbh
exactly the issue
seems like gateway is the only way to go, to my knowledge
you could maybe hijack their firebase (android push notifications)
that also works
but it takes longer to clear notifications
?
filter out any messages that don't mention you based on the message content (if it's not mentioning you, since you can enable notifications for all messages)
like, if you read the ping in your phone, it will take a while for firebase to push that event
also we cannot retro actively check back pings that were already there with gateway can we?
fun fact this one learned yesterday: firebase is based on xmpp
it's really cursed. android push notifications were originally literally just hooked up to google talk.
i hope it's not tls/xmpp
(bcs it has no framming 💀 )
well how else would official clients do it
I am asking because I dont know!
dead google project
I'm trying to figure out how the client even sees mentions in the first place
(90% of google projects)
oh apparently the xmpp api is now finally deprecated
the gateway events page is pretty incomplete on discord.sex
probably via ready / ready_supplemental gateway event
you get them when you first connect
I'm reading the doc for that
okay then it shouldn't be too hard
it doesn't mention mentions though
read_state on the ready event
check if it exists
you can enable gateway log in discord developer settings (use experiment plugin), and enable verbose log in devtools console
seems like the doc for ready event is incomplete
unrelated: is there a nice way to automatically apply a class like theme-midnight to <body> with vencord, to not have to copy-paste the official css from discord?
it is the dispatcher tab in devtools, right? because I refreshed, and I'm scrolling through it, but not seeing READY
and holy shit this + party mode makes my client die
chrome devtools
ahhh
all I get is what seems to be the trace, but I searched read_state and it comes up with that, so I'm assuming read_state is part of the ready event
only with quick css, no
uncompress user plugin doesn't work on desktop wahoo
its right there
it is just a matter of document.body.classList.add("theme-midnight"), but where exactly to inject that (or an edit to the html maybe)
guess I'm blind or I screwed up lol
@stable moss there's your answer then ig
just document.querySelctor("body").classList.add("theme-midnight")
then it would be possible, just needs like a bit of work to connect to the different gateways and very minorly the visuals
hmmmmmm, should i expend my weekend doing that
export default definePlugin({
...,
startAt: StartAt.DOMContentLoaded,
start() {
document.body.classList.add("amongus");
}
})
go ahead, it would be fun
oh thanks
I do have to wonder if discord would find multiple gateway connections being created at once by user accounts too sus, but who knows
the thing is, if we switch accounts constantly we would probably hit a ratelimit, bcs of reconecting too many gateways
is there a way to have a connection persist across account switches?
it's time to make a plugin to allow selecting the hidden darker and midnight (oled, kinda) themes 
not even that, just opening the menu a ton of times
it might be actually better to integrate it with the appearance ui, but it's not a huge deal if it starts off as its own thing ig
No my idea would stay permantely connected and show an indicator only where the user wants
was worth a try sob
actually can make sense too if you're one of those people™️ who use light mode sometimes
as this would only override your dark mode
bcs connecting each time would get us rip pretty fst
like we connect on startup, read the read_state and then just poll events from there
that also works
I'm not sure if modifying intents would be too sus but we could use that to remove some noise, like presence events
on that note what about presences
hmm
you could just send invisible for the default presence
we can always use the new gateway reading app api 💀
the what?
not presences again I don't wanna go back to xmpp
no you cant
it could literally read your messages lmao
and it doesnt affect privacy
gateway connection != reading ur messages
there was always scope that allowed gateway connection
also fyi theres literally a messages.read scope lol
but the vast majority of scopes require discord approval
doesn't that
yeah I was about to say
and it's got something to do with local RPC iirc
they could make this gateway scope require approval tbh
anyway gateway connection isnt anything new
there was always
voice allows your app to connect to voice on user's behalf and see all the voice members - requires Discord approval
iirc steam deck used that one?
never knew apps could join vc for you lmao
that is only one part of gateway though, but tbf we don't know what the gateway scope will contain now or how it will be implemented
so could it read all the data that a normal gateway connection could, just using your oauth2 token instead?
true
oh huh
but when the client sends the API request to change the settings
the API just goes "yup, one dark mode coming up"
well, you can just apply theme-darker and theme-midnight class yourself ig?
ye I suppose
I could probably overwrite the uh
onselect or whatever it is
but how do we persist that
if we do it like this
hm wait there were vencord settings right
a store I mean
seems so
Hello, I'm trying to make a patch that replaces a function. the final goal would be replacing the code that updates (specifically) spotify's rich presence, but for now I'm only trying to make it log updates.
I checked that the find regex only matches one module from the devtools and that the match only matches once in the module with regex101.
I used the experiments plugin as a reference (along with the docs on github) to find my way around how to approach creating a patch and everything seems right, but nothing gets logged to console and the updates still behave as they did without the patch.
Here's my code:
export default definePlugin({
name: "MusicTitleRPC",
description: "Makes the song's title appear as the activity name when listening to music.",
authors: [Devs.Blackilykat],
start: start,
stop: stop,
patches: [
{
find: /"function .{1,2}\((?<e>.{1,2})\){let{connectionId:.{1,2},track:.{1,2}=\k<e>"/,
replacement: [
{
match: /"let{connectionId:.{1,2},track:.{1,2}=([^;]{1,2})"/,
replace: (e) => `$self.thingy(${e}); return`
}
]
}
],
settings,
thingy(e: any) {
console.log(e);
}
});
says it doesnt find anything for me,
u should utilize patch helper (pnpm watch) and vencord companion (vscode extension)
check pins
wasn't using vscode, do I have to to get accurate code? I am using pnpm watch and it checks out on my client
well not required no
just mentioning it's existence
testing finds/patches without leaving ur editor might come in handy
I'll give it a shot and see if it helps
prefer using a find which is a string, not a regex
you are gonna end up destroying the performance of your client startup in accident
look at every other plugin, they all use finds which are strings
wouldn't i have to hardcode names then?
tbh i forgot u added regex finds 
yes but in a find you normally target text that does not change
regex finds are a last alternative for when a string find is not enough
alright I'll change that to a shorter string
find a unique string in your module that isnt minified
for example in your module there's the string ContentInventoryManager"
okay, got vscode and updated my find. Also I noticed I had /"regex"/ iinstead of /regex/ in my match, changing it now gives a SyntaxError:
Patch failed: Replacement 1 failed: SyntaxError: Unexpected strict mode reserved word
Here's the new code:
export default definePlugin({
name: "MusicTitleRPC",
description: "Makes the song's title appear as the activity name when listening to music.",
authors: [Devs.Blackilykat],
start: start,
stop: stop,
patches: [
{
find: "){let{connectionId:",
replacement: [
{
match: /let{connectionId:.{1,2},track:.{1,2}=([^;]{1,2})/,
replace: e => `$self.thingy(${e}); return`
}
]
}
],
settings,
thingy(e: any) {
console.log(e);
}
});
replace replaces the entire matched string, so that also removes the let part
it's supposed to
Can I edit the Clyde message that gets sent with sendBotMessage? I wanna use it as a sort of progress updater for an async task. Or is there a better way of giving progress updates?
oh
Found a solution that sorta works:
let previousMessage: Message | null = null;
while (xyz) {
if (previousMessage) MessageActions.dismissAutomatedMessage(previousMessage);
previousMessage = sendBotMessage(ctx.channel.id, { content: "Hello world" });
}
what is the progress for?
I'm downloading a video with yt-dlp
maybe an UI Component would be more fitting than repetitive bot messages
It was in the back of my mind, but UI scares me...
It shouldn't be too bad it fhere's only 1 message at any given time, and the message disappears once done
It's the result of a slash command, so it feels appropriate imo
maybe you could send a bot message after running the command and send a toast , when it is done
the problem is that while it is downloading, the command hangs. If the download takes a while, there's no clear feedback about whether it's working or not
I just want to show the user that something is actually happening
Coulb probably create a component that shows the loading state or something though
dispatch a message update with the returned message's id
I have now expanded the regex to actually replace the function (instead of having a return; in the middle)
My usage of the replace function in the patch seems to not work, when I hardcode condole.log(e) it patches OK but when I leave it to the capture group (as shown in the code below) it gives the same SyntaxError.
{
find: "){let{connectionId:",
replacement: [
{
match: /let{connectionId:.{1,2},track:.{1,2}=([^;]{1,2});if\(null!=.{1,2}\)\(0,.{1,2}\.isEligibleForListenedMediaInventory\)\("ContentInventoryManager.handleSpotifyNewTrack"\)&&\(0,.{1,2}\.postTrackToContentInventory\)\(.{1,2},.{1,2}\)/,
replace: e => `console.log(${e})`
}
]
}
Alright, updated to use \i and my issue was fixed by using $1 instead of the arrow function. Thanks everyone :)
Though I wonder, why does the experiments plugin use the arrow function when mine couldn't?
{
match: /(?<=>)(\i)\.hasFlag\((\i\.\i)\.STAFF\)(?=})/,
replace: (_, user, flags) => `$self.isStaff(${user},${flags})`
}
you dont have to use an arrow function for basic replacements
replace: "$self.isStaff($1,$2)
that isn't my code, it's from the experiments pluign and my issue is fixed. I was wondering cause I took it as a reference
oh ok
yours can use the arrow function
it's a way to give a name to your capture groups
_ is the full match, user is the first capturing group, flags is the second
the same as $&, $1 and $2
ah, got it. So, since I just treated the only argument as $1, it used the full match instead of the capture right?
what I meant is
I had:
e => `$self.thingy(${e})
but I should've had:
(_, e) => `$self.thingy(${e})
ok cool ty!
the first argument is always the full match
Okay so the little that I have researched this has been:
I need to use the UserStore to get the current user id
Then I (optionally) need to use the MultiAccountStore to get info on the accounts
And use the tokens LocalStorage to get the auth for the gateway
Now only to look how to use the gateway
actually you need to use getToken("user id") to get the tokens
Thanks!
wait where is that function?
findByProps("getToken")
Okay thanks! Now I only need to figure out the gateway connection
And maybe how to persist it across account switching
but im pretty sure the second one gonna be impossible
you need to close the running connection first ig
or create a new socket
that could also would
@signal lichen
the companion told me that Find bad: Failed to find: Found more than one result! Make this filter more specific
And I am trying to smash my head into how the find works
findByProps("setToken").getToken
I guess reading this can help you https://docs.betterdiscord.app/plugins/advanced/webpack
if you dont know modules are like files that export things in javascript
node js
// a.js
export default function A() {}
export const B = 1;
...
import A, { B } from "a.js"
webpack or discord
// a.js
12345: (module, exports, webpackRequire) => {
webpackRequire.setExports(exports, {
setToken: function() {
return setTokenDefinition;
},
getToken: function() {
return getTokenDefinition;
}
})
function setTokenDefinition() {
blablabla
}
function getTokenDefinition() {
dsdfdsfdf
}
}
// b.js
34373: (module, exports, webpackRequire) => {
const TokenUtils = webpackRequire("12345");
function someFunction() {
console.log(TokenUtils.getToken());
}
}
// in a vencord plugin
const TokenUtils = findByProps("setToken");
console.log(TokenUtils.getToken());
Wait you can only have one GateWay connection per window?
but instead of file names, you have numbers, and a cache which you can use to find everything that was required
findByProps iterates the cache and find the module that has an export with the props you want
if you dont know modules are like files that export things in javascript
Ye, commonjs, amd, es6
also yeah i know nothing about webpack, now that makes a little bit more sense
if you look here that's exactly what's happening
it's the way webpack bundles and makes modules work in browsers
yeah, bcs bundling and minification makes a lot of sense
Find bad: Failed to find: Found more than one result! Make this filter more specific
this means more than one module exports a prop named getToken
which is true, another module exports getToken (it's the same function but whatever)
so instead I just changed your filter to setToken, since only one module exports that
function webpackRequire(moduleId) {
var cachedModule = cache[moduleId];
if (undefined !== cachedModule)
return cachedModule.exports;
var mod = cachedModule[moduleId] = {
id: moduleId,
loaded: false,
exports: {}
};
return modules[moduleId].call(mod.exports, mod, mod.exports, webpackRequire),
mod.loaded = true,
mod.exports
}
this is the webpackRequire
wait, so when we get by props lazy it doesnt get found till we use it?
yep
findByProps lazy only does the finding once you first try to use
so that we don't try to search before it was loaded and cached
it would fail if we did
(which I already experienced and now came to that realization)
now you understand why :)
super unrelated but I have worked in something which changes the way we do the finding
it's no longer lazy
elaborate
try to understand yourself first https://github.com/Vendicated/Vencord/pull/2409
(the size of the cache, and this is not everything)
Okay so basically, it will check the cache, and if it misses, it will use wait for, which basically means that it will do it how lazy would do it with the proxy and such
It's clever
yes kinda
but it will not even try the cache if you use it properly
it will directly jump into wait for because nothing has been yet loaded
basically what wait for does is, it will check the filter when this happens
return modules[moduleId].call(mod.exports, mod, mod.exports, webpackRequire)
so as soon as it's loaded it will check if it's something we want
holy shit I just got a crazy idea
it's time to remove this :)

this might actually work super well
:( shit
it uses the object directly
yeah can't run away from that nvm
hmmm wait I can try more cursed stuff
which is actually super interesting
time to cook
okay this is gonna be wild
no fucking way
this doesnt get called for object definitions
I am about to cry.
hm wait
:(
okay what I'm about to do is horrible but I just wanna experiment
you are not understanding.
i < 1000000 
this is kinda working
wait wtf it worked?
lmaooooooooooooo
okay but this killed performance
this is the normal
if only I could intercept any value set... but I can't use a proxy here
huh this does absolutely nothing for me
what plugin might that be?
its ShowMeYourName
class DiscordNotifier extends EventTarget
oh shit here we go again
why are you writing like this
?
wdym
So. I implemented the GateWay myself, I have the upmost basic version of the plugin working now.
Does someone want to help me figure out how to use the native gateway code? I am smashing my head against a wall tbh
it won't get merged either way, sorry
you'd be much better off just making it an external app
then you can use a library dedicated for connecting to user accounts, like arikawa or discord.py-self and just send desktop notifications
which are designed to be safe for your account
Just want to get it to be safer :>
oh oki
just wanted to let u know so u dont put in extra effort just for it to not get merged anyway
consider this tho!!
u can use one of these to connect to ur other accounts, listen to messages and then show desktop notifications whenever u receive a ping or dm. much much lighter than doing it inside discord and also safer cause these libraries are well crafted (well idk anything about the last one but it seems very popular so its probably decent quality)
https://github.com/diamondburned/arikawa
https://github.com/dolfies/discord.py-self
https://github.com/aiko-chan-ai/discord.js-selfbot-v13
lmaooo i checked the last person's projects out of curiosity and got jumpscared by this 😭
most well adjusted vencord user
actually its a bot client so maybe their bot just got added to that by the person who owns that server
still tho the fact it exists
i finaly got the funny
badge :3
im trying to include the emoji picker in a modal, but the webpack module its in exports nothing else, so i have no idea how to get access to it (since the only way i know how to do that is findByPropsLazy and that doesn't work when there's only one export. anyone know how i might be able to do that?
ah, ty
am i potentially misunderstanding how this function works? it cant find the module even when chrome devtools can.
it only finds exported members
if ur func isnt exported u cant find it
check what it exports
it.. doesn't seem to export anything in the source code, but i know it does since other modules import it. like it doesn't have one of these blocks of exported functions
it has to set default somewhere
seems to set it to a react thingy, can i search in that?
yes
i see
findComponentByCode
also if u scroll up a bit more there's an id
2345: (m, e, n) => {
that number is the module id
yea but doesnt that change when discord updates?
you can run wreq(2345) in console to import it (enable console shortcuts plugin)
ah okey
yeah! but it allows you to easily import it from the console to see what it exports
yeah i was trying to do that lol
ty for telling me how
ah it works, ty for the help
I need to access a really specific webpack module ( 277390 providing QRCodeWithOverlay )
I know it's used in the family center and login page
What's the best way to load it?
it's lazy loaded?
Yop
extractAndLoadChunk
i explained it to alyxia a few days ago how to use it
go looking for it
alright
am i going insane or does MESSAGE_REACTION_ADD trigger on poll votes?

me when emoji '2'
i thought theres a separate event
i love discord
and the weird thing is i cant reproduce it half of the time
does that mean aliu reaction plugin detects poll votes
lmaoo
(it doesnt womp womp)
polls are based on reactions
makes sense now why post plugins check for type
most*
probably
idk

nevermind brainfart
Hello, I'm trying to write a small plugin to hide blocked users from the user list.
I looked at noBlockedMessages, which removes blocked users' messages from the chat by patching Messages.BLOCKED_MESSAGES_HIDE
However I'm not sure what I should be patching. I tried UserList, Userlist, Users. But I am in the dark. Is there a list of these somewhere? "Messages" exists. What else exists?
Also: Maybe it's not possible to achieve through "patches", so if anyone knows any other plugin that modifies the user list, I can just look at that and probably get my answer.
MoreUserTags or PlatformIndicators maybe, though those just modify user entries rather than removing them
look into RoleColorEverywhere, it modify the member list sections color, module number 335615, and I believe renderRow is responsable for rendering the members on those sections
Thanks folks, I will look into these three plugins and see what I can hack together. This is great.
(P.S why does blocking someone on Discord not hide them everywhere, anyway?)
I'm still curious about what "Messages" is, and what other things can be patched directly using the same direct, simple method https://github.com/Vendicated/Vencord/blob/main/src/plugins/noBlockedMessages/index.ts#L32
index.ts: Line 32
find: "Messages.BLOCKED_MESSAGES_HIDE",
looking at the code for export interface Patch I see it mention "module" being patched. So it seems like Messages is a module. And I am still wondering if there is a list of all possible such modules
modules are separate code files, that contain reuse code across different parts of discord
allow developers to break down complex code into smaller, manageable pieces. Each module typically contains related functions, classes, or components
my brain capacity has reached its end.. 
Thanks
Where is this screenshot from? I tried searching the Vencord repo but I didn't find it.
you seem to be right about renderRow
this screenshot from the devtools, the module I mentioned above, search in devtools for tutorialId:"whos-online and you would find it
a protip: press { } to make code prettier and easier to read
||this is not from the vencord codebase, its discord code||
search for that in the "components" tab of the developer tools?
search in the sources in all files
you would find random js file name
oh thank you, I didn't see that option
yes now I can search for it and find the js I can reverse engineer probably
Presumably not everything can be patched in this way? This might be a fool's errand. Is there any way to know?
so it's just about finding the right one?
e.g. when I try to find: "renderRow" and click "Test Patch" in VS Code, I get 41 matches. Is it about narrowing that down to 1?
thank you, this might be exactly the primer I needed
The VS Code extension doesn't show the "Test Patch" shortcut when a regex is used, only for a string.
Is that just a limitation of the VS Code extension?
oh it doesnt support regex finds cause theyre very new
extension hasnt been updated
anyway dont use regex find
you dont need it in 99% of cases
OK I figured it'd be something like that.
OK I will try without
If I search for the string renderRow:e=>{let t then I can narrow it down to 1. But t might change, presumably. In future.
why not search something before renderRow
then match something in renderRow after
it doesn't need to be exactly renderRow
OK that's worth a try. If the VS Code extension says my plugin matches multiple "find"s does that mean the plugin will patch all of them? Or does it mean the plugin won't work?
I think I want to start by finding all of the renderRow definitions and replacing them with a function that returns immediately but does nothing
it's defined separately 8 times.
it will match one of them but that not recommended, it may match something other then what you want to match for
no.. you will break discord 
find something that could be unique
of course I will! I just want to see something
hey I saw something
and learned a great deal, now my head is spinning
there are many rows in discord
you only need to patch the one in question
I know, rn I'm trying to:
- Prove I can actually patch something by finding and replacing text (DONE)
- Find the correct renderRow that is called when viewing members in the channel list
- Find a string that lets me match that, and nothing else
- Do the needful
Hey I found it
I mean I'd rather the row was not an empty space but this is progress
maybe renderRow is the wrong thing after all. I will look again tomorrow
maybe
try to instead filter the data before it's fed into the component
Where is this? I can't seem to find it
Currently I've just been vaguely looking at the few uses in Vencord
Calling extractAndLoadChunks(["QRCodeWithOverlay"]) will just return Couldn't find chunk loading in module factory code
^
you can try this
horror dont psoonfeed
find the module which you want to import from
oh
go up all the file til the .push statement
first argument (or second I dont remember) should be a number (as string), that's the chunk id
then search that id in the console and you will likely find where it's loaded
Oh okay
I already found that
in my case it's Promise.all([n.e("49237"), n.e("99387"), n.e("49368"), n.e("90688")]).then(n.bind(n, "978305"));
yep that's what you need
now you need a find for extractAndLoadChunks to find the module that has that
(thinking now it should support regex too but it's okay probably since I think the first argument is an array)
Find being any unique string in there?
The code for it is ```js
568671: function(e, t, n) {
"use strict";
n.r(t),
n.d(t, {
default: function() {
return c
}
});
var a = n("735250");
n("470079");
var s = n("481060")
, l = n("626135")
, i = n("503899")
, r = n("292352")
, o = n("981631")
, u = n("689938")
, d = n("277886");
function c() {
return (0,
a.jsxs)(s.Button, {
innerClassName: d.qrCodeButtonContent,
size: s.Button.Sizes.LARGE,
onClick: ()=>{
(0,
s.openModalLazy)(async()=>{
let {default: e} = await Promise.all([n.e("49237"), n.e("99387"), n.e("49368"), n.e("90688")]).then(n.bind(n, "978305"));
return t=>(0,
a.jsx)(e, {
...t
})
}
),
l.default.track(o.AnalyticEvents.FAMILY_CENTER_ACTION, {
action: r.FamilyCenterAction.ShowQRCodeModal
})
}
,
children: [(0,
a.jsx)(i.default, {}), u.default.Messages.FAMILY_CENTER_REQUESTS_LINKING_BANNER_TEEN_BUTTON]
})
}
},
I GOT IT
I think
ok time to get 429 too many requests on /users/@me/invites endpoint
okay I kinda have some hacky mess working
now I wanna unfuck my other hacky mess
This is very awful.
if you need to use outside the plugin object no
oh also
i am curious
did discord bomb friend finder endpoint

In case anyone was wondering what I'm building, it's a UI for the friend invites plugin
or do you need to opt in from the mobile app to enable contacts to add me
ask the alien friend
i already checked @clear parcel site for it
no docs for it
only specifies the code field in createFriendInvite

yes i literally posted about that 8 minutes ago
it's been that way for months

@gritty sparrow can you explain how that code even worked in the first place and what all those fields mean
I see a lot of 1 but I do not know what I need to tweak to get a custom max uses value to be registered or even if it's possible anymore
i wouldnt be surprised if discord bombed it
WE
NO DOCUMENTATION

WE
DEPRECIATED FEATURES
ya iirc that first ep is gone for good
ignore all the fields, use the ep in the else block
most likely
guh
I can maybe check it out
?remind 23h
:remind 23h
!remind 23h
;remind 23h
vencore got no good bots

someone ping me in 23h thx
there's pissbot
add rdanny
ve setTimeout(() => channel.createMessage({ content: "pookie @eager abyss", allowedMentions: { users: ["1026534353167208489"]}}), 23 * HOURS_IN_MS)
Timeout {
_idleTimeout: 82800000,
_idlePrev: [TimersList],
_idleNext: [TimersList],
_idleStart: 15515073,
_onTimeout: [Function (anonymous)],
_timerArgs: undefined,
_repeat: null,
_destroyed: false,
[Symbol(refed)]: true,
[Symbol(kHasPrimitive)]: false,
[Symbol(asyncId)]: 652982,
[Symbol(triggerId)]: 0
}```
real
😨
the hell did i copy
role id?

right click on role in member popout
you should be glad there is @ and @&

else you would've just pinged 200 people
Alright @dull magnet, in 17 years: what's good boomer
gonna be almost 40 then wtf
is there a specific way to make this menu or do i have to find it myself
(ping reply please)
i found the module but idk how to get it in code, this doesnt find anything
const PickerTab = findComponentByCode(".AnalyticEvents.EXPRESSION_PICKER_TAB_CLICKED");
Alright @clear parcel, in 18 hours: …
TIL you can resize the gif picker
yea, I didn't knew that till I made the cookieClicker
hey y'all, would it be bad to edit utils.ts in a plugin pull request? i had to access the module to add reactions to messages and i feel it might be useful to other plugins but idk what i should do and i feel like asking is probably my best course of action
stealing your api rn
not again
were u gonna make a plugin to resize it
then realized u can resize horizontally without plugin
woa
too bad the gif picker is slow now that they added ?params and caching is broken
for this plugin, would DataStore or settings be better to store the user's media (in links)? I want it to sync across clients but DataStore doesnt do that
@clear parcel, <t:1716351559:R>: …
@clear parcel, <t:1716416380:R>: …
fiiine
pookie @eager abyss
lmaooo
@clear parcel

(build does no type checking)
does anyone know what this object does (it is required to use expression picker functions like opening it)
this is the module that generated it
how would i even find this module
that module is def not what u need lol
const { ChatInputTypes } = findByPropsLazy("ChatInputTypes")
its just config for the slate input
customises behaviour depending on which context youre in
thank you
I did check this out btw
friend finder appears neutered and there's no other way to make the 1 use invs
idk why they didn't expose max_ params on the ep
yeah sure, but make sure to take the one from the TablistApi branch as the one in the fun branch is not maintained anymore (there isn't many changes externally other then the names of functions/components)
i have these two finds that don't work on the top level, but they do work when the find is executed in start. should i just leave them in start or is there something im doing wrong?
oh i thought the bottom one was broken too but yeah that works
how does that work though, just removing a property access causes it to work?
ah got it
you can only access exports
but the reason the first property access work is because we make those lazy too, in case you do what you are doing there
bump
i want vertical resize
discord so stupid for not adding
I used to use BetterDiscord and there was a plugin that added some features to images, one of the features was displaying the file name and size below images. Is there a plugin that already does that? I'm considering making it if there isn't.
There already is a plugin request for that and from my knowing it is also being developed by someone already
for MessageLatency, i wonder if it would be worth implementing edge cases like "this message seems to have a delay of 5 minutes, but they replied to a message newer than that, so the actual potential delay is lower than that and their clock is probably just off"
is there any point in developing complex algorithms just to tell you that some random user's clock is 2 min wrong?
i wouldn't really call it a "complex algorithm", it's a simple comparison
but tbh, it is probably unnecessary, and instead the general message could be changed to something like "This message was sent with a delay of X (or their clock is off)."
I’ve sent a message and then it says that my clock is 2 seconds behind
I heard from the grapevine that using APIs you host yourself isnt going to get merged into the main repo... Is there a way to get the server "officially hosted" so that I can have my plugin merged?

i'm currently developing a new plugin and am trying to put a select dropdown next to the display name input field in the profile settings tab
i've tried a similar approach to the 3y3 button
addStyleSelector: ErrorBoundary.wrap(function ({ pendingGlobalName }: { pendingGlobalName: string; }) {
return <Select
placeholder="default"
options={styleOptions}
select={(font: string) => stylizeName(pendingGlobalName, font)}
isSelected={function (value: any): boolean {
throw new Error("Function not implemented.");
}}
serialize={function (value: any): string {
throw new Error("Function not implemented.");
}}>
Style your Display Name
</Select>;
}, { noop: true }),
but my patch errors (unexpected token '.'),,, i am certain i've found the right place to patch in
{
find: ".DISPLAY_NAME_MAX_LENGTH",
replacement: {
match: /(\i)\.currentGlobalName\)&&void\s*0!==(\i)\?(\i):""}\)/,
replace: "$&,$self.styleSelector($1.pendingGlobalName)"
}
}
i feel kinda stuck, are there any obvious mistakes here i haven't caught on to?
edit: the patch is supposed to append my component after the TextInput field where Display Name is changed
when you realize you renamed a function but forgot to update it elsewhere 
What's the best way to get the file type of a file? I don't want to just check the extension and making a request would require a native.ts for cors and that seems really unnecessary
export async function getMediaType(src: string): Promise<MediaType> {
return await fetch(src, {
method: "HEAD",
mode: "no-cors"
}).then(res => {
const type = res.headers.get("Content-Type");
if (type?.startsWith("image")) return "image";
if (type?.startsWith("video")) return "video";
if (type?.startsWith("audio")) return "audio";
return "image";
});
}
what if you split by /?
res.headers.get("Content-Type")?.split("/")[0]
I don't see cases where this could go wrong other being undefined
No adding no-cors makes the response opaque so there is no headers
what's this for
So I can choose what component to render based on what file type it is
got it working with a native.ts but i feel like its a bit unnecessary, is there a different solution?
describe the full use case
different component based on file type? wha?
how is that useful if you can't fetch the file anyway
isn't attachment go through a checking thing? to check to whatever its an image or video or text based file? have you tried to debug or check the possible entries
and are we talking about someone sending a url and check what's the file type in that or just some regular discord attachments?
im making a place to store media in discord, like the favorite gifs but with any media. i want to display the media, and i need to know what kind of media it is to know how to render it, like a video, image, or audio. for some reason, making a fetch request for it requires you to go through cors but putting it in a video or image tag does not.
ah, have you thought of storing the type with the src?
to avoid fetching?
that's what im going to do but i still need to get the type somehow
i might be able to get it from the message itself
could be the best option
where's that?
ah the message
if only I wasn't in incognito mode
I don't know how to say this in a kind way but I can almost certainly say that your plugin will not be merged (It blatantly breaks rule 12 of this server itself)
How can i make an input field component that's styled like a discord codeblock?
There might be a plugin that has already done this but i can't think of one off the top of my head
Not sure how exactly to do it but I did a hacky workaround one time to set the font with CSS
wouldn't you want it to be a textarea?
Probably
I'm not sure how to get it to look right though
idk, not on a computer rn to check, probably just a matter of applying the appropriate class(es)
i want to make a vencord plugin, where can i start? im lost because there arent any documentations anywhere and the plugin-template is archived lol
documentation is kind of scattered, its mostly just source reading and seeing what other plugins do
there is a couple of things at https://github.com/Vendicated/Vencord/tree/main/docs but they are most likely quite out of date now
though it should be relevant enough
plugin-template is from an experimental plugin loader that never got implemented into vencord, so dont worry about it
the only supported plugin type is the one thats built in
oh yes
the vscode extension is a helper that lets you test patches from vscode itself to make sure they're valid
its quite handy
does anyone know why when i try to create an iframe it responds with "Refused to frame because it violates the following Content Security Policy directive"
it does this with any url in discord, but it allows me to create the iframe on a different site which means it isnt the url problem
Just a wild guess: because of the content security policy 

yeah
read the error 
theres probably some way to bypass it
iirc vencord already has to somehow
yeah
read src/main/main.ts
alright
it looks like it already removes the content security policy over the app?
ohh okay, so would i just modify that code or do something simular in my plugin code
what is this iframe you are trying to load anyway?
just a document embed
add frame-src to the automatic directive injection thing
thank you, it worked
I'm having a weird issue, i'm trying to hyperlink to another site in a plugins about component but it throws an error when pressed

(vesktop and plasma x11 if it matters)
I will just
import { Link } from "@components/Link";
<Link href="https://example.com">here</Link>

How do i get the users favourite gifs? i tried looking at the stores but nothing useful seemingly (also can't think of any other plugins that go this)
UserSettingsActionCreators.FrecencyUserSettingsActionCreators.getCurrentValue()
should be that
What the fuck
Why are you actually making GifRoulette
Insane
BECAUSE IT'S A GOOD IDEA FUCK YOU
yop
how tf am i supposed to match this
match something else in the module probably
ok that worked
my plugin is fixed
try the following:
MemberListBanner: ErrorBoundary.wrap(({ user }: { user: User }) => {
...
}, { noop: true })
then call it like $self.MemberListBanner({ user: ... })
got this far, now need to go through the queue
oh do you not yet?
you can just use the queue util in vencord
it makes it super easy to do promises sequentially
import { Queue } from "@util/Queue";
const queue = new Queue();
queue.push(() => doStuff());
queue.push(() => doOtherStuff());
oh shit ty
how do i tell userProfileStore to fetch the profile
getUserProfile returns whats in the store
oh thats in util
its infinitely fetching profiles down the list, its not restricting itself to just viewport?
oh wait it stops like 200px down
okay
stores are stateful. they allow you to register change listeners
useStateFromStores subscribes to store changes
i got it
if you read the fetchProfile() function code you will see that it dispatches flux events USER_PROFILE_FETCH_SUCCESS, GUILD_MEMBER_PROFILE_UPDATE, etc
the profile store is subbed to these events
so whenever that event is dispatched, the store will handle the event, then the store will call its own change listeners
whcih will in turn trigger your state to be updated
so all you need to do is
- sub to the store via
useStateFromStores - fetch the profile if necessary
yeah it works
discord's store + event system is really awesome
super cozy
you can even make your own stateful store and sub to it using the same apis
https://github.com/Vendicated/Vencord/blob/main/src/plugins/spotifyControls/SpotifyStore.ts
https://github.com/Vendicated/Vencord/blob/main/src/plugins/memberCount/OnlineMemberCountStore.ts
oooooo
@dull magnet btw, super random, but I looked more into message updater api in the past, I was able to manually dispatch store updates
however, messages are also memoed
so they were not getting updated because of that
I'm trying to make a plugin that when running a slash command it will send an embed of a random photo from my GET api, although when I run the command it just displays the link instead of the photo. I have no clue how to fix it and neither did my friend.
{
name: "raccoon",
description: "Gets a random raccoon image.",
inputType: ApplicationCommandInputType.BUILT_IN,
execute: async (_, ctx) => {
const data = await fetch("https://api.racc.lol/v1/raccoon?json=true")
.then(response => response.json())
.catch(err => {
console.log(err);
sendBotMessage(ctx.channel.id, { content: "There was an error. Check the console for more info" });
return null;
});
if (!data) return;
let imageUrl = data.data.url;
imageUrl.replace("http", "https");
sendBotMessage(ctx.channel.id, {
embeds: [
{
type: "rich",
title: "Random Raccoon",
color: 0x8663BE,
description: `${imageUrl}`,
image: { url: imageUrl },
footer: {
text: "using racc.lol",
},
}
] as any
});
}
}
]```
Check the network tab to see why the request is failing cause that’s most likely why it won’t show up
omg hahaha @amber basin
in the future just use this button lmaooo
oh
I'm getting a 200, {"success":true,"data":{"url":"http://api.racc.lol/v1/raccoon/104","index":104,"width":564,"height":423,"alt":"a raccoon"}}
i just do this with gitlens
vee checking their income
straight away: that plugin won't be merged
you're better off making a user installable app
🔥
selfapp (like pinging mantikafasi)
doesnt require a client mod and is way more useful
user installable apps are really cool
Tried making a plugin and got shit on lmao
wdym shit on 😟
im not meaning to shit on u, just saying that your idea is better off as a regular bot
cause u can do this and it'll work even on mobile and anyone can install ur bot and use its commands globally on discord
User apps aren't out yet iirc
Is there docs? Or do they just work like bots
its just normal slash commands
Well that answered my question
i will implement this eventually
for some random plugin i make
anyone have any idea why this wouldn't work?
function at the bottom just doesn't properly update the status (it just duplicates it for some reason but also doesn't show for anyone other than myself)
Hey uh, Vee told me to replace tsx { find: "Messages.ROLE_ICON_ALT_TEXT", replacement: { match: /function\s+\w+?\(\w+?\)\s*{let\s+\w+?,\s*{className:.+}\)}/, replace: "$self.RoleIconComponent=$&;$&", } }
with findComponentByCode. Could anybody give me some pointers on how that works?
nvm, figured it out lol
looked more complicated than it was
Is there no enum application command option type? i think i might be blind
wdym, is there more types other then those?
I'm not sure
I wouldn't be surprised if there is
get rotated
looking great, and aw cute cats you got there.
one question does the search work?
I have an example of how I got the search thing to update
lemme send it
i plan on allowing you to add a description to your media and making the search use that or the url if there isnt one
and it will also use fuzzy search
@jagged briar here, this may be useful
wreq(parseInt(findModuleId("useExpressionPickerStore:") || "0")); 
(too dumb))






