#🧩-plugin-development
1 messages · Page 81 of 1
Giant ahh buttons
yeah but the alternative is giving them their own lines
like client themes
doesnt look good imo
and you cant resize the color picker like i originally wanted
you'd need to patch it .-.
I’m not hating. I’m just laughing.
Hello,
I've been working on a plugin, that, after processing some files, adds them to the current channel, so the user can optionally add a message and then send it. This worked quite well until recently, and i have no idea why it stopped.
Here's the code in question
/**
* A wrapper for adding attachments to a channel.
* @param files The files to attach
* @param channelId The channel to attach them to
*/
export function addAttachments(files: File[], channelId: string) {
UploadHandler.promptToUpload(files, ChannelStore.getChannel(channelId), DraftType.ChannelMessage);
}
And looking into the debugger it seems to receive the things it needs (see image below).
However nothing appears in the channel. And this despite UploadHandler.promptToUpload seemingly working in other Vencord plugins.
As I can't seem to figure out myself what I'm doing wrong, I'm asking here. Anyone got a clue or a tip?
oh nvm you can resize them. thanks for bullying me into trying again lol
.vc-qq-color-picker-container>div>div[class^="swatch"] {
width: 300px;
}
Long ahh color picker
😭
just stack them in a 2x2 grid so nothing is too wide
oh yeah I could do that huh
hm that would mean I would have to squash them into a single OptionType.COMPONENT though wouldnt it
ill look into it tmrw
fixed by using the upload manager instead
/**
* A wrapper for adding attachments to a channel.
* @param files The files to attach
* @param channelId The channel to attach them to
*/
export function addAttachments(files: File[], channelId: string) {
// UploadHandler.promptToUpload(files, ChannelStore.getChannel(channelId), DraftType.ChannelMessage);
// Vencord.Webpack.findByProps("addFiles")
UploadManager.addFiles({
channelId: channelId,
draftType: DraftType.ChannelMessage,
files: files.map(e => ({
file: e,
isThumbnail: false,
platform: 1 // WHAT DOES THIS MEAN.
})),
showLargeMessageDialog: false
});
}
I'm still baffled by why it didn't work with the simple other function anymore
were you up to date
promptToUpload got broken recently
but it has been already fixed
vencord was finding the wrong function which did nothing
looked into it today instead :^) and I have no clue how to change multiple different settings from inside a component. nothing I do updates the settings :(
Are you using setValue on the props passed into the settings component?
It'll only change the settings when you click save this way
that props wont have all 4 other settings
You can use useSettings if you need the others but they won't update until you click save either
If you need access to the other settings in realtime they're gonna need to be custom too
This is for this settings page, all these are one custom component so I can access all the settings as they're entered #👾-core-development message
got it working somehow
const [value, setValue] = useState(settings.store.restyleExpired);
function updateSetting(newValue) {
console.log(`Updating setting restyleExpired to ${newValue}`);
settings.store.restyleExpired = newValue;
}
...
<ColorPicker
color={value}
onChange={newValue => {
setValue(newValue);
updateSetting(newValue);
}}
showEyeDropper={false}
/>
updates live too. wasnt expecting that
previous 1 entry per version didnt
Nice
Setting on settings.store directly means it'll update the setting live as you change it but it means the cancel button on the settings modal won't really do anything
just checked it manually, I wasn't, even though git pull told me it was up to date... fixed it now, that was certainly confusing how i got there...
hmm yeah not sure how to fix this
use setValue from the custom component props, it's basically just a buffer that holds the new settings value to be applied when you click save
But you'll probably have to have one overall setting that contains the individual ones
You can always just have a colours object as a single setting with the four colour settings as properties of that
That's what I do for the timestamp formats
can I see how that object looks
You might have to use withPrivateSettings for ts to know that settings.store contains that
Smh i've fucked up my plugin somehow with this previewer change I made so the settings keep resetting
instantFormats is the same as formats when it's working normally
and thats just a setting in definePluginSettings?
Yeah
doesnt it yell at you if you try to use options that are built in
oh optiontype.custom?
Yeah
That one component option manages the format settings object and I just put all my settings on that
can custom still have a component argument
Oh not custom sorry
huh
I mix up custom and component
The code is in here https://github.com/Vendicated/Vencord/pull/3189
CustomMessageTimestamps
This plugin allows you to customize the timestamps in chat messages and tooltips.
This is a rework of Rini and nvhhr's plugin and as such both are included as devs t...
I dont like private for this because I cant set defaults
rn I just have them set as hidden: true
Yeah I do the defaults manually
My big brain managed to reset the settings every time I opened the modal

are settings from settings.use mutable?
ok yeah just went with a comma separated list
export function parseRestyleValue(restyleValue: string): (number | null)[] {
let colorArray = restyleValue?.split(",").map(color => color === "null" ? null : Number(color));
if (!colorArray || colorArray.length < 4) colorArray = defaultStylesArray;
return colorArray;
}
const defaultStyleValues = "2842239,6105983,8334124,2368553";
const defaultStyleValuesParsed = parseRestyleValue(defaultStyleValues);
const [defaultUnclaimed, defaultClaimed, defaultIgnored, defaultExpired] = defaultStyleValuesParsed;
const defaultStylesArray = [Number(defaultUnclaimed), Number(defaultClaimed), Number(defaultIgnored), Number(defaultExpired)];
function RestyleGrid(props: { setValue: (value: string) => void; }) {
function serializeRestyleValue(colorArray: (number | null)[]) {
return colorArray.map(color => color === null || color === undefined ? "null" : color).join(",");
}
function handleRestyleChange(colorIndex: number, newColorValue: number | null) {
const colorArray = parseRestyleValue(value);
colorArray[colorIndex] = newColorValue;
const newRestyleValue = serializeRestyleValue(colorArray);
setValue(newRestyleValue);
props.setValue(newRestyleValue);
}
would be kinda cool to see it update live but then if you click cancel have it revert but I dont think thats possible with how the settings props work
g r i d
Yeah, I wouldn't mind a bit more control over the settings modal in general, it's very compartmentalised for each individual setting
speaking of settings is there a better way to do this without destroying settings for other platforms
like currently this linux setting is specifically for KDE but what if I wanna have a setting for a different DE but also persist the selected setting across DEs (and OS's but i split them)
(also i think rn its imossible to have the hidden value come from native cause its all async)
the appearance settings could potentially be moved onto a modal?
I think that'd allow more control over the data
I feel like there's a simple way tho
@dull magnet is there a specific reason you made everything coming out of native be a function coerced into being async?
idk what you mean by "coerced"
there is sync and async ipc
you should avoid sync ipc
so it simply uses async ipc
well you can export function nonAsyncFunction() () in native and itll be only accessible with a promise despite lacking the async modifier
mhm and i was wondering why only async
like yeah you should avoid sync ipc but its still useful sometimes
im asking why
why why why
i need a static value out of native synchronously so cope your api is bad
this ui looks soo good
Perfect
now to just test it for a bit to make sure nothing breaks :D
You gonna make it a Pr or submit it too #1256395889354997771 ?
Because it’s actually kinda cool
originally unofficial cause it was minimal but then I started adding a lot of cool useful stuff so I'll make a pr once I test it for a bit and make sure nothing breaks. also need to see if I can find a loophole to discord not updating your available quests without a client restart or manually clicking to the quests tab
So when you reload Discord, or when you navigate to /discovery/quests, the client makes a request to https://discord.com/api/v9/quests/@me to update the available Quests. (It also sends one to https://discord.com/api/v9/quests/decision?placement=1&client_heartbeat_session_id=xyz&client_ad_session_id=xyz but I'm not sure if that's relevant.)
I'm not really sure how the stores work but would manually requesting the quests/@me endpoint also update the QuestsStore or would I need to do something else, if that's even possible to manually trigger a store update?
The main problem is if you leave your Discord open for a long time then you'd never be giving the client time to update the Quests and so the plugin would be a bit behind as well. 🤔
okay now add complete quest button
dont think daddy discord would be a fan of me if I did that
just dont make it complete faster 
you cant anyways. has to take as long as it needs to
should be fine then
???
insane
thanks
figured out how to send an api request to quests/@me and retrieve the current quests. im assuming this wouldnt update the store but the way the plugin works it doesnt really need that until you go to the quests page which would update the store automatically anyways, so I can just make use of the results from quests/@me for the unclaimed quest indicator. would making auto fetching quests every hour with a setInterval a setting cross the line of the "no self bots" rule or is that reasonable enough? 🤔
@fallen sandal is there a specific reason to be fetching the avatar URL again in SendNativeNotification? avatarUrl is already passed as an argument in the function
UserUtils.getUser(advancedNotification.messageRecord.author.id).then(user => {
const avatar = user.getAvatarURL(basicNotification.guild_id, 256, false).replace(".webp", ".png");
this plugin already exists as a third party just not really available here
?
the plugin you’re mentioning of adding an indicator for newly available quests it adds a color gradient and calls the api every time you start at an interval
i’m not entirely sure what that interval is cause i’ve only looked at the code once or twice
but it would add a button to the top of your server list and display all your quests that are available as a number and once clicked it’ll direct you to quests tab
when there’s no quests it’s white and when there is quests it’s rainbowish
yeah found the repo. interesting. still prefer my implementation
i was mentioning it so maybe you could take a look at how they make api requests in case you’re still confused
also potentially outdated looking at the routes they use
saw in another plugin the syntax is just
const { body } = await RestAPI.get({ url: "/quests/@me", retries: 3 });
wasnt sure how the authentication would work but guess it's automatic. thats nice
yeah with rest api it automatically passes your token in the requests i think you don’t need headers for most of discords api
maybe I found a different project cause this one isnt making any api requests as far as I can tell
probably i can send it to you idk if it’s officially published he only sent it on discord
ah
he said he made it for himself
if you have a link sure
I doubt it'll change but there's probably a constant URL in Constants.Endpoints
based on the repo I found thats a year old it used to be /channels/@me/questsMenu lol
where do I find the values here
Just look at the object in dev tools I think
If you have console shortcuts on then Constants should just be on the window object
I'm not at my PC so I'm not sure where it gets it from but you should be able to find it in the consoleshortcuts code if not
It's in @webpack/common
its there
my ctrl f didnt find it
search again
very cool joona thanks
its fine if you use a plain string for that though
uhhh not sure I might've just not noticed it was passed
let me look
ok looking at the commit history user.getAvatarURL(basicNotification.guild_id, 256, false), was used before
dunno what's coming in through that avatarUrl var
Link to the senders avatar
It's smaller though
160x160
@pearl stag why are you called ruotsin tunti 😭
I'm guessing you're Finnish?
Yup
yop
I used to have a different profile picture
Since let's just say i didn't enjoy swedish as a subject
It used to make more sense
My old pfp was some guy screaming
Paired with the username
lol
Then i updated my pfp in... 2023 i think
And didn't bother changing my username
Or nickname i guess
that's fair
@pearl stag the betterNotifications pr is still obviously under development so no its not gonna be approved for merge yet...
Alright
Just wondering if there's anything obvious to fix
focus on that when all the features are in
Question; Other then like building a custom element, maybe doing a <br /> to force it on to a different line, or a text wrap. Is there anyway to add a second line of text ...
The text wraps, so you can write more text.
Nah I wanna add a second line of text that can be easily customizable
Make description take a component as well as string 
Are the letters here consistent or are the webpack modules consistent? I'd like some way to note on my patches where they're found to make going back to them in the future easier.
neither the webpack modules or the letters are consistant
agony
Obfuscated names are extremely unstable, they change with every update
ya
Module ids are somewhat stable, sometimes last for months
thats why we use finds instead of webpack ids cuz the content of webpack modules changes WAY less than the id
whelp depends on the module itself and the find i guess
well I guess patch helper is the solution here then
what do you wanna do
get a component?
just know where the patch is made so I can go back to it later if I need to do anything with it
oh wait missed the second half of your message completely
lol
not sure if there is a good way
normally if i wanna add more info to patches i just add comment that says what the patch does exactly
i think thats enough to find the module that was patched
yeah doing that too
example
For that I've found downloading a local copy of all of discord's webpack modules to be the easiest thing to do.
I download a local copy, then pre-format it with the exact same formatter devtools uses, and then I find it really easy to search through and find the module I need to patch.
how do I go about doing that
Vencord companion can do that for you and it's really nice and easy to use.
I don't format mine, just split each module to separate files
(My version of it)
I have companion but only like 1 of the 4 buttons in vscode work 
your version too
cause it was newer
yeah, that's what it does, it makes a file for each module
I'll upload a video tutorial later tonight, maybe. god knows my ux needs work
only test patch ever works. other 3 always error
Did you install the plugin alongside it?
I'm gonna go into the store. I'll help you out when I get back.
thought yours was an alternative
No, you need to plug in in vencord.
👍
plugin pretty much done at this point I just need Discord to send me a new quest while my discord is open to see if the auto fetch is working .-. chop chop discord
sadan's version has a different discord plugin
ah
readme just mentions the dev companion plugin so I wasnt aware
for some reason it isn't mentioned at all in the vscode extension
lol
i know, i need to fix that
if Someone PRs that I'll merge it in
Error: webpack.find found no module
best way to wait/check if webpack is ready?
Is the module lazy loaded?
I want something to run when the plugin is enabled so I'm putting it in start() but if it's already enabled at startup it doesnt need to run (and cant cause the plugin is set to start at INIT)
it's calling RestAPI.get
or is there a way to tell the difference between startup and enabling it after the fact 🤔
looks like onceReady.then(() => {}); worked
oh I forgot the plugin forces a restart after enabling it anyways so this is pretty useless. 
Where is a good example for how to add a checkbox a VencordToolBox setting?
Have skimmed through this channel but still not too sure, what would be the best course of action of modifying the logic of a component like the tooltip, or replacing it? My use case is changing the way tooltips anchor onto elements and their appearance behavior.
sounds like CSS would work? if it's just about appearance
context menu patch
The anchoring behaviour isn't driven by CSS from my looking
looks pretty css-able to me.
though it would effect all tooltips
The tooltips can spawn in all four directions (top left right bottom) so you can't hardcode an offset as an example
what do you even want to do with it
Move them so they're anchored closer to the element you're hovering over
{
find: "tooltipPremium});",
replacement: {
match: /spacing:\i(,nudgeAlignIntoViewport:)/,
replace: "spacing:50$1"
}
},
default is like 12 or smthn
inspecting the tooltip component is a pain since it's an on-hover only and if you pause with a breakpoint the components tab freezes 
but if you unpause in the sources tab and dont mouse over the client the tooltip wont go away so it works
I haven't worked with plugins before, what specifically can I do with this? I'm still not too sure.
hey I have a request
could we remove the NoUnblockToJump plugin from the official plugins?
it was created by a now-deleted user, and also it never worked for me
always jumps to a random message
?
clarify
auto fetch worked, nice :D also apparently updating the quests store manually is as easy as dispatching QUESTS_FETCH_CURRENT_QUESTS_SUCCESS with custom data. that makes this easier
Ig as long as auto fetching doesn’t get too flagged for spam or whatever
looked at some other plugins that do periodic api calls and it's only once an hour so hopefully it's fine
also a disableable setting
kinda less useful without it though cause you wont know when new quests are released otherwise
@dull magnet hey there, in the ticket you mentioned reexporting stuff from @webpack/common. I tried your snippet and ig it's not valid typescript syntax:
import { ChannelStore } from "@webpack/common";
export { ChannelStore: ChannelStore as MyChannelStore }
// Parsing error: ',' expected. eslint
I also tried declaring a local variable and exporting that:
import { ChannelStore } from "@webpack/common";
const _ChannelStore = ChannelStore as MyChannelStore;
export { _ChannelStore as ChannelStore };
But this seems to be causing some issues
should I just wrap it in proxyLazyWebpack/proxyLazy? Idk if that's bad practice but it stops the errors at least
oof
why is that not valid syntax lmao
idk 😭
but is there any reason why it crashes when accessed indirectly
I thought it was just passing around the whole proxy object so it should't matter
You'd get an export named MyChannelStore I believe
I think ```ts
import { ChannelStore as OriginalStore } from "@webpack/common";
export const ChannelStore = OriginalStore as MyChannelStore;``` would work which is just a streamlined version of the second solution above
what is that even doing
I'll probably use that
redefining the store type and exporting it again under the same name
the types in @webpack/common and discord-types are outdated and I don't want to cast every time I use the store
😭
just fork it and update it and then pr vencord to it thanks

Is there a way to patch a component but only my implementation of the component 🤔 I want to change a built-in string but not for every implementation across Discord, just mine.
Can you do anything to differentiate your one? For my preview timestamps I set the message ID to something only my preview messages would have so any others could be ignored
If you can access it from your patch sure
Or just add a another prop
can you explain this more
In your patch, is there anything you pass into a function or something that you could identify your own version and return early instead of doing whatever the patch does?
Like```$self.doThing(component);
doThing(component){
if(component.isMine) return;
// do thing
}```
I don't know what you're patching but if you can identify your own component you can just tell it not to do anything
ah
I get it now. so I patch it for everyone but the patch just checks if it's mine and if not does the default
Yeah
holy shit that was way more work than it needed to be
{
find: '"onSearchChange",',
replacement: [
{
match: /(\((\i),\i\){)(var{options:\i,)/,
replace: "$1const vcDynamicDropdownNoResultsText=$2.noResultsText;$3"
},
{
match: /((\i);return\(0,\i.\i\)\(\i,{)(loading:\i,)/,
replace: "$1noResultsText:vcDynamicDropdownNoResultsText,$3"
},
{
match: /(function \i\((\i)\){let{onSelect[^]*?)(\i.intl.string\(\i.\i\["[^"]+"\]\))/,
replace: "$1$2.noResultsText??$3"
}
]
},
agony
:)
I mean, as long as it doesn’t let you go under 30 minutes that’s actually kind of cool
Because I think if someone was to sell it checking too frequently than that might trigger the API for abuse
Noice
gonna have other checks anyways to validate it
since you can edit settings manually
speaking of getting rate limited 
forgot to multiply by 1000
was making request every 1800ms not 1800s
wtf this is a new reward type
digital PNG download
probably ingame
oh that'd make sense
usually they specify ingame though
btw how do you upload assets for the readme? I know you can just drag an image into a comment on github then copy that markdown elsewhere but I notice all the existing plugins that have readme assets are attributed to the repo: https://github.com/Vendicated/Vencord/assets/... whereas the image I get is https://github.com/user-attachments/assets/....
also does the readme need to be basic? I notice a lot of plugins dont have readmes and those that do pretty much just have the tagline of the plugin and an image but I'd rather also explain all the settings if that's fine. 🤔
yeah

bro hacked into my discord and stole my code
@humble tulip you have an onChange for your component setting, right?
I don't think so
rip
When you save it just commits what you've passed to setValues
mine are triggering twice
I also logged shikiCodeBlocks's onChange and that triggers twice too
cant fathom why
Maybe breakpoint it and see if you can see where it's being called twice in the stacks?
like breakpoint the save button?
Or just your onChange, I dunno
is there an example somewhere of how to add domains to csp with my plugin?
private notifyListeners(pathStr: string, value: any, root: T) {
const paths = pathStr.split(".");
// Because we support any type of settings with OptionType.CUSTOM, and those objects get proxied recursively,
// the path ends up including all the nested paths (plugins.pluginName.settingName.example.one).
// So, we need to extract the top-level setting path (plugins.pluginName.settingName),
// to be able to notify globalListeners and top-level setting name listeners (let { settingName } = settings.use(["settingName"]),
// with the new value
if (paths.length > 2 && paths[0] === "plugins") {
const settingPath = paths.slice(0, 3);
const settingPathStr = settingPath.join(".");
const settingValue = settingPath.reduce((acc, curr) => acc[curr], root);
this.globalListeners.forEach(cb => cb(root, settingPathStr));
this.pathListeners.get(settingPathStr)?.forEach(cb => cb(settingValue));
} else {
this.globalListeners.forEach(cb => cb(root, pathStr));
}
// this.pathListeners.get(pathStr)?.forEach(cb => cb(value));
}
ok so the issue is the last line in SettingsStore.ts. Once I commented it out my onChange only gets called once and it does succeed updating the value. sooooo 
this is above my pay grade
Update, was able to do via very cursed means
@cedar olive since this was your PR mind chiming in
tldr onChange for settings is being called twice. commenting out that last line fixed it for me but im not sure if that has other consequences.
no setValue calls a temporary onChange which is independent in the settings modal
It looks like it's the same onChange that is called on all settings types
well yeah but it's not the one you can optionally set on the setting
unless it is idk
all the plugin internals confuse me
this is what I meant
the setting component's on change is a wrapper for setTempSettings and is called any time the value changes while the modal is still open
not the same as the onChange you can pass in which is only called if you click save
Yeah I think you're right
Too many things with same names
When you add your own onChange it gets added as a SettingsStore listener, so yeah I guess it fires once for the plugins.pluginName path and once for plugins.pluginName.setting ts if (opt.onChange != null) { SettingsStore.addChangeListener(`plugins.${p.name}.${name}`, opt.onChange); }
yeah. cant really understand what all that bit of code is doing though so idk if the last line was a mistake or is partially needed in some cases
logged it for my use case and the values of settingPathStr and pathStr were identical so idk
Yeah I was gonna say I'd be kinda confused on how it'd be calling plugins.pluginName because there would be nothing setting a listener with that key
I should just put an onChange on something and try things instead of speaking in hypotheticals
it happens to shikicodeblocks too
lol every time my timestamps rerender (every second for every message because of relative time) and get the settings again it adds the change listener again
lol
I think where it says ts if (paths.length > 2 && paths[0] === "plugins") { it just needs to be 3 instead, because this captures plugins.pluginName.settingName which is identical to the whole path and so the if block and the lone callback after both get the same listener
setting it to 3 stopped my issue
I would make the change and PR but I can't be bothered testing a bunch of settings to make sure it doesn't break anything
thats why I pinged nookies
I just looked through every use of onChange and it looks like nobody has ever used it for anything where it matters if it's called twice lol
So it's never been noticed
yeah it has few uses
it sucks for me cause im stopping an interval then starting it again so what ends up happening is stop start stop start
Only took five months for the bug to be found
im good at that. my only 3 merged prs were bugs(&adjacent) I found while trying to modify plugins 
Looks like this is because it adds a new onChangeListener for every useSettings and I call that in my renderTimestamp function
But I may as well just use settings.store instead since it rerenders every second
@dull magnet since you reviewed it can you chime in 
pretty much everything there down was us talking about it
we found the problematic code we just dont know what way would fix it without unintended side effects
most basic working example is shikicodeblock
if you add a log here you'll see it triggers twice when you change the setting
I don't think there should be side effects as the point of it is just to call the main setting's hooks if any nested properties update, and with length > 2 it's catching the main setting path
is there a better way of adding a CSP exception required by a plugin besides VencordNative.csp.requestAddOverride(), or is that the intended approach?
if it's meant to be an official plugin, just add it directly to the object
otherwise you can make a native.ts file and import the Csp object from there and add to it
awesome, thanks
Found a less cursed way todo it
I feel like it would be more descriptive to write out every single colour format and it's syntax, as "almost any" is very broad
And the description text doesn't need to repeat the title text
I'd recommend a color picker if you don't have any special input requirements
they look nice and easy to use
Horror
you could also just add the hashtag for the user instead of warning about it
?
Nah
Shouldn't Nsfw be uppercsse 
gotta make a custom component for that
I was joking
I'm not. do it
Yeah, but it causes this weird syntax issues so we don’t do that
I think you could make it a bit more clear by just saying you can use any CSS colour
in my smyn pr I just mention the formats "hex(a), rgb(a), hsl(a)"
Then the addendum about the hashtag isn't necessary
Technically oklch is also supported
And oklab
Soo…
what's that
is it just css colour
It’s the best CSS colour
a laboratory that's not bad nor amazing, it's just okay
an oklab
right
I meant is the colour you enter into the plugin just used as css colour 😭
hsl, hwb, lab, lch, oklch, lwb😭
It’s the overwrite for the default colour incase you don’t want it to be red
rgb(a) also
If you wanna get nerdy kinda yeag
Using inches and milimeters as the CSS unit for my personal plugin
what kinda answer is that 😭
do you <Element color={thing} /> or do you parse it manually from js
if it's the former, just write something like
Supports all web colour formats (hex, rgb, hsl, etc)
That would work
if someone is smart enough to know what an oklab is they will also know that web colours includes oklab

normal users will just use hex
What are even the chances of this getting accepted too #1256395889354997771 because yes, it can be done with CSS but the CSS requires that you use :has and it’s laggy as shit
Has is optimizable to some degree if you make your selectors simple enough
(it's not fun though)
Lil vro ive tried
Plus I prefer the plug-in anyways since all the customization abilities it gives you
Plus, it works in places where the snippet doesn’t work
Eg nsfw stages, and threads
You can also toggle it where you wanted to show and were you don’t
Also small question; what exactly does wrapping something in a ErrorBoundary do?… cause a saw Saden did it here…
https://github.com/Vendicated/Vencord/blob/main/src/plugins/consoleJanitor/index.tsx#L58
Looking at the ErrorBoundary source code it looks to catch errors and display the error as part of the UI
I mean, yeah I guessed that when I looked at the code… I’m just asking is it necessary?
Not really if you're using Vencord components, but if you're using something extra like the rich chat editor it makes it easier to pass proper props without crashing your entire app every time
(Also users wont know how to stop crashes themselves, it's better ux to show an error box)
if your component throws an error while it's rendering it will crash the entire app and show the discord crash screen
if you wrap your component on an error boundary, the error boundary will catch the error
if your component can in any way error, you need an error boundary
but it's optional for things like modals because the crash recovery plugin can recover those by just closing the modal
why are you using a text input instead of a colour picker for this?
instead of a whole settings thing give it a class you can easily target
??
i use 7 spaces indentation
bump
there's an assets upload issue thread
ah thanks
spent half an hour trying to figure out why component isnt working
finally realize I was matching the component below the one I actually wanted
agony
-# (no this is not what it will look like I was just trying to get the upper badge to work)
They can
Make a native.ts file and import the stuff
hä why are u assigning twice
it's just gonna use the second
image src includes connect src
if you wanted to do image src and media src
would you do like ImageSrc + ' ' + MediaSrc
or whatever
they're arrays
Ohh, I see that now… how did I not notice that before??
I might be a bit stupid
[...ImageSrc, ...ConnectSrc]
(doesnt matter anyways since imagesrc contains connectsrc)
/*
* Vencord, a Discord client mod
* Copyright (c) 2025 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { ConnectSrc, CspPolicies } from "@main/csp";
CspPolicies["files.catbox.moe/"] = [...ConnectSrc, "media-src"];
reinject, restart
not sure about path, i just do
pnpm run build && pnpm run inject --branch canary
working thanks
nothing like having wumpus vibe to the weeknd
/*
* Vencord, a Discord client mod
* Copyright (c) 2025 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { definePluginSettings } from "@api/Settings";
import definePlugin, { OptionType } from "@utils/types";
const settings = definePluginSettings({
source: {
description: "Source to replace the vibing mp3 with",
type: OptionType.STRING,
default: "https://files.catbox.moe/udwvp9.mp3",
restartNeeded: false
}
});
export default definePlugin({
name: "Weeknd Wumpus",
description: "have wumpus vibe to our lord and savior, The Weeknd",
authors: [{ id: 1003477997728313405n, name: "Death" }],
settings,
patches: [
{
find: ".navigator.mediaDevices.enumerateDevices()",
replacement: [{
match: /\.src=(\i)/,
replace: ".src=this.name==='vibing_wumpus'?$self.settings.store.source:$1"
}]
}
]
});
You don't need to reinject, just build and full restart, not reload
Was about to say
Is there any documentation on functions? I'm wondering if there's a way to detect if a current guild is in a folder and to collapse the folder
Stores.UserSettingsProtoStore.getGuildFolders() has a list of folders and the guild ids within them, could probably go off that
you can get folder information using the SortedGuildStore
Then you just need to find what the onClick does when you toggle a folder
Even better
specifically
findStore("SortedGuildStore").getGuildFolders() would return all your folders and whats in them
not sure exactly how youd do the expanding/collapsing though, never looked into that
Alright, thank you
usually youll find a store for like everything, very rarely do you have to go through usersettings
Yeah I was looking through them, just didn't see that one
Guess it would've been smart to look in BetterFolders
is there some alternative localstorage
like hidden vencord config thing
i don't want to add more info to localstorage
why
credential storage
should clarify it's a userplugin and not for PR so i really don't care if stuff is in plaintext
Allows access to simple encryption and decryption of strings for storage on the local machine.
i mean like an alternative way to store it
what...
not encryption-type stuff, i already saw the methods on DiscordNative
safeStorage is what you want
am i stupid
like Datastore?
block it how? cause in the pr I'm working on one of the features is disabling the popup by the user modal.
I'd want to basically remove all references to quests
all of it
as if quests never even existed
well not wording but I mean functionally
idc if other unrelated UI stuff refers to it
thinking we could merge it with the yt ad block and create a generic upsell / ad blocker
maybe
could have a setting for blocking yt, one for blocking quests and perhaps one for blocking other types of upsells such as nitro etc
also, imo: "just use css" isn't really a good solution imo. few people know how to use or find the CSS for this stuff.
I imagine basically only power users and ppl in here would be able to do that then
which isn't great
if we wanna go the css route we should maybe have vencord ship with a couple prewritten CSS files you can enable / disable
bc expecting ppl to do it themselves is a bit much
and at that point it may be more thorough to go the JS route to avoid having to maintain the CSS
Well, the #🎨-css-snippets channel is there for a reason tbh
well that still means only ppl here would be able to use it
we shouldn't require ppl join a server for ts
Make it a github import and you'll find it on there as well
I hypothesize it may be the easiest if we somehow modify the code making the REST calls to nullify the data related to quests.
we wouldn't need to go anywhere else then, if we just cut out the quests data and make the client think there weren't any then we wouldn't need to inject into any UI
so no fiddling with css class names changing, or the components themselves changing, and if we do need to fiddle it'd be in a couple rest calls at most, which propagates throughout the client
though idt they would be changing the API layout on that much so fiddling would be very rare
I do agree that css has a shorter reach compared to an official plugin/feature, but I would personally still use the former since it's what I'm most familiar with
As for the other users, a post on the snippet channel, github import and uploading the theme to the BD website would be enough
that still doesn't feel very accessible
and very power user centric
Joey Mainstream doesn't even know what a github is
also tbh I think CSS would be more work than the REST data modification
But they use a discord client modification, and if it's Vencord there is a direct link to the BD website themes section
It might be, yeah
even as a power user it's just super inconvenient too
You could also add a Flux interceptor to modify quest related events, no patches required then
it'd be a whack a mole too
you think you got them all and bam a new one pops up or 1 of the bunch had the class name changed
the privacy settings inside your discord settings:
disable all of this shit and activity panel, quests, a lot of stuff just disappears except if you specifically look for it
I would have yeeted quests in Anammox, if I had ever seen any
is there an example somewhere of how to add domains to csp with my plugin?
Alr disabled the quests stuff. Still getting them
they still appear in the discoveries menu, if you mean something else restart or give it a bit, might take a while for discord to not recommend you anything due to outdated data or something like that
Have had it disabled since quests came out
I still get them on ppls profiles n stuff
On activity feed etc
I don't see them at all, so maybe it could be region based?
any way to access the native ping sound player or is the best method creating an audio element and playing that? I tried break pointing a message being made while it pinged me but god I got like 1000 functions calls in before I gave up 😭
Have a look at the preview button in the notification sound settings, probably easier
debug(HTMLAudioElement.prototype.play) yields a nicer call stack
bruh I looked through all the settings and couldnt find any but forgot you had to hover to see them...
ok note to self
dont fuck with SoundpackStore
or you'll brick your discord
had to delete the key from local storage after accidentally modifying it
💀
I don't think man was meant to hijack the ping sound to use it elsewhere... guess ill look into the element method
OMG
that was so easy
lol
const Test = findByCodeLazy("Unable to find sound for pack name:");
Test("message1")
message1, deafen, undeafen, mute, unmute, disconnect, ptt_start, ptt_stop, user_join, user_leave, user_moved, call_calling, call_ringing, stream_started, stream_ended, stream_user_joined, stream_user_left, activity_launch, activity_end, activity_user_join, activity_user_left, reconnect
🤔
damn do NOT mess with SoundpackStore fr
just had to remove my discord folder from appdata local and roaming
client kept freezing on boot
nvm looks like breakpointing a specific part of the code also bricks your client
fun
oh dope it's not limited to those sounds
activity_end, activity_launch, activity_user_join, activity_user_left, asmr_message1, bit_message1, bop_message1, call_calling, call_ringing, call_ringing_beat, call_ringing_snow_halation, call_ringing_snowsgiving, clip_error, clip_save, ddr-down, ddr-left, ddr-right, ddr-up, deafen, discodo, disconnect, ducky_message1, halloween_call_calling, halloween_call_ringing, halloween_deafen, halloween_defean, halloween_disconnect, halloween_message1, halloween_mute, halloween_undeafen, halloween_undefean, halloween_unmute, halloween_user_join, halloween_user_leave, highfive_clap, highfive_whistle, human_man, lofi_message1, mention1, mention2, mention3, message1, message2, message3, mute, overlayunlock, poggermode_achievement_unlock, poggermode_applause, poggermode_enabled, poggermode_message_send, ptt_start, ptt_stop, reconnect, robot_man, stage_waiting, stream_ended, stream_started, stream_user_joined, stream_user_left, success, undeafen, unmute, user_join, user_leave, user_moved, vibing_wumpus, voice_filter_loopback_off, voice_filter_loopback_on, voice_filter_off, voice_filter_on, voice_filter_swap, winter_call_calling, winter_call_ringing, winter_deafen, winter_disconnect, winter_mute, winter_undeafen, winter_unmute, winter_user_join, winter_user_leave
aintnoway
{
find: "could not play audio",
replacement: {
match: /(\i\(\d+\)\(".\/".concat\(this.name,".mp3"\)\))/,
replace: "this.name.startsWith('https')?this.name:$1"
}
},
that easy to get it to play urls. gotta host it on an allowed domain tho
is there a helper function built in for checking if urls meet the csp 🤔
nop you'd have to make a native function to get the CSP
yes there is don't listen to nina 😭
look at VencordNative
i will document CSP
well?
anywhere else 🤔
Did you build this or
yeah it's gonna be part of my quest plugin pr
I like quests so im adding enhancements.
Le pog
was all pretty easy to patch out
Did you consider the option of nullifying the quest data
thats fetching quests
it blocks the request on startup
so quest store never gets populated
Good
if you try to go to quests tab it's blank
Very nice
you mentioned something about activity quests? I tried looking around my servers but couldnt see anything about that
Oh uh yeah so if you go to the friends tab
The right hand list of users' shenanigans
It has quests there often
And they're quite in your face
I see. ill have to try to see if I can get it to work with an alt
if you see one take a pic and ping me so i know what to look for
May be hard to bc it kinda requires friends on the account
Enough for some to have played a game that has a quest related to it
@quick zephyr
if you see quests anywhere else in the client lmk
naisu
In the memberlist
does vencord have some easy way to open a modal with inputs
foudn @utils/modal thanks bye
cooking?
Hey just a question, have the source vencord version etc.
Why can it not find the modules?
no idea, need more info like the path this file is in for example
and what its called
and the error itself
Cannot find module '@utils/constants / @utils/types' or its corresponding type declarations.ts(2307)
C:\Users\caly\Documents\Vencord\src\userplugins\testPlugin
and what is this file called
index.ts
@quick zephyr Why did you react with an X? Is that the wrong filename + extension? I got this info from the wiki.
I'm not familiar enough with ts to know for sure but all the files ive ever seen and worked with in the repo have been tsx
also I expected james to keep talking and didnt want to interupt which is why I reacted lol sorry
i guess you opened a plugin folder instead of the root vencord directory
C:\Users\caly\Documents\Vencord\src\userplugins\testPlugin
Yeah but whats the opened the folder in vscode
Yeah open the vencord folder
for the life of me i cannot figure out how to get an external webpage to embed
Refused to load plugin data from 'https://www.example.com/' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'object-src' was not explicitly set, so 'default-src' is used as a fallback.
Add the header then duh
Add the domain to csp via native
How would I go about making a plugin, that add a slash command and when ran, it sends a message from your user?
look at how similar plugins do it
VencordNative.csp.requestAddOverride("https://isle.pizza", ["default-src", "object-src"], "LegoIsland"); like this?
thats more of a dynamic way, you probably want to enable it without user interaction since its required for your plugin to work
import { CspPolicies } from "@main/csp"
// native.ts
CspPolicies["isle.pizza"] = ["default-src", "object-src"]
still doesn't seem to work
putting it in native.ts
did you restart
Any you recommend to look at for my case?
spotify share commands
How would I get every guild channel's name?
ChannelStore
So like findByPropsLazy("getChannels"); or something like that?
No
Huh then how?
why does nobody search the code of vencord its like a single keybind
search ChannelStore
Which code tho
ts is for regular typescript files
tsx is for typescript files that also contain jsx, especially for react
in regular ts files you cant do this for example:
const element = <div>hi</div>;
works in tsx though
they are pretty much completely interchangable though (except if you use extensions on imports but who does that...)
thats why if you search enough youll find plugins that just use .ts files, they just dont need react and so have no reason to use .tsx
I have a question.
Is it possible to export the entire dom and HTML discord?
So that it is easier to view the dom and HTML without having to use Ctrl + Shift + I?
I am asking because I need to pass this information on to someone else and for my own use.
What is the house may I ask?
I apologize, English is not my native language and I wrote this without thinking.
It might be better to write it in your native language then we can use a translator to understand it better for future reference.
#rules says english&german only
What if they speak German?
then they would know english
anyway they're a malware skid so i'm gonna revoke their access
ok finally finished rewrite. now to daily drive it for a bit to make sure nothing breaks :D
Looking forward to it!
oh my god this is so cute
@quick zephyr can you link me the pr if/when you have it
sure
im having this issue where if you hover over the button the pill slightly bumps. but it also happens on the DMs button. and it doesnt happen for guild pills. so im wondering if this is a me issue or a discord issue. can someone try hovering a guild and see if the pill "bumps". what I mean by that is that it doesnt just animate equally but also shifts by like a pixel. and then try the same thing with the dms button and see if it happens there?
well would you look at that I change addServerListElement(ServerListRenderPosition.Above, ... to addServerListElement(ServerListRenderPosition.In, ... and it doesn't bump anymore. Why is this platform so ass making me spend an hour trying to debug CSS.
how interesting if I remove the divider between the server list and the top buttons then all the guild pills bump too
so there's some fucky hackiness being done to account for the divider that doesnt get applied to the pills above it

omg max-height: 20px fixed it bless
for some reason it was animating up to like 20.3px
why dev companion hitting me with "disallowed origin" 😭 man just let me debug a patch please
ok fixed it. agony
"rendered more/less hooks than last time" is despair
has anyone experimented with making a plugin that sends notifications to websockets?
i had this idea to make a plugin that sends notifs to OVRToolKit, so i can see them as popups while in vr
xsoverlay does it
xsoverlay and ovrtoolkit both use the same method, windows notifs, which i really dont like 
well it uses websockets to send data
Might not be the same thing, but my vencord companion fork communicates primarily over web sockets.
looks like it might be conflicting with the hover bar?
why are you even putting a dropdown there
what's that for

put it in a modal or tooltip or whatever
maybe a popout
how do you actually get the proper image url though? im copying image links from that thread and they're all private-user-images links.
edit your message to get the link
still just gives the https://github.com/user-attachments/assets/ syntax
syntax like https://github.com/Vendicated/Vencord/assets/45497981/354220a4-09f3-4c5f-a28e-4b19ca775190
ton of plugins have this
github changed it because people abused this for scams
it makes it seem like that image comes from the repo
can't believe NSA uploaded this file!!! https://github.com/NationalSecurityAgency/ghidra/assets/142212465/095f6a17-47cd-4c58-814e-e04d86b75924
how could they
and this one too wow NSA must love turkey https://github.com/NationalSecurityAgency/ghidra/assets/118324883/b8209e95-1bb7-4c1c-875b-8cceed44c3a1

vee brainrot arc
perhaps
how is it brainrot
it has nothing to do with skibidi toilet if that's what you mean
it's already over for you
I havent seen that guy on my fyp in months. that arc of the internet is over
or well technically it does because this song is what inspired skibidi toilet's name
but like the song predates the toilet and was just appropriated
you use dc that's abt 10x worse
discord server
use discord
I spend money in the shop and do quests, we are not the same
so does vee 
One message removed from a suspended account.
One message removed from a suspended account.
One message removed from a suspended account.
if you want it to be apart of vencord yes you should PR, for reference I suggest looking at other PR's to see where and how people are adding plugins
One message removed from a suspended account.
core plugins are ones that are essential for the client mod to function, most likely yours isn't one of those.
One message removed from a suspended account.
it wont be
though i don't exactly have faith that it would be accepted, due to the fact that themes already serve that purpose already and a similar theming plugin has been rejected before for being overly complex
if it's not going to be it would be better for it to be some unofficial plugin for #1256395889354997771
One message removed from a suspended account.
anyone knows anything about discords new csp
its blocking all my external requests
is there some kinda vencord api to make requests now
im getting failed to fetch
Discord hasn't changed anything (afaik), it's just that vencord stopped deleting the csp
how to edit a channel name? (or find out how to)
manually edit the csp object in a native.ts file
One message removed from a suspended account.
One message removed from a suspended account.
this does request an override
- user generated domains: request override
===== - predefined domains in a userplugin: add to csp with a native.ts
- predefined domains in a plugin: edit the csp.ts file
csp.ts i think
yes
One message removed from a suspended account.
omg thank you
hi i created a plugin and need help making it comply with vencords rules?
contributing.md for official, topic of #1256395889354997771 for there
Followup to #🏥-vencord-support-🏥 message
I'm trying to allow the ListenBrainz API in the CSP for my plugin (it's basically Last.fm). Am I missing something here? I've seen a couple of different ways of allowing a URL but none work. I'm using Vesktop and per docs I'm running pnpm build to update my changes, and the custom plugin is obviously loaded because it's in my logs.
I just added a file called native.ts and it looks like
import { CspPolicies, ConnectSrc } from "@main/csp";
CspPolicies["api.listenbrainz.org"] = ConnectSrc;
CspPolicies["listenbrainz.org"] = ConnectSrc;
// CspPolicies["api.listenbrainz.org"] = ["connect-src"];
// CspPolicies["listenbrainz.org"] = ["connect-src"];
index.tsx:231 Fetch API cannot load https://api.listenbrainz.org/1/user/qouesm/playing-now. Refused to connect because it violates the document's Content Security Policy.
this is correct
I can't confirm that native.ts is even loading but I'm not an expert here
did you fully restart discord (close it completely and reopen)
this is what i did for my userplugin
native.ts:
/*
* Vencord, a Discord client mod
* Copyright (c) 2025 sadan and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { ConnectSrc, CspPolicies } from "@main/csp";
CspPolicies["https://api.urbandictionary.com"] = ConnectSrc;
I've been refreshing but I just killed my Vesktop process and started it again to no avail
native wont ever show up there because native is part of the electron node process not the browser render process
so there is no point in including it there
I was suspecting something like that because I couldn't find any others
i really need to revive my native import pr
wrong reply
have you tried adding https://
no errors during build?
nope
you also have to restart watch after adding a new native file for it to pick it up
oh
maybe a pnpm build --watch
if you were never using pnpm watch or pnpm build --watch it doesn't matter
it's chill
but yea no dice with this current config
wait
that's a different url
hold on let me add that one
I don't know when that changed
Ok there's a third API I'm calling now that I'm gonna add but I had to kill Vesktop, not refresh, to get the 2nd one to take
oh jeez
so they show up now
but one of the URL's is like a specific archive.org server
so I've added https://archive.org but can I wildcard that URL? because that's gonna switch all the time surely
I see wildcards in the others, I'll try
It works!
for the record CspPolicies["https://*.*.archive.org"] = ConnectSrc; does not work but CspPolicies["https://*.archive.org"] = ConnectSrc; does
So let me post my solution
Just added a native.ts with the following:
import { CspPolicies, ConnectSrc } from "@main/csp";
CspPolicies["https://api.listenbrainz.org"] = ConnectSrc;
CspPolicies["https://musicbrainz.org"] = ConnectSrc;
CspPolicies["https://coverartarchive.org"] = ConnectSrc;
CspPolicies["https://archive.org"] = ConnectSrc;
CspPolicies["https://*.archive.org"] = ConnectSrc;
https://github.com/qouesm/vencord-listenbrainz-rpc/blob/main/native.ts
Thanks guys
why does it need to fetch from archive.org 😭
cause of the https://coverartarchive.org/ API which is a project between archive.org and musicbrainz
the images seem to be hosted on archive.org itself
Hi I have a question regarding my plugin idea.
I want to make plugin where I can click a button which would bring up popup with all discord badges and you could select few of them (let's say Early Supporter Badge) and when you'll click Search, it will show all people in the server that you're currently in, which have the badge / badges that you selected.
Would it be possible to make and how hard could it?
Thanks
it's not even possible cuz you can't easily get all members of a server
why not
just online members if all members is not possible
equally impossible
You'd have to continuously fetch parts of the memberlist, which is limited to 300 members per query
This could take really long for servers with thousands of members, or get you banned
like on whole discord?
you'd also need access to a channel with all members, which isn't always the case if you have to ex. verify first
which is why i boiled it down to it being impossible
Oh true 😭
as I said it doesn't have to be all members
Yeah, since it technically is considered api abuse
lol
so how could I get members with nice badges
as I'm a badge goblin and going manually through 100's of member profiles is quite annoying
just to find 1
as i said, online members wouldn't be possible in many scenarios either
try not being a badge goblin :D
In economics and business decision-making, a sunk cost (also known as retrospective cost) is a cost that has already been incurred and cannot be recovered. Sunk costs are contrasted with prospective costs, which are future costs that may be avoided if action is taken. In other words, a sunk cost is a sum paid in the past that is no longer releva...
yep that's me
why's everything so fricking sensitive nowadays
youtube is getting blocked with normal words
just say it's total dog shit and whoever made the decision to do it should get fired
easy 
so how could i get list with users with good badges
uhm why exactly?
Why do u want to know which people have good badges
I'm a badge goblin
.
Nah what does that mean 😭
Do you keep a spreadsheet or something
nah just dm people who's profile meets the criteria
Are you blackmailing these people perchance /jk
selling accounts is against the tos and rules of this server, please stop taking about it here
modding discord with 3rd party clients is also against discord's tos
vban @simple sandal asking for help with buying accounts
Done! 
Banned miki_official (@simple sandal)

nice badges @dull magnet can i buy ur account for 1 dollar
nice badges @austere mauve can i buy ur account for 1 dollar
nice badges @hoary pilot can i buy ur account for 1 dollar
nice badges @swift delta can i buy ur account for 1 dollar
nice badges @carmine spade can i buy ur account for 1 dollar
Bro messed up the joke
Laugh at this person
sure my password is Anime1234!
she wasn't lying
counteroffer i will buy it for 50p
Haiii hii hewwo, so basically I'm making custom plugin that integrates my rotary encoder on rpi2040 with discord to change volume of specific user
I tried changing localstore directly but nothing happened, so I guess there must be some function I need to call (or Im dumb and I did it incorrectly
) but I cannot find anything related to changing volume of a specific user (and muting specific user) in src code
have you tried looking at at the volume slider for users
You mean manipulating the component somehow?
no
finding the component and seeing what it does when the slider is changed
I can try tmrw cuz im in bed rn
if you can't find it, i will and send it to you in a bit
Oke
So i guess you'll be faster than me getting up from bed and turning on pc lmao
Ty in advance
discord is made with react
you can use react devtools to inspect components and see their inner workings
you can see handlers like onClick, onDrag, etc
you need to find a component that does what you want, inspect it with react devtools, then check its handlers to see how it does it
then you can just replicate this in your own code
@flat summit the volume is passed through this function first, then set with wreq(846027).Z.setLocalVolume(userId, transofrmedVolume)
make a proper find for both functions
(i dont think vencord finds AudioActionCreators)
ok i'm too dumb to understand how vencord works, going back to working with microelectronics lmao
i have suspicions that it would be easier for me to find it in ram using cheat engine and patching it like this 💀
the moment when c++ guy touches ts/js
When I started working on my plugin I had no idea how it worked. Took about a week of pestering people here with questions and checking how other plugins did things to figure it all out.
i mean i got handed out which function i should use, i also found getVolume function using react components and i guess i could do the same for muting functionality.
Though i have no idea how to extract it from webpack chunk or reference it or do anything to it at all
And I don't have patience to dig thru vencord for a week especially because it was supposed to be shrimple plugin to change volume of a specific user with rotary encoder
It always starts as a shrimple plugin. i just wanted a shortcut to quests... then you add and add and add and suddenly a week has gone by 
you know how to inspect the components and find the code?
i mean i dont even need any other functionality
I'm building "sound panel" cuz im lazy shit and i don't want to open windows volume mixer every time i want to change volume of an app, especially when I'm playing rhythm games like chunnithm, piu or sound voltex where app can crash when minimizing and i have keyboard put under monitor cuz those games have custom controllers which take up desk space
I have 8 rotary encoders communicating with driver on com port and everything works perfectly i just need one encoder for one annoying user in our discord as a meme and if i won't find out how to do it, i'll just mute him by hand if really needed so there's no additional stuff that can be added to functionality of this lmao
or monitor rotated by 90deg
how tf do you enable the bug icon/dev icon where the flux events are shown
dev mode enabled, react tools on, built with dev flag, dont see a relevant plugin, what am I missing 😭
iirc there is an toggle in the settings for the experiments plugin to enable it
yeah there it is
why on earth is that part of the experiments plugin
it's super relevant to plugin development 😭

I am actually inclined to agree it should either be part of the companion plug-in or a setting toggle in the main Vencord setting page
Vencord.Webpack.Common.FluxDispatcher.dispatch({
type: "AUDIO_TOGGLE_LOCAL_MUTE",
context: "default",
userId: "<their_id>"
});
just dispatching this is enough. no function needed
once to mute, again to unmute
syntax will be different in a jsx file. ^ thats for dev console if you want to test it
It would fit below the "Enable React Developer Tools" button on the Vencord tab in the settings
thats where I expected it to be lol
Inclined to agree, but it is what is 
Ok so one part done I got the mute function (tysm
) , now figuring out volume change lmao
Clk is clockwise this is bound to f15
Dt I cclockwise this is bound to f14
Sw is switch - and we have this one (thank you again)
Muting itself is useful tho lmao
Vencord.Webpack.Common.FluxDispatcher.dispatch({
type: "AUDIO_SET_LOCAL_VOLUME",
context: "default",
userId: "their_id",
volume: some_float
});
could not tell you why but 100 equates to 100% in the client. 0 equates to 0%. but 1 equates to 19% and 2 equates to 25%
some fuckass scaling
can test it in dev console again to play around with values
if you wanna inspect events like this yourself you can do this and then go to the dispatcher tab. any time you do something in discord it'll probably show up there. then you can copy the data format to forge events. the events can be really fast and hard to track so after you do your thing you can click the checkbox to pause displaying new events to make finding the one you just made easier
-# oops sorry for ping if I did
its because humans dont perceive sound linearly so every time you handle volume you usually want a logarithmic scale
exactly
@swift delta dont nerd me nerd
It would not.
AFAIK experiments work by setting is developer to true or something.
Reverse engineering Blink and working around the optimization stuff that V8 most definitely is something you need to thoroughly consider
Also, JS is a garbage collected language with very few fixed pointers so they can move around in RAM
im not writing whole stuff in js, im not insane
the driver and firmware is in low level c++

the discord plugin for connection with one of 8 rotary encoders is in TypeScript, like vencord
I thought you were talking about your plugin to change the volume of the users 😭
yes this too
Basically it works like that
I have a board with 8 rotary encoders
I want 1 of 8 rotary encoders to be bound to changing volume and muting one annoying user on discord.
The rest is bound to changing volume of specific games/programs
Firmware sends commands on COM5 channel, driver interprets it and changes volume of software/game on pc
For discord I made workaround and connected to HID, and I'm sending keyboard strokes (F13,F14,F15)
In discord my plugin adds keyDown event and I needed to know how do I implement functionality mentioned above
Why are you sending keyboard strokes? You can just connect with a websocket.
yes but i was lazy
lmao
also why should i create websocket for such simple thing
and on top of that
it's bound to non-existent keys anyways
ok i have everything i wanted except for one thing
when i change volume it randomly spams in console with something like this
23:24:33.934 > [RTCConnection(undefined, default)] Media sink wants: {"any":100}
23:24:34.476 > F14 45
23:24:34.477 > [RTCConnection(undefined, default)] Media sink wants: {"85256":0,"any":100}
23:24:35.093 > F14 50
23:24:35.094 > [RTCConnection(undefined, default)] Media sink wants: {"any":100}
23:24:35.140 > F14 55
23:24:35.141 > [RTCConnection(undefined, default)] Media sink wants: {"85256":0,"any":100}
23:24:35.709 > F14 60
23:24:35.710 > [RTCConnection(undefined, default)] Media sink wants: {"any":100}
23:24:36.093 > F14 65
23:24:36.094 > [RTCConnection(undefined, default)] Media sink wants: {"85256":0,"any":100}
23:24:36.364 > F14 70
23:24:36.365 > [RTCConnection(undefined, default)] Media sink wants: {"any":100}
23:24:36.397 > F14 75
23:24:36.398 > [RTCConnection(undefined, default)] Media sink wants: {"85256":0,"any":100}
23:24:36.692 > F14 80
23:24:36.694 > [RTCConnection(undefined, default)] Media sink wants: {"any":100}
23:24:36.765 > F14 85
23:24:36.766 > [RTCConnection(undefined, default)] Media sink wants: {"85256":0,"any":100}
and user mute state flickers between toggled off/on
even tho f13/f14 doesn't mute an user
Which console?
both terminal and dev tools
so basically the same thing
it redirects me to this
That's discord's generic logger function. Just breakpoint it if you want to know what's calling it.
makes sense
still, when i change volume mute state flickers for some reason
tried adding debounce, nothing changed
maybe if i raise debounce in firmware
fixed a bug with double inputs but nothing changed anyways lmao
I checked, it is a patch, I just think it would fit better on the main vencord page still anyways lol
nice
What's the best place to find decent documentation on what internal functions are called? In the plugin im making I want to be able to autimatically mute and un-mute DirectMessage channels, but I'm not sure what function it is I need to call. This is what I've tried but it does not seem to work:
// mute DM notif for N seconds
if (!msg.guild_id) {
// DM case
const CID = msg.channel_id;
// create a mute config that ends in N seconds
const muteConfig = {
muted: true,
muteConfig: {
endTime: Date.now() + settings.store.muteTime * 1000 // ms
}
};
NotificationSettings.updateChannelNotificationSettings(CID, muteConfig);
}
// empty case for servers because they don't need support
else {
return;
}
My only experience with coding things related to discord is making discord bots, so it's also possible I've made a logic error somewhere, but it builds and injects without any errors, and the plugin does show up in the settings
It's this, it's higher up in the code
const NotificationSettings = findByProps(
"updateChannelNotificationSettings",
"updateUserNotificationSettings"
);
No, but I am using AI generated docs, because I am wildly lost
this is complete bullshit
stop asking ai
I suspected so
also what you're making is already a stock feature, no?
almost, but I want to automate it.
personal: || I have autism, so repeated loud noises is very difficult for me, and I have some friends who insist on writing the same sentence in like 5 different messages ||
so I want to be able to automatically mute a DM channel for 30 seconds after I get a message so I don't get spammed with loud noises
vp OnePing
If unread messages are sent by a user in DMs multiple times, you'll only receive one audio ping. Read the messages to reset the limit
ProffDea
That's basically what I need; I'll rewrite some of it to fit my needs. Thank you very much :3
But my original question still remains, where do I find the docs for all the functions? The vencord docs just include a guide on how to use git; but not anything about actually making plugins beyond the TS boilerplate (unless I've missed something). These are the docs I used: https://docs.vencord.dev/plugins/ are they the wrong ones?
And for the sake of clarity, these are the docs I tried summarizing: https://discord.com/developers/docs/reference
It's very often a great tool and most of my pupils use it to skim documentation. It's practically a requirement for some of the special needs kids we teach at my school. You probably shouldn't be so quick to judge people for using a tool you don't like :I
yes when it's based on real docs it can summarise
but asking it to hallucinate up "docs" for a proprietary undocumented codebase is just nonsense
you dont, almost all functions are completely undocumented, its discords code after all
you have to find them in the code yourself
discord.dev docs are only for the bot api
nothing else
it doesnt include functions, a lot of api routes only usable by bots and missing a ton of other api routes
https://discord.food is a good resource if you want to find undocumented api routes/objects
There's an excellent study by UFMG in Brazil 🇧🇷 [https://arxiv.org/pdf/2408.14007] regarding LLMs for the purpose of codebase documentation. It's a great read if you are interested, it's only 7 pages; they only test Javadocs though, but the point still stands. The output usually isn't prod ready, but it's a decent step
bummer, but thank you :)
there isnt much to document in the vencord codebase, if you need info you can look through other vencord plugins
most of the work making a plugin goes into looking through the discord code to see what you need to call/modify, then writing patches or ts/react
the vencord side documentation for this would quite literally just be close to "matches find a webpack module, finds are regex finds that will be replaced with replace"
just drop it, this is a pointless discussion
don't come here with ai garbage or you will be kicked out of this channel, like #📖-info states
Kevin would be offended
Kevin isn't ai
What is he then





