#🧩-plugin-development
1 messages · Page 83 of 1
I do set it?
just create a new array when you change it
instead of push, use [...arr, newElement]
same thing you would do with react state
I dont push anywhere
if it's not reactive ur missing something
but instead of pushing make the set -> then turn into array again and settings.store.ids = newArrayFromSet
oh yeah turns out checking if the quest is ignored by passing the quest name when you're checking for ids tends to fail
yeah im reading it as is, making it a set, doing validation, casting back to array, then setting it. seems to be working

Something like this will never be perfect because people don't generally chat exclusively in replies but it comes in handy every now and then
Should do
Seems like it doesn't necessarily load users though, I should look into that
Well, members
You need to run ```js
GuildMemberRequesterStore.requestMember(guildId, id)
for every user
Nice, thanks
pretty fire
spent too long playing around with trying to dynamically group different plugin context menu items cause the context menu is kind of a mess 😭
works though 
joinOrCreateGuildContextGroup(
children,
downloadifyItems,
"guild-content-group",
"download-guild-context",
"Download",
[{ id: { child: "devmode-copy-id" }, type: "BEFORE_GROUP" }]
);
joinOrCreateGuildContextGroup(
children,
[viewRawItem],
"guild-content-group",
"view-guild-context",
"View",
[{ id: { child: "devmode-copy-id" }, type: "BEFORE_GROUP" }]
);
Does anyone know if a plugin akin to discrub is available for vencord?
Would be nice if similar functionality existed on-client
that sounds like api abuse so no
Would they not ratelimit it then?
It works fine as a tool
has for a long time
Perhaps but Vencord is already breaking TOS by existing so they don't take chances on making Discord break their "we'll pretend that's not happening" streak by allowing automation involving the API. That's the invisible line in the sand afaik.
how did you make use of GuildMemberRequesterStore? it doesnt seem to return anything for me. or change the data my client has cached.
specifically my client isnt loading guild specific profile data (per-guild banner, etc) in the profile modal until I click through to the bigger "view full bio" modal. then any time I check that specific profile it will show the guild specific data. so like discord is just failing to do an api call to the profile endpoint. 🤔 if I can't do this with a store imma need to use the rest api I guess.
I literally just called this function before displaying the components and it just worked, I assume message components subscribe to the store and are reactive to when it retrieves members
damn
just realized I cant even rely on an api call cause I wouldnt know if the user was supposed to have a guild banner or not so it would be a blind api call and I'd need some way to only call it once. agony. why cant discord just return a full user object 😔
was able to fix it with a patch. pass the guildId along properly.
thats enough of that for today 
it is but I don't really like the requirement of it needing its own repo
will think about it
where do you even develop it
do u just push to your vencord fork
github wouldnt let me fork a fork cause I already had the upstream forked so this was my solution
k ticket made. will see if accepted when I wake up 
clean :)
you made this .??
working on it yeah
@quick zephyr i got an idea about plugins maybe you can help me ?
$1,000 PayPal
there goes my job opportunity smh
v+ no prog
#1404220527387742278 you made a mistake giving the role to the person that made at least 4 typos in 3 messages in the first place
i wouldn't have 
true
yeah that modmail should have been an instant rejection

anyone who knows how to code would also know proper English
how do i reject that tho 😭
"uhh you do not know how to speak the english language therefore you may not write vencord plugins thank you next"
maybe just don',t give the progra,mming role out straight away then just closing the modmail lol
no questions asked type shit
esp because they didn't ask for dev channel access they just asked how to make plugins
@hushed loom we will do that
Hellooo 
First time working with webpack injection and I was wondering how exactly I can find the code for a React element in order to patch it. For instance, I want to add a div right under "Member since" (I'm using React Dev Tools - do I need other tools as well?
)
I've been trying everything but been stuck for 2 days 
also ty ven for access :D
click "view component source in devtools"
There's some helpful messages in pins
been trying to make a simple plugin for an inside joke that replaces all instances of the word "blue" in messages to "crust" (don't ask, again it's an inside joke) in both read and sent messages, and i'm focusing on the other messages first because i know i can lean from the plugin that strips canary and ptb links for the sent one
it feels like i have to use the flux functions but i cannot find documentation for it anywhere and the only thing i can find in the vencord code is a list of strings of the functions but not their arguments or anything
You'll have to find the event arguments yourself
Just run ```js
FluxDispatcher.subscribe("SOME_EVENT", console.log)
and see what data it is receiving
enable experiments plugin then use discord's own devtools (not the chrome devtools), it has a page that shows all flux events that happen in the app
followed sunnniee's guide as a training but instead of finding an array it's just
t
tried looking everywhere for t but no hope 
tried other components, it's all just t
t is passed down from the props (e), so try checking the parent component
Also the variable names are generally random
Also if you just want to add something after the original children, you can do [t, <YourComponent/>]
React will figure it out

actually, looking into this i might need to just use patches augh
how exactly does the patches stuff work? i know i probably have to patch handleLoadMessagesSuccess but i'm not sure what the difference between find and match are in patches
and what is \i in the regex i don't remember that being a normal regex escape character
this explains it really well
thank you so much! never found this somehow, will have a look
patch went so well can't even open someone's profile no more

LES GOOOO
now using variable names but hopefully it's not that bad 
did you get these showing in the small profile again?
wait did they remove it from there??
can you not see it at all now?
by these I meant the member since
I'm specifically talking about the "uwu" under it
oh
I thought that was just the about me
injection so good it was added to everything
You can use \i to match mangled names, so if you capture children:(\i) in the regex it will allow you to reuse that name in the replacement with $1
(or a function can be used)

{
find: "header-secondary\"}=",
replacement: {
match: /(\(0,\i.\i\)\(\i.\i,{children:)(\i)/,
replace: "$1[$2,$self.renderSilly()]"
}
}
example without assuming variable names
tysm
Hi, can anyone help me with "Error while starting UserDevCompanion"
to use that fork you need the forked Vencord plugin by the same author
silly question, but isn't $1?.startsWith('members') always true? since that's where the child is trying to get added to, just one div
(MemberCount plugin)
a wait why also there 
how did it get form the members wrap all the way to the channels wrap
does it mean the same function gets used in creation of both containers?
the only solution I see when actually making it is failing at first and then making the replacement even more specific
yes

Open console lol
User dev companion is the plugin on the vencord side
Yes
quick question before I start wasting multiple days searching:>
I'm trying to find the function that spawns discord's native picture in picture and for that I thought checking all components of a channel (since it only appears when clicking on a channel for the first time while already watching someone's stream)
but is this even the appropriate approach? since there are so many hooks it might take more than 10 hours (willing to do) and still not sure if what I'm doing is right 
iirc it's done with a store
@eternal sparrow check out the module that this patches (ignore the patch itself)
ty
I was just scrolling this chat and have some questions lol xd
I just picked a random old reply chain to test on lol
Hiiiiii !!!! I'm trying to make my very first Vencord custom plugin and since I'm a complete beginner I'd need some advice ^^
In particular, I would like to know if there is a hook for received messages because I'd like my plugin to react to the content of received messages
Would you help me ? 🥺
MESSAGE_CREATE flux event or smth, look at other plugins
Hmmmm these ?
noBlockedMessages\index.ts:73: match: /(?<=function (\i)\((\i)\){)(?=.*MESSAGE_CREATE:\1)/,
xsOverlay\index.tsx:203: MESSAGE_CREATE({ message, optimistic }: { message: Message; optimistic: boolean; }) {
second one
first one is a patch
Hi, guys. I finally have access to this channel. So, I got my plugin to work. @silk sorrel @stone wedge @ everyone
But I believe I can benefit from the scrutinizing eyes of an expert.
Do I go ahead and share a pastebin link to the code? It's about 300 lines long.
make a git repo
Do you mean I should submit the plugin as per dev instructions?
you can do pastebin for now ig
least vibecoded plugin
AI slop and blatantly against server rules
what’s the link
Yes, I was assisted by AI. Anything inherently wrong with that?
v- prog
it's against the rules for this channel
ai can't write vencord plugins
v+ no prog
it doesn't have the knowlage required
@clear parcel implicitRelationships sends an invalid gw payload and doesn't actually load any users
idk if the structure changed at some point, but userIds should be a raw user ids array (toRequest.map((u) => u.otherUserId))
sadan is my top implicit friend 
def changed lol
Hello there, I noticed that the openInApp plugin does not (or at least not like I would expect) support spotify jam invites. So I edited the getRedirect method of the native.ts from the openInApp plugin to make it work (somehow). Anyone mind to give their opinion on the code?
Hey, how can I find the correct parts for "find" when writing a patch? My goal was to add an option to the popout that comes up when you press the plus circle on the left side of the chat box (where you can select attachments etc).
Like such
You can inject into that menu without using (your own) patches at all
vp VoiceMessages
Allows you to send voice messages like on mobile. To do so, right click the upload button and click Send Voice Message
V, Vap0r1ze, Nickyux
see how this plugin does it
I will, thanks a lot!
any way to mark a plugin as desktop only without naming the folder plugin.desktop
why is renaming the folder not an option
I just didnt want to have to name the github repo like that
ugly
contextMenus: IS_DISCORD_DESKTOP ? {
...
} : {},
patches: IS_DISCORD_DESKTOP ? [
...
] : [],
thoughts 🫴
side note, electron functions like showOpenDialog should work fine in vesktop right? it's based on electron too 🤔
when the hidden
huh
man I tried looking in the definePlugin and didnt see that option 😭
yeah im blind. thanks
still curious about this if anyone knows
if you’re working in native.ts yes
yeah I am
ok guess I'll be using hidden: IS_EXTENSION || IS_USERSCRIPT,
btw what is IS_WEB I could find literally nothing that explained what all it applies to
is it just a shortcut for IS_EXTENSION || IS_USERSCRIPT or does it have some separate meaning
is_web is extension userscript vendroid legcord basically anywhere without a native.ts I velieve
IS_WEB = running in a web browser (not electron) => no natives available
who cares 😭
just make a github organisation
oh so I actually want IS_WEB
🙋
just let us make single repos containing multiple plugins :)
no
sad
you can technically but you can't post it in #1256395889354997771
Can you create a standalone installer yourself with the userplugins?
Just to make it easy to share a userplugin with a non-technical friend without them having to do all the pnpm setup etc?
its the way it is intentionally
Ah I see ok thanks
yes
huh
we don't want people to use userplugins easily because it just makes it way more accessible to shoot yourself in the foot by giving yourself malware or break your discord
and then people will complain to us about it and we don't want that
but you could fork vencord or whatever if you wanted but you would have to maintain it
you need to publish your builds to a github repo the same way vencord does, then change these variables https://github.com/Vencord/Installer/blob/main/constants.go#L14-L19
constants.go: Lines 14-19
const ReleaseUrl = "https://api.github.com/repos/Vendicated/Vencord/releases/latest"
const ReleaseUrlFallback = "https://vencord.dev/releases/vencord"
const InstallerReleaseUrl = "https://api.github.com/repos/Vencord/Installer/releases/latest"
const InstallerReleaseUrlFallback = "https://vencord.dev/releases/installer"
var UserAgent = "VencordInstaller/" + buildinfo.InstallerGitHash + " (https://github.com/Vencord/Installer)"
Alright I will look into that, thank you :)
Don't need ven to allow it, just do it
But can you git clone it like that?
no point if I can't #1256395889354997771 it
#👾-core-development message
All that weirdness is what this function is for
To make the url people actually send match to what the unfurler returns, so if I'm going to be cataloguing that anyway, I may as well use the same logic to link batched embed requests back to the url
If it fails it fails
Who knows, maybe there are extra params I can send and get nonces or ids back or something
whaaaat
how do you install a single one
Heck if I know
didn't you make it
Yeah and I use all of them
does this just delete folders that you don't want?
I don't really completely understand it
So it's just a plugin called vencordplugins that loads other plugins?
You can't actually just clone one folder of it?
That's a git question, not a my repo question
You can copypaste or symlink individual folders just fine
I was looking into expressionCloner and wondering when itemHref is even used
I've tried a bunch of scenarios including with/without fakenitro and itemHref always returns undefined
taking side quests since picture in picture defeated me 
wait I found out
makes sense with that name
but wait in this scenario favoriteableType is null
so itemHref is never actually used 
I'm genuinely confused about what scenario has favoriteableType and also itemHref
Discord might have just changed it since that was written
XY
you can detect most things if you try hard enough
what are you trying to detect
sadan detector
also is there a reason why StickerExt[data.format_type] could be first undefined and then png 2 times? Is Discord's API acoustic?
also I saw emojis use cdn.discordapp.com/emojis/
while stickers use media.discordapp.net/stickers/
tho afaik both endpoints work for emojis and stickers, so why not use window.GLOBAL_ENV.CDN_HOST for both? 
is there a difference between the responses perhaps?
png and apng
For emojis I'm pretty sure both domains work the same but for stickers they do not.
TLDR gif stickers are only available on the media proxy and lottie stickers are only available on the cdn

because cdn is insane and doesnt serve gif stickers
discord moment
so ig in this scenario window.GLOBAL_ENV.MEDIA_PROXY_ENDPOINT works for both since lottie stickers are ignored anyway
the var isnt available by the time the plugin loads so if you're trying to set it to a global plugin variable it will error. but if you're using it inline it should work
I think I read the explanation for this was something something cloudflare
in most scenarios I'd recommend the media proxy over cdn just cause it has more options available to it. you just gotta know when to use the cdn instead for the rare few cases the media proxy isnt an option. which are not documented :D
well so far the only things not available on media proxy afaik are default avatars (primary domain), unicode emoji svgs (primary domain), lottie stickers (CDN), and nameplates (CDN).
havent come across anything else
on the topic of embed that recently come, i'm trying to solve my own issues with them, since some of you have knowledge maybe you know smth
discord isn't embedding my website, i'd be interested to know why
i first checked the client i case it was smth there, but no, so i did go up and weirdly the discord dev embed debugger seems to strip the thumbnail URL, but iframely's debugger show me that it's valid, i tried changing the size, serving the image myself, but nothing does it
i already work around discord not fully supporting the omebed spec by specially for discord serving HTML since it doesn't care about the HTTP Link header so i wonder if there's smth else i have to do
-# screenshot of curl so you can quickly see what i'm serving discord
Discord uses https://ogp.me/ for titles, description, etc and https://developer.x.com/en/docs/x-for-websites/cards/overview/markup for images.
Can find examples on stackoverflow and reddit.
they actually support more than that
just copy paste the markup from a site that has it working 
and how is this plugin dev
eeeeh
i didn't find a better place, ig probably should have been #🪅-progaming
thing is
i did that
like i've looked at other issues
send the site here
i tried so much
mine ?
ye
is it completely not embedding your site or partially failing
nah it seems to be stripping stuff
such as
if it was stripping the html from rich, i would understand
but stripping the thumbnail URL is weird
especially when it's their own domain
also make sure to spoof your UA to Discord like i did here so you get the same answer
why are you doing that 😭
it's returning it as link header
except for discord where i return it as HTML too because it doesn't seem to support the full oembec spec
no as I said it only supports twitter card for images
one is discordbot the other is a normal browser user agent
because i assume that people are properly implementing the spec
they all have Discord in them, i checked my log
💀 why do they say they support it then if they don't bother implementing the spec
they dont. if you google it you'll notice nowhere do they list the tags they support
closest you'll get is https://x.com/discord/status/952834253842153472
@sandia_mesa_mlh @WordPress Heya! Our website uses metadata from the Open Graph Protocol to form embeds. If you can manually edit your website's metadata, you should be able to exclude the author! You can check it out here: https://t.co/GpcAoCaH7E
well yes but no
i can't
location /blog {
add_header link "<https://$host/oembed$uri.json>; rel=\"alternate\"; type=\"application/json+oembed\"";
if ($http_user_agent ~* "Discord") {
more_set_headers "content-type: text/html";
return 200 "<html><head><link rel=\"alternate\" type=\"application/json+oembed\" href=\"https://$host/oembed$uri.json\"/></head></html>";
}
return 302 https://youtu.be/dQw4w9WgXcQ;
}
this by example is only doable because websites who fully implement oembed support link header it allow me to have my own embed, but redirect the user
oh checked my site and I use og:image too actually. but you also need <meta name="twitter:card" content="summary_large_image"> to tell it to make it a big image
what
why are you conditionally returning html
location / {
add_header link "<https://$host/oembed$uri.json>; rel=\"alternate\"; type=\"application/json+oembed\"";
if ($http_user_agent ~* "Discord") {
more_set_headers "content-type: text/html";
return 200 "<html><head><link rel=\"alternate\" type=\"application/json+oembed\" href=\"https://$host/oembed$uri.json\" /></head></html>";
}
try_files $uri $uri/ =404;
}
same here, i just can't remove the UA check, because i need the embed to actually be a link header if i want the content to be served
the idea is that my whole stick is built as a fully static thing
and the served file does not need to be modified for it to have an embed
which allow myself to do smth very powerful
ANY file that i serve can have an embed
im so lost why cant you just put metadata in your <head> block
because the file that's served could be an exe
and an exe has no head block
but it can have an HTTP Link header
why do you need an embed for an exe
because the idea is that i'll be able to serve application artifacts and have metadata be shown in embed
lemme create you an example
i can do this by example
dummy is not a text file and yet it can have an embed
hence the use of the link header
and the goal of this is to just share a file with someone?
it actually is a text file but ignore that
the goal is that i'm moving shit to gitea/forgejo, my artifacts will be served by myself and also i technically will have a blog, etc, etc
it'll be a personal website
my point is does the link need to go directly to the file
stuff that yes will be shared on discord
wdym ?
just add a download button on that page and add the file metadata and a description next to it if the goal is to share it
🤦♂️
the idea is to be able to see the metadata without leaving whatever platform the thing is shared on
that's the point of embeds
quick preview of what's behind the link
yeah you can still do that
this. then if I want the file I click on it and then click the download button
the point is why is discord basically stripping the thumbnail part of the embed
what i return here clearly work, with the link to the resource, it finds the embed, it then correctly parse my json embed but when it transform into its own output yeet thumbnail gone despite respecting the spec
it's fine if you don't have an answer i was asking generally since some people clearly know discord here
gotta use og tags for images
oh also since i noticed that they also support one last thing that is documented nowhere which is using the html title and meta description, i tried mixing that with oembed and actually they do combine, altho in an unexpected way, the HTML stuff shadow the oembed and not the opposite
thing is, i can't do that statically
or i have to have one nginx block for each image
why cant you do it statically
also technically this is not the image, this is the thumbnail
because i'd have to add one new block to the nginx config for each image
or basically only serve HTML, which is not the point
anyway unless someone has a magic trick or the explanation to why the spec is being handled so weird, i guess i'll write a big issue on the discord repo
the explanation is they only use opengraph for images
lemme find you the oembed website i had found that discord support
legend has it he never found that site
my history is so filled that yes it's hard to find
and the big names obv implement all of the methods
like meta (facebook and instagram) have an oembed API, but actually also use ogp and twitter to serve the metadata, instafix use ogp and oembed, etc, etc and i want to find the ones that truly only used oembed
wait
no
i found one
fucking spotify
https://open.spotify.com/intl-fr/track/1w8QCSDH4QobcQeT4uMKLm
see how spotify return a thumbnail URL and it isn't actually used
if you look at what the embed tester returns it has the same issue as me
but i'll find another instance of it
well yeah cause discord has a custom embed for spotify
it doesnt go through the embed tester
the thing is, when you test it, clearly the embed tester use the standard process for it
idk why you cant comprehend discord has special handling for spotify that is not available for your website
well hopefully someone else has a solution for you but im pretty sure og tags is your only option. good luck
it's not about spotify
the point is discord should not say they support oembed if they don't
yeah I should have rephrased that to "idk why you can't comprehend discord only supports open graph for images"
well because they say they don't
yeah discord is pretty stupid
it's like if i told you that you can choose 1M$, 1k$ or nothing
and you ask me for $ and i told you actually no, it's just nothing
you tried setting type to rich or photo?
i did try the photo type with url instead of thumbnail_url and with both url and thumbnail_url
as for rich type i've found in the discord API issue tracker that they only allow whitelisted sites to use it because it allow embedding arbitrary HTML
oh I saw that post and saw they had a working embed with an image so assumed they did rich type
but reading closer now I see they say they use open graph tags for that
https://julienraptor01.ddns.net/example_photo.jpg removed embed cause bad
i swear i'm gonna go crazy
has an image this time. except it's broken
why it's broken?
iframely says it's good
why does it fail to fetch the image
i'm gonna slap discord
it's trying to use the non-thumbnail as thumbnail
and if i'm lucky it's fucking cached the wrong thing
i can see in my logs it's not even trying to fetch the thumbnail
cause your width and height are wrong?
they aren't, look more closely
?
the thumbnail sizes are right
but it used the wrong URL
the thumbnail URL ends with thumbnail
your image is 2560x1440 not 480x270
yeah the embed unfurler returns an incorrectly structured embed idk why. it says thumbnail but it definitely is not resolved that way
i literally copied this working thing
here's mine. it says thumbnail but if you actually send the link it uses it as the main image and the internal embed data has it as the image not thumbnail
so thats not your issue
the unfurl endpoint does the same thing for some reason
hey please make use valid embeds
there must be some post processing done on the unfurled embeds
anyways your image not loading is a separate issue
https://julienraptor01.ddns.net/example_photo_thumbnail.jpg removed embed cause bad
please please please
i swear what is wrong this time...
like this time it cannot be wrong
looks to me like discord is being blocked from accessing it
what makes you think that ?
cause it's not loading the image
but the image exists at the url
it cant generate a content type for the image
so it cant access the image
i'm gonna try smth again
surely third time will be the charm
https://julienraptor01.ddns.net/yes.jpg removed embed cause bad
oh wait so the file is located at https://julienraptor01.ddns.net/example_photo_thumbnail.jpg. for users you serve the image but for discord you serve the html
so thats why it cant access the image, it's getting the html at that location
well yes the first time i'm forced to serve them the html since it doesn't support link headers...
also it's supposed to fetch the image with another UA which is macintosh
because "it represents" the user
thats why content type is empty cause html doesnt have an image content type
:pain:
oh the pain
so i can't make discord have embeds unless i serve it HTML because it doesn't read HTTP Link headers
but i can't serve it HTML because i need to serve it the file, otherwise obviously it's not getting the file
wait no
i'm thinking
this isn't even my problem
oh i'm gonna try a last thing
so this works
ok so clearly they suppress thumbnails
and only allow photos
so they also don't support the thumbnail part of the spec
they use the oembed photo as discord thumbnail
and they trash the oembed thumbnail
whats your oembed code look like
gimme a sec
https://julienraptor01.ddns.net/test4
{"type":"photo","version":"1.0","title":"Example Photo","url":"https://cdn.discordapp.com/avatars/94597845868355584/ee22dc4da38afa53158c1434bc5fa842.png?size=4096","width":4096,"height":4096,"thumbnail_url":"https://a","thumbnail_width":64,"thumbnail_height":64,"provider_name":"oembed-example","provider_url":"https://lachee.dev/","author_name":"Julienraptor01","author_url":"https://julienraptor01.ddns.net"}
this is cursed
it uses the url, discord the width and height, needs the thumbnail url to be valid, but discard it and use the thumbnail height and width
yes so after all these tries
when an oembed is served when it's in photo type :
- the oembed photo url is used as discord thumbnail URL (which is the one that gets proxied)
- the oembed photo width and height are discarded (and do not need to be present which is wrong according to the oembed spec)
- the oembed thumbnail url is required and needs to be a valid URL but does not need to lead to anything since it's unuused (the thumbnail URL is actually optional in the oembed spec for all types of embed, so again, not respecting the spec)
- the oembed thumbnail width and height are required gets used as discord thumbnail sized which technically is wrong as it's supposed to be the oembed photo that gets used if it was coherent or the oembed thumbnail url and then using these would make sense (again the oembed thumbnail sizes are optional for all types of oembed, so again not respecting the spec)
and i'm gonna go sleep because it's 5AM and i did not realize
also i'll probably make a user plugin when you can whitelist some links and those will get a client-side embed cause fuck it
when making commands, how do i get the reference msg?
PendingReplyStore.getPendingReply(channelId) has the message you're currently replying to in that channel
If that's what you mean
Question. How long is the verification process??? On the pr?
There is no set time, just whenever someone gets to it
Best to just submit and forget
hey, how can i get all messages that are rendered on a client?
im trying to make something that replaces text of existing messages
A/B problem
just patch the message component that renders messages
are there any similar plugins that i can check to see how something like that is done? i tried looking at TextReplace but it replaces the text for the user who sends it
i believe i've found what i need, could it be that the component is named g ?
i see how it works, how can i get the actual component name?
You can't, it's pretty much all minified
yeah i've scrolled a bit through messages here and figured that out, how can i patch this message component then if i dont know the name of it?
im very new to all of this lmao
you click to inspect the code and write a patch for that code. if you can't inspect it, you're on the wrong element.
the parent of g is G. you can inspect that
that makes sense yeah thanks
however G looks like a generic function. definitely not gonna want to patch that. really in this case you want to go up to Anonymous where it has the key which is the message id
you'd patch that
you can see it has a message object you can mess with
yep nice
although if your goal is to modify messages already rendered you're gonna need some way to rerender them once you've edited them. not really sure how you'd do that off the top of my head
what do you mean edit?
well you want to change the text in messages right
only for the client using the plugin tbh
There's a utility function to rerender messages
yeah exactly
I think it's just called updateMessage
you're going to be patching in something to modify message.content
hey there, this might be a stupid question but how does one get stuff like icons into messgae modals.
So for instance this:
tryna get the icon into the file name modal but I'm not sure how lmfao.
trying to do it like so:
quick question, in expressionCloner plugin why is there no need to check for sticker slots available like emojis below 
wait but even for emojis it's only counting the animated ones 
I'm so confused
wait you're right 
I forgor that isAnimated comes from the emoji's own data
still begs the question with stickers tho
I simply didn't implement it 
veediot
restart discord using ctrl-R
hey, so yesterday we discovered that its possible to use this as message component. it has a content property. but when i go to the minified code of this component i am greeted with a long as fuck minified line of code, how do i know what i can use in this minified code?
yeah its a 9500 character functionn
oh yeah i just threw it in a un minifier website and it actually looks readable now, the next step is to figure out, what do i need and how can i use it
trying to see if that gist guide can help me understand
i cant figure it out for the life of me 💀.. im looking at other plugins to find if they do something with rendered messages or so but i cant seem to find anything..
OH is that how my editor always shows it formatted? I was wondering about that
I must have clicked it one day and then forgot it was a thing cause ever since it's been prettified lol
scuffed proof of concept. you'll have to put the pieces together into your plugin to test it though. I've been mangling messagelogger to test this lol
// in settings object
stringToReplace: {
type: OptionType.STRING,
description: "type something",
default: "do not make the default value an empty string nightmare fuel awaits if you do",
},
// top level function
function replaceTextInMessage(message: Message) {
const { stringToReplace } = settings.use(["stringToReplace"]);
message.content = (message as any).originalContent ?? message.content;
(message as any).originalContent = message.content;
message.content = message.content.replaceAll(stringToReplace, "replacement text");
}
// plugin def
export default definePlugin({
// yada yada ...
replaceTextInMessage,
// yada yada ...
patches: [
{
find: "ChatMessage\"),",
replacement: {
match: /(message:(\i),message:{id:.{0,125}?;)/,
replace: "$1$self.replaceTextInMessage($2);"
}
},
]
})
this'll change the code to something like
let l, {id: o, message: x, message: {id: P}, channel: Q, channel: {id: et}, compact: en=!1, className: er, flashKey: ei, groupId: el, renderContentOnly: ea} = e;
Vencord.Plugins.plugins["MessageLogger"].replaceTextInMessage(x);
holy shit do not use an empty value for that setting.
nightmare
amazing, trying this now, is just saving the file sufficient or do i need to build it somehow?
pnpm build --dev
yeah. while working on it you can pnpm watch --dev but at the end you'll want to do a final build
and then restart discord or does it hot reload?
gotta ctrl r
if you do anything with native files in the future it'll require a full taskmanager restart but anything else reload is enough
yeah hence the "dont use an empty string" 😭
would be better to add a check in the replace function for that lol
yeah the idea is gonna be that the user can define what words to replace in a sentence
you’re making incoming messages textreplace?
yeah
well just every rendered message
nice
if you’re planning to PR integrate it to the main TextReplace plugin
just parse the existing TextReplace rules
i have read that code, let me check again
hm adding this to textreplace would need a bit of care though cause theres a big difference between changing your own text before it sends out vs client side modifying everyone else's messages for yourself
how
eh i guess you could add a per rule toggle to also apply to incoming messages
This is kinda spammy tho
I added a console log and as i was hovering over messaging it was spamming the print lol
yeah cause discord rerenders messages in real time if you're hovering it
I mean the only part of the code that I provided that would itself trigger a rerender would be when you update the setting so any rerenders it's doing otherwise is default discord
thats why I had to add the originalContent variable
without it it would compound replace
I was printing the result of one of the string options from the cog ui
hm yeah actually simple. I more meant like it might confuse people the difference between your message actually being modified but others' messages only visually being modified but not actually being changed for anyone else but I guess that's basic common sense
name it “Apply this rule to incoming messages on this client”
not sure where thet option should be placed. not much room left 🤔
maybe move the delete button down and have 2 equal width buttons below each rule?
or well a delete button and a dropdown where you select between apply to my own, apply to others, apply to all
does it work across everywhere on discord (like channel names or nicknames etc.)?
or just messages
that would be epic if it worked across everywhere
thats a lot more work to work everywhere
there's no universal text interceptor
you'd need a patch everywhere there is text
i did that at some point
but only for system strings
🤔 would replace one of the deletes with a dropdown but 🤔
idk how else to fit in another setting for "this rule applies to mine, to others, or to both"
oof it double replaces
cause once on send and then once on render
fixed with a message.author == me check I think
yea that’s great
bottom border between rules or no bottom border? 🤔
How about a line just between Using String, Using Regex and Test rules?
I was more worried about rules themselves blending together but 🤔
Smaller line between them
smaller line or smaller spacing around the line
oh
I see what you mean. not talking about the lines up there lol
🤔
Peak
invisible on light mode smg text-invert useless
Maybe a little brighter
use the divider component instead of making ur own 😭
FormDivider or smth like that
well it wouldnt work here anyways
nvm
you can margin left/right the divider
wtf
margining it is pushing it off the page
agony
does this mf have a default minwidth
no a default width of 100% ok
bit light but 
love when auto linting on save randomly stops working in vscode
?
it's a divider
and the margin allows it to imply a soft separation from the next item instead of a full on "this is unrelated to whats next"
just don't
agony
so i'm still a little confused with how specifically the find entry in a patch works, when you enter a string does it search for the function that matches and then let you modify anything in that function via regex or does it just look in the general area? when i see a patch it seems like it selects a bit of code and then modifies a completely different area of code in the general vicinity
so 
I've been trying all day to find the function that uploads emojis as practice (I'm looking again at expressionCloner with findByCodeLazy(".GUILD_EMOJIS(", "EMOJI_UPLOAD_START")) but the more I try the more confused I get
I tried everything from setting breakpoints on the onClick function, to XHR/fetch breakpoints, to checking the call stack, but I genuinely have no idea where I'm going
How else could I try to find it besides brute forcing with search? 
you are using the find in expressionCloner as a base to what ur supposed to find?
no
I'm trying to reach the same thing expressionCloner reaches
instead of just copy pasting it
I wanna understand how the person that made the plugin got to ".GUILD_EMOJIS(", "EMOJI_UPLOAD_START"
ye that's what I meant
I just gave it a shot trying to find it myself out of curiosity. Here's how I did it.
||I first fumbled with the call stack for 10 minutes before getting tired of that. Then I uploaded an emoji with the network tab open to find the endpoint/parameters it used. I saw it send a post with payload of image and name. So I global regex searched for image:.*?name: which is image: followed by whatever followed by name:.
Didn't go too well cause of how broad it was. So I just tried searching for the endpoint from the network tab instead /emojis which led me to a file with GUILD_EMOJIS: e => "/guilds/".concat(e, "/emojis"),. Then I searched for GUILD_EMOJIS which brought me to
function v(e) {
let {guildId: t, image: n, name: r, roles: i, analyticsLocation: o} = e;
return s.Z.dispatch({
type: "EMOJI_UPLOAD_START",
guildId: t
}),
a.tn.post({
url: g.ANM.GUILD_EMOJIS(t),
body: {
image: n,
name: r,
roles: i
},
```||
If you just wanted hints and not my process of finding it then I'd say take a look at the network tab while you upload an emoji.
I found it 
tho a bit differently
I found processFiles in the initiator tab of the post request which had the perfect name (so lucky that it wasn't obfuscated I guess) which led me to this
return e => (0,
n.jsx)(t, u({
processFiles: () => P(a)
}, e))
which then I inspected P with a breakpoint which led me to d(t, s) which upon inspection I saw that s is actually the function needed which also led me to a function I.G which was pretty big because of file size checks and name sanitization stuff but I eventually found a.rS which finally it was what I was looking for, the function that sends the post request
so from a function to function to a function to ...

speaking of luck, it's not the same with stickers 
I know that the actual code kinda skips this by directly using RestAPI.post, but I still need to go thorugh the same process to truly know what to dispatch with flux don't I?
you can just use the rest api
await Vencord.Webpack.Common.RestAPI.post({
url: "/guiilds/${guild.id}/stickers",
body: {
name: "sheep",
tags: "🐑",
description: "sheep",
file: binarydata
}
})
it'll automatically use your token n stuff to authenticate everything
But what about dispatching afterwards
dispatching what
FluxDispatcher.dispatch({
type: "GUILD_STICKERS_CREATE_SUCCESS",
guildId,
sticker: {
...body,
user: UserStore.getCurrentUser()
}
});
you have the debug menu enabled?
do that then upload a sticker and check the flux event
then just mimic however that does it
Im not sure you really need to do that though

isn't that necessary for refreshing the ui and stores?
try using the restapi and seeing if it automatically dispatches
oh checked expression cloner and it uses the restapi for stickers lol
ah it does dispatch
idk I commented out the dispatch and cloned a sticker and discord automatically sent out a GUILD_STICKERS_UPDATE
which isnt even the same event the plugin dispatches
so idk what use GUILD_STICKERS_CREATE_SUCCESS is
lmao
you were right
when creating a sticker naturally it sends both GUILD_STICKERS_CREATE_SUCCESS and GUILD_STICKERS_UPDATE
makes me question the whole purpose of ever dispatching
I'm gonna try to see if I can use the same RestAPI approach with emojis too, since it's clearly much easier than trying to find the actual function
hm I went through the process of what GUILD_STICKERS_CREATE_SUCCESS ends up doing and it looked like it was doing something with cache/sticker store idk
really this is a try it and see moment
try dispatching one, the other, neither, both, and is everything you need everywhere you need it afterwards
wdym
discord expects specific data in their dispatch handlers so you test it to see what it needs and then mimic it properly
les go it works 
used the link directly since I'm not that familiar with the constants 
saying that in some cases maybe you don't need to dispatch anything and it will still be fine
yeah idk
crypto.randomUUID doesn't work in unsafe http contexts but that shouldn't be an issue with a discord client 😭
why doesn't it anyway
no idea 💀
other crypto methods work
you can use crypto.getRandomValues() to polyfill randomUUID
Just checking, does it mean anything when Discord logs me out after ctrl + R to test a vencord change?
try enabling
vp nodevtools
Disables the 'HOLD UP' banner in the console. As a side effect, also prevents Discord from hiding your token, which prevents random logouts.
V
it's a string, the default value is an empty string 
sorry, yeah i added some values to it
but they didnt appear in the UI
now i just did it like this but still no worky
yeah cuz you had a non nullish value already at that setting
i turned the plugin off, restart my discord, turned it on again, restarted discord again
and the value was still not there
unless i am mis-understanding something
yes
do you expect a setting to delete itself when toggling the plugin
or that changing the default value for a setting to overwrite the existing setting
the first default you set already got saved
aka an empty string
but if i set one again and rebuild the plugin it should use that one no?
Oh its just a local storage thing?
the default value is used once when the setting is first needed and no value has been saved yet
after that it just becomes a normal setting value like if the user did the input
so changing the default will have no effect
since you are still developing the plugin just open your settings file and delete the setting, then the default value will be used again
or just input the new default value you want
idk if doable, but it would be nice if i could set the spellchecking languages in discord cause i speak in english and french and it seems to choose one at random each time
i'm sure i cannot be the only person to get this problem...
you can in vesktop
i should use this to make the menu saner
doesn't vesktop have downsides over vencord on windows ?
Only really in streaming
not in my experience
streaming has always worked fine for me
Its fine on windows for me
Only thing I dislike is streaming issue on Windows
Other then that it works
I'd put no game detection as a pro
I mean you can just disable it in discord ?
Anyway if this could come to vencord it'd be fire
no
😭
is it because it's pure pain / impossible to do, or because you don't want to ?
so that i know if i should try to do it or not
just make it a plugin
That's probably not a good way to indicate a setting is enabled but id look at the reply bar
How would i communicate between an
native.ts
and index.ts
more precisely
// index.ts
import definePlugin, { PluginNative } from "@utils/types";
const natives = VencordNative.pluginHelpers.GlobalShortcut as PluginNative<typeof import("./native")>;
export default definePlugin({
name: "GlobalShortcut",
description: "Global shortcut tester",
authors: [],
async start() {
console.log("Start");
natives.registerShortcuts();
},
doStuff() {
console.log("This does some stuff");
}
});
// native.ts
import { IpcMainInvokeEvent } from "electron";
import { globalShortcut } from "electron";
export function registerShortcuts(e: IpcMainInvokeEvent) {
globalShortcut.register("CommandOrControl+A", async () => {
// Run from index.ts doStuff()
});
}
there's no intuitive way to send messages from native to renderer
you can define a method on your plugin and use evaluateJavascript
oh ok good to know
You're probably better off just adding a chat bar button that both toggles and indicates whether it's on or off
I have a question regarding the rules of plugin upload. Specifically "No raw DOM manipulation. Use proper patches and React." In the case of playing a sound, how is this done without using the HTMLMediaElement which is part of the DOM. I was not able to find a way to do this in React without using external lib/hooks.
any help is appreciated 🙏
do you want to play a custom sound or a default discord sound?
a custom one
then I think new Audio() is the way you want to do it
Forgive me if i am wrong but doesnt that create a DOM element?
I mean I think so? But you're not modifying the existing dom or attaching it anywhere. it just floats there in space til you delete it.
Ah okay, Thank you very much for your help 🙏
also afaik no way to play audio in a browser context without using an audio element
goccha
this rule refers to things like using a MutationObserver or querySelector to grab raw dom nodes and then messing with them
creating an Audio or Image element or similar are perfectly fine
Oh awesome thank you for the clarification
just use message accessories
how can i call an external api? its getting blocked by csp if i just do it with fetch 💀
i wanna notify a (non discord) webhook when specific things happen
add a csp rule using native
you can also request an override in your plugin settings
oh my god thank you 🙏
If it’s an API known at compile time, you should use add a csp rule in native
The function for requesting overrides at runtime is intended for user provided urls
how would one accomplish that
Take a look at csp.ts
ok 🙏
thank uuu
On addMessagePreSendListener(...), can I somehow cancel the message?
return {cancel: true}
another silly question
, is it possible to create another fixed element using patches?
For example I'm trying to add a textarea right under the members tab. I could in theory make it position: fixed from anywhere but I want the background color to be good with any theme, meaning that I'd have to basically shrink the members tab and create a completely separate area
I tried going up the react tree until I found something above the whole tab, but only got to this class so I went even higher and tried to patch there but no result and I genuinely don't know where to go from here 
You can generally patch the children prop of the parent to add in your own components
yeah but how do you do that when the parent is so complex
wrapping the channel header, chat and members tab all in one
that's why I'm confused
you need to patch the children prop of the element which includes the member list
there is 100% one parent which has a child that is the member list with the whole scroller
wait I think I'm getting somewhere

I was able to add it right inside of the first layer of the members tab but members keep pushing it down
like it works fine when the members aren't taking 100%
FINALLY
Congrats
tho the most shady patch in existence
yeah but if you set background: none wouldn't it be a conflict?
You can probably just replace most of that with groups from the match
Yeah you can see the list behind it
You'd have to use discord's background colour var
Probably blocks the bottom of the list as well, not sure
built in notepad, maybe a message display before sending, idk for now I'm just testing with the limits of patching
Nice
you know you can write JSX in your plugins code and call a function from your plugin

but even then, is this a viable solution?
doesn't sound that stable at first sight
I guess this makes much more sense
you can also import css files
also that errorboundary makes no sense
isn't ErrorBoundary basically a safer div?
no????
idk I saw other plugins use it instead of normal divs
and with noop that's what I ended up thinking
error boundary is meant to catch errors in your react components
if your component errors, it won't take down the whole app with it
that's what I meant by safer div
but ig it's impossible to get an error from just a textarea
so makes sense
in most cases, prefer ErrorBoundary.wrap(() => { /* jsx here */ }) over <ErrorBoundary />
no
export const WontError = ErrorBoundary.wrap(() => {
throw new Error("foo");
});
export const WillError = () => {
throw new Error("foo");
return (
<ErrorBoundary>
<NonErroringComponent />
</ErrorBoundary>
);
}
errorboundary as a component only catches errors of children, not the component itself
your ErrorBoundary will only catch if the textarea component errors. but that is an inbuilt html element so it is impossible to error
ErrorBoundary only catches errors in child components
even this will not be caught by the ErrorBoundary
function MyComponent() {
const user = null;
return <ErrorBoundary>
<div>{user.name}</div>
</ErrorBoundary>;
}
what you have to do is this:
function MyComponent() {
// something that errors here...
}
const renderMyComponentSafely = props => (
<ErrorBoundary>
<MyComponent {...props} />
</ErrorBoundary>
);
that's exactly what ErrorBoundary.wrap does for you (and it also has the nice side effect of turning your component into a function that can safely be called with component())
ErrorBoundary.tsx: Lines 121-125
ErrorBoundary.wrap = (Component, errorBoundaryProps) => props => (
<ErrorBoundary {...errorBoundaryProps} wrappedProps={props}>
<Component {...props} />
</ErrorBoundary>
);
another silly question 
is changing the profile theme colors considered api aboose? I'm basically trying to change the colors based on the rpc's image (like it would be kool to make the profile blend with the album cover if it's spotify for example) but what if that risks getting disabled 
changing the colors every ~3 minutes shouldn't be that bad should it 
risky but not that bad ykyk
not sure if there's a special ratelimit on profile editing tho
may be
there 100% is
I've kept the script with a really risky interval on an alt for half an hour and so far so good
wait I just realised that's something else unrelated 
I think
oh you’re intervalling
insane
for test purposes only
oh okay
I do plan on making it sync with any rpc if I can figure out that
this is just selfapping
there’s some flux event 
use that but yeah a bit risky
it wouldn’t be in #1256395889354997771
long live flux (but not the dispatcher)
😔
not necessarily for unofficial plugins tho sux that it's risky
Is there a way to use MessageActions to send a file or do I have to use the RestAPI to send a file?
I can't tell atm by reading the code tbh
Unless you start skipping through a bunch of songs
Could you point me in the right direction? I am reading the code and it is giving me cancer and I see nothing related to attachments, uploads or anything with SendMessage / MessageActions
There is one and that is where I get the RestAPI idea but no others
But if it is possible doing it a different way I want to do it that way because it just adds a mess into something that is kinda already fucked up
how petpet does it is how I have it atm it just puts the file as prompt to upload
voice messages does do it however I want to stay away from this because there are multiple instances of sending files and this is a mess, I could just make a function that will handle it however if I can just do it through sendMessage it is a lot easier for reading and adding onto at least imo
you can CloudUpload and then sendMessage with the attachment probably
sendMessage takes no attachments or anything that is my struggle LOL
Breakpoint MessageActions.sendMessage and send a file
put a breakpoint on it and then send a message with a file
If you drag and drop a file while holding shift it insta sends so you can see what they do there too since it's not pre-uploading
does the same thing
it just doesnt send a deletion post to the attachments endpoint if you cancel your message
cause it's already sent and cant be cancelled
sendMessages takes up to 4 params despite only showing 2 in the function declaration. breakpoint it while uploading. the attachments are in the 4th argument. arguments[3].attachmentsToUpload or something like that
but the format that takes is what the attachments endpoint returns im assuming so
you'll have to chain something together
despite only showing two
what?
in sources it only shows 2
takes up to 4 though
I guess that just means it can take between 2 and 4
wording not great but
use sendMessage from vencord utils bruh
that's how they do optional arguments
yeah
you say this like MessageActions is typed and should explain all of this. it aint typed at all unless im blind
use sendMessage from vencord utils bruh
it isnt
its sent in messageoptions
idk why ven repeating themselves when I clearly dont know what they mean but good luck with your search x_x
lmfao I really appreciate it ty
thats... literally the function I posted a screenshot of??
are you being dull on purpose
for the love of fucking god this needs to be added to the MessageOptions interface
I was just assuming you were omitting the MessageActions to be brief. Like [MessageActions.]sendMessage. Didn't realize it had a separate sendMessage of its own
its the same thing
also the file is named utils.ts so my brain didnt compute
yeah but it's slightly more typed
yeah not enough for what you need
but it shows you the structure
4 arguments
4th is the one you pass attachment data to
That is what I was thinking already but if it was typed -_-
I gave up on it like "maybe im the dumbass and thats all there is"
pr the change you want to see in the world
gonna have to 😭
I saw that discord uses a get request to receive messages when searching (ofc makes sense) tho brings me a question 
is it theoretically possible to expand the functionalities like adding "not from ..." and maybe even regex? I doubt discord prepared an api for that and the cache of a channel on the client side seems to be only 50 messages (at least with MessageStore.getMessages())
negation seems fairly possible cuz I can just filter out on my side tho loading the pages would be a bit tricky
You're not gonna be able to add any parameters the endpoint doesn't support so you probably can't do much besides a local search which has the issues you mentioned
not possible
the only way to add that would be to fetch every single page from their api then do it locally
just download your data package and you can regex search that

Discord should just improve search tbh but I think they've said in the past that it's a limitation of how they index messages or something
authorType is a nice recent addition at least
at least one thing they could do is keep it one language
which I'm going to try to do
it's funny how discord only loads some in japanese meanwhile there's a module with all of them
I am back with another dumbass question
Whenever you prompt and upload with a file it instantly uploaded to discords cdn
How could I go about patching that to prevent it from auto uploading to the cdn?
I am not the greatest using the devtools to find stuff like that tbh so if someone could help me out that would be great
For a plugin 😅
the question is what is your endgoal. what is it you're making. why do you need to prevent it from auto uploading to cdn
Making an encrypted messaging p luginusing pgp i hate all the other plugins. I know you are going to say "just use a different chatting platform". I just want the ability to speak like this to different types of ppl without using a different app
I want to encrypt that file before it is ever even reaching discords servers but being it is auto uploaded to the cdn it kinda prevents that
there already exist such plugins
anyway you need to find the place in code where discord starts uploading the file
and before that just encrypt it
I have only seen 2, encrypt cord which only works in a groupchat and invisiblechat which i dont like because it uses a password system instead of a public / private key system
mine is more advanced then all of those but anything related to reading how discord does thingss (like what was said above) is where I struggle that isn't where my experience is so im still learning
I tried patching genuinely everything I could find and no result
I was able to change the text but directly typing "mentions:" doesn't work, the whole purpose I'm even trying
what else could I try to do? 
you might want to use this instead of the raw key
makes things eaiser to read
What tool is that 
btw idk if this is helpful at all but a long time ago I made a little plugin for adding custom search operators/enabling hidden ones, you might find something useful there https://github.com/Vendicated/Vencord/pull/534/files
there were a couple places that needed to be patched for the search operators to actually function properly
Even then the key patch did absolutely nothing

wait am I doing something wrong? the first one works just fine meanwhile adding intl breaks it
it adds a dot I think
life is so much better now
only a bit of manual labour
I could theoretically pull the values from the english module to make it future proof but 
how can match alone find a module while the same expression in "find" is going to scream at me cuz of too many results
I'm basically trying to make it language independent, tho can't quite find peculiarities yet
I love regex
yanderedev code
btw maybe instead of patching individual strings you could just add the properties you want to override at the end of the json string
this way you could also get the hashes at runtime using runtimeHashMessageKey
or remove the keys entirely, since that should theoretically fall back to the english translations
that makes so much sense
I have to try it out
you were right (tho still yandev moment
)
changing a language module is the worst way of doing it
you could have just patched where they are used
and it would work for all languages
I tried that everywhere but couldnt do anything about the search autocompletion
This was my last resort
it wasnt
the same way you are changing the language files u can change everywhere the string is used
Tried that for 5 hours yesterday without success, I genuinely don't know where else to look
I need to double check that, tho I think I've looked into those before
you can do something like
idk
match: /\i\.intl\.string\(\i\.\i#{intl::h2NzSU::raw}\)/g,
replace: '"during"'
in both of those modules

Tho why is changing the language module that bad?
I made it work with any language
ehh
other plugins might rely on it not being changed?

you risk changing places which are unrelated





