Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a94787a9f3 | ||
|
368d2bcdbb | ||
|
bc46bfa467 | ||
|
dab48288a8 | ||
|
9aef97c771 | ||
|
9d62dec6b9 | ||
|
6bf6583e7d | ||
|
5219fb700f | ||
|
184c03b28e | ||
|
ec091a7959 | ||
|
89a6c575c9 |
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "vencord",
|
"name": "vencord",
|
||||||
"private": "true",
|
"private": "true",
|
||||||
"version": "1.2.4",
|
"version": "1.2.5",
|
||||||
"description": "The cutest Discord client mod",
|
"description": "The cutest Discord client mod",
|
||||||
"homepage": "https://github.com/Vendicated/Vencord#readme",
|
"homepage": "https://github.com/Vendicated/Vencord#readme",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
import { generateId } from "@api/Commands";
|
import { generateId } from "@api/Commands";
|
||||||
import { useSettings } from "@api/Settings";
|
import { useSettings } from "@api/Settings";
|
||||||
|
import { disableStyle, enableStyle } from "@api/Styles";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Flex } from "@components/Flex";
|
import { Flex } from "@components/Flex";
|
||||||
import { proxyLazy } from "@utils/lazy";
|
import { proxyLazy } from "@utils/lazy";
|
||||||
@ -40,6 +41,7 @@ import {
|
|||||||
SettingSliderComponent,
|
SettingSliderComponent,
|
||||||
SettingTextComponent
|
SettingTextComponent
|
||||||
} from "./components";
|
} from "./components";
|
||||||
|
import hideBotTagStyle from "./userPopoutHideBotTag.css?managed";
|
||||||
|
|
||||||
const UserSummaryItem = LazyComponent(() => findByCode("defaultRenderUser", "showDefaultAvatarsForNullUsers"));
|
const UserSummaryItem = LazyComponent(() => findByCode("defaultRenderUser", "showDefaultAvatarsForNullUsers"));
|
||||||
const AvatarStyles = findByPropsLazy("moreUsers", "emptyUser", "avatarContainer", "clickableAvatar");
|
const AvatarStyles = findByPropsLazy("moreUsers", "emptyUser", "avatarContainer", "clickableAvatar");
|
||||||
@ -50,11 +52,12 @@ interface PluginModalProps extends ModalProps {
|
|||||||
onRestartNeeded(): void;
|
onRestartNeeded(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** To stop discord making unwanted requests... */
|
function makeDummyUser(user: { username: string; id?: string; avatar?: string; }) {
|
||||||
function makeDummyUser(user: { name: string, id: BigInt; }) {
|
|
||||||
const newUser = new UserRecord({
|
const newUser = new UserRecord({
|
||||||
username: user.name,
|
username: user.username,
|
||||||
id: generateId(),
|
id: user.id ?? generateId(),
|
||||||
|
avatar: user.avatar,
|
||||||
|
/** To stop discord making unwanted requests... */
|
||||||
bot: true,
|
bot: true,
|
||||||
});
|
});
|
||||||
FluxDispatcher.dispatch({
|
FluxDispatcher.dispatch({
|
||||||
@ -89,14 +92,27 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
|
|||||||
const hasSettings = Boolean(pluginSettings && plugin.options);
|
const hasSettings = Boolean(pluginSettings && plugin.options);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
enableStyle(hideBotTagStyle);
|
||||||
|
|
||||||
|
let originalUser: User;
|
||||||
(async () => {
|
(async () => {
|
||||||
for (const user of plugin.authors.slice(0, 6)) {
|
for (const user of plugin.authors.slice(0, 6)) {
|
||||||
const author = user.id
|
const author = user.id
|
||||||
? await UserUtils.fetchUser(`${user.id}`).catch(() => makeDummyUser(user))
|
? await UserUtils.fetchUser(`${user.id}`)
|
||||||
: makeDummyUser(user);
|
// only show name & pfp and no actions so users cannot harass plugin devs for support (send dms, add as friend, etc)
|
||||||
|
.then(u => (originalUser = u, makeDummyUser(u)))
|
||||||
|
.catch(() => makeDummyUser({ username: user.name }))
|
||||||
|
: makeDummyUser({ username: user.name });
|
||||||
|
|
||||||
setAuthors(a => [...a, author]);
|
setAuthors(a => [...a, author]);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
disableStyle(hideBotTagStyle);
|
||||||
|
if (originalUser)
|
||||||
|
FluxDispatcher.dispatch({ type: "USER_UPDATE", user: originalUser });
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
async function saveAndClose() {
|
async function saveAndClose() {
|
||||||
|
3
src/components/PluginSettings/userPopoutHideBotTag.css
Normal file
3
src/components/PluginSettings/userPopoutHideBotTag.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[class|="userPopoutOuter"] [class*="botTag"] {
|
||||||
|
display: none;
|
||||||
|
}
|
@ -24,15 +24,13 @@ import { Heart } from "@components/Heart";
|
|||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
|
import { isPluginDev } from "@utils/misc";
|
||||||
import { closeModal, Modals, openModal } from "@utils/modal";
|
import { closeModal, Modals, openModal } from "@utils/modal";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { Forms, Toasts } from "@webpack/common";
|
import { Forms, Toasts } from "@webpack/common";
|
||||||
|
|
||||||
const CONTRIBUTOR_BADGE = "https://cdn.discordapp.com/attachments/1033680203433660458/1092089947126780035/favicon.png";
|
const CONTRIBUTOR_BADGE = "https://cdn.discordapp.com/attachments/1033680203433660458/1092089947126780035/favicon.png";
|
||||||
|
|
||||||
/** List of vencord contributor IDs */
|
|
||||||
const contributorIds: string[] = Object.values(Devs).map(d => d.id.toString());
|
|
||||||
|
|
||||||
const ContributorBadge: ProfileBadge = {
|
const ContributorBadge: ProfileBadge = {
|
||||||
description: "Vencord Contributor",
|
description: "Vencord Contributor",
|
||||||
image: CONTRIBUTOR_BADGE,
|
image: CONTRIBUTOR_BADGE,
|
||||||
@ -43,7 +41,7 @@ const ContributorBadge: ProfileBadge = {
|
|||||||
transform: "scale(0.9)" // The image is a bit too big compared to default badges
|
transform: "scale(0.9)" // The image is a bit too big compared to default badges
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
shouldShow: ({ user }) => contributorIds.includes(user.id),
|
shouldShow: ({ user }) => isPluginDev(user.id),
|
||||||
link: "https://github.com/Vendicated/Vencord"
|
link: "https://github.com/Vendicated/Vencord"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ const ClientThemeSettingsProto = proxyLazy(() => searchProtoClass("clientThemeSe
|
|||||||
const USE_EXTERNAL_EMOJIS = 1n << 18n;
|
const USE_EXTERNAL_EMOJIS = 1n << 18n;
|
||||||
const USE_EXTERNAL_STICKERS = 1n << 37n;
|
const USE_EXTERNAL_STICKERS = 1n << 37n;
|
||||||
|
|
||||||
enum EmojiIntentions {
|
const enum EmojiIntentions {
|
||||||
REACTION = 0,
|
REACTION = 0,
|
||||||
STATUS = 1,
|
STATUS = 1,
|
||||||
COMMUNITY_CONTENT = 2,
|
COMMUNITY_CONTENT = 2,
|
||||||
@ -66,6 +66,14 @@ enum EmojiIntentions {
|
|||||||
SOUNDBOARD = 7
|
SOUNDBOARD = 7
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const enum StickerType {
|
||||||
|
PNG = 1,
|
||||||
|
APNG = 2,
|
||||||
|
LOTTIE = 3,
|
||||||
|
// don't think you can even have gif stickers but the docs have it
|
||||||
|
GIF = 4
|
||||||
|
}
|
||||||
|
|
||||||
interface BaseSticker {
|
interface BaseSticker {
|
||||||
available: boolean;
|
available: boolean;
|
||||||
description: string;
|
description: string;
|
||||||
@ -171,6 +179,10 @@ export default definePlugin({
|
|||||||
{
|
{
|
||||||
match: /(&&!\i&&)!(\i)(?=\)return \i\.\i\.DISALLOW_EXTERNAL;)/,
|
match: /(&&!\i&&)!(\i)(?=\)return \i\.\i\.DISALLOW_EXTERNAL;)/,
|
||||||
replace: (_, rest, canUseExternal) => `${rest}(!${canUseExternal}&&(typeof fakeNitroIntention==="undefined"||![${EmojiIntentions.CHAT},${EmojiIntentions.GUILD_STICKER_RELATED_EMOJI}].includes(fakeNitroIntention)))`
|
replace: (_, rest, canUseExternal) => `${rest}(!${canUseExternal}&&(typeof fakeNitroIntention==="undefined"||![${EmojiIntentions.CHAT},${EmojiIntentions.GUILD_STICKER_RELATED_EMOJI}].includes(fakeNitroIntention)))`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
match: /if\(!\i\.available/,
|
||||||
|
replace: m => `${m}&&(typeof fakeNitroIntention==="undefined"||![${EmojiIntentions.CHAT},${EmojiIntentions.GUILD_STICKER_RELATED_EMOJI}].includes(fakeNitroIntention))`
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -542,7 +554,7 @@ export default definePlugin({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
hasPermissionToUseExternalEmojis(channelId: string) {
|
hasPermissionToUseExternalEmojis(channelId: string): boolean {
|
||||||
const channel = ChannelStore.getChannel(channelId);
|
const channel = ChannelStore.getChannel(channelId);
|
||||||
|
|
||||||
if (!channel || channel.isDM() || channel.isGroupDM() || channel.isMultiUserDM()) return true;
|
if (!channel || channel.isDM() || channel.isGroupDM() || channel.isMultiUserDM()) return true;
|
||||||
@ -623,8 +635,9 @@ export default definePlugin({
|
|||||||
},
|
},
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
const settings = Settings.plugins.FakeNitro;
|
const s = settings.store;
|
||||||
if (!settings.enableEmojiBypass && !settings.enableStickerBypass) {
|
|
||||||
|
if (!s.enableEmojiBypass && !s.enableStickerBypass) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,39 +649,37 @@ export default definePlugin({
|
|||||||
const { guildId } = this;
|
const { guildId } = this;
|
||||||
|
|
||||||
stickerBypass: {
|
stickerBypass: {
|
||||||
if (!settings.enableStickerBypass)
|
if (!s.enableStickerBypass)
|
||||||
break stickerBypass;
|
break stickerBypass;
|
||||||
|
|
||||||
const sticker = StickerStore.getStickerById(extra.stickers?.[0]!);
|
const sticker = StickerStore.getStickerById(extra.stickers?.[0]!);
|
||||||
if (!sticker)
|
if (!sticker)
|
||||||
break stickerBypass;
|
break stickerBypass;
|
||||||
|
|
||||||
if (sticker.available !== false && ((this.canUseStickers && this.hasPermissionToUseExternalStickers(channelId)) || (sticker as GuildSticker)?.guild_id === guildId))
|
// Discord Stickers are now free yayyy!! :D
|
||||||
|
if ("pack_id" in sticker)
|
||||||
break stickerBypass;
|
break stickerBypass;
|
||||||
|
|
||||||
let link = this.getStickerLink(sticker.id);
|
const canUseStickers = this.canUseStickers && this.hasPermissionToUseExternalStickers(channelId);
|
||||||
if (sticker.format_type === 2) {
|
if (sticker.available !== false && (canUseStickers || sticker.guild_id === guildId))
|
||||||
|
break stickerBypass;
|
||||||
|
|
||||||
|
const link = this.getStickerLink(sticker.id);
|
||||||
|
if (sticker.format_type === StickerType.APNG) {
|
||||||
this.sendAnimatedSticker(link, sticker.id, channelId);
|
this.sendAnimatedSticker(link, sticker.id, channelId);
|
||||||
return { cancel: true };
|
return { cancel: true };
|
||||||
} else {
|
} else {
|
||||||
if ("pack_id" in sticker) {
|
|
||||||
const packId = sticker.pack_id === "847199849233514549"
|
|
||||||
// Discord moved these stickers into a different pack at some point, but
|
|
||||||
// Distok still uses the old id
|
|
||||||
? "749043879713701898"
|
|
||||||
: sticker.pack_id;
|
|
||||||
|
|
||||||
link = `https://distok.top/stickers/${packId}/${sticker.id}.gif`;
|
|
||||||
}
|
|
||||||
|
|
||||||
extra.stickers!.length = 0;
|
extra.stickers!.length = 0;
|
||||||
messageObj.content += " " + link + `&name=${encodeURIComponent(sticker.name)}`;
|
messageObj.content += ` ${link}&name=${encodeURIComponent(sticker.name)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!this.canUseEmotes || !this.hasPermissionToUseExternalEmojis(channelId)) && settings.enableEmojiBypass) {
|
if (s.enableEmojiBypass) {
|
||||||
|
const canUseEmotes = this.canUseEmotes && this.hasPermissionToUseExternalEmojis(channelId);
|
||||||
|
|
||||||
for (const emoji of messageObj.validNonShortcutEmojis) {
|
for (const emoji of messageObj.validNonShortcutEmojis) {
|
||||||
if (!emoji.require_colons) continue;
|
if (!emoji.require_colons) continue;
|
||||||
|
if (emoji.available !== false && canUseEmotes) continue;
|
||||||
if (emoji.guildId === guildId && !emoji.animated) continue;
|
if (emoji.guildId === guildId && !emoji.animated) continue;
|
||||||
|
|
||||||
const emojiString = `<${emoji.animated ? "a" : ""}:${emoji.originalName || emoji.name}:${emoji.id}>`;
|
const emojiString = `<${emoji.animated ? "a" : ""}:${emoji.originalName || emoji.name}:${emoji.id}>`;
|
||||||
@ -686,23 +697,25 @@ export default definePlugin({
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.preEdit = addPreEditListener((channelId, __, messageObj) => {
|
this.preEdit = addPreEditListener((channelId, __, messageObj) => {
|
||||||
if (this.canUseEmotes && this.hasPermissionToUseExternalEmojis(channelId)) return;
|
if (!s.enableEmojiBypass) return;
|
||||||
|
|
||||||
|
const canUseEmotes = this.canUseEmotes && this.hasPermissionToUseExternalEmojis(channelId);
|
||||||
|
|
||||||
const { guildId } = this;
|
const { guildId } = this;
|
||||||
|
|
||||||
for (const [emojiStr, _, emojiId] of messageObj.content.matchAll(/(?<!\\)<a?:(\w+):(\d+)>/ig)) {
|
messageObj.content = messageObj.content.replace(/(?<!\\)<a?:(?:\w+):(\d+)>/ig, (emojiStr, emojiId, offset, origStr) => {
|
||||||
const emoji = EmojiStore.getCustomEmojiById(emojiId);
|
const emoji = EmojiStore.getCustomEmojiById(emojiId);
|
||||||
if (emoji == null || (emoji.guildId === guildId && !emoji.animated)) continue;
|
if (emoji == null) return emojiStr;
|
||||||
if (!emoji.require_colons) continue;
|
if (!emoji.require_colons) return emojiStr;
|
||||||
|
if (emoji.available !== false && canUseEmotes) return emojiStr;
|
||||||
|
if (emoji.guildId === guildId && !emoji.animated) return emojiStr;
|
||||||
|
|
||||||
const url = emoji.url.replace(/\?size=\d+/, "?" + new URLSearchParams({
|
const url = emoji.url.replace(/\?size=\d+/, "?" + new URLSearchParams({
|
||||||
size: Settings.plugins.FakeNitro.emojiSize,
|
size: Settings.plugins.FakeNitro.emojiSize,
|
||||||
name: encodeURIComponent(emoji.name)
|
name: encodeURIComponent(emoji.name)
|
||||||
}));
|
}));
|
||||||
messageObj.content = messageObj.content.replace(emojiStr, (match, offset, origStr) => {
|
return `${getWordBoundary(origStr, offset - 1)}${url}${getWordBoundary(origStr, offset + emojiStr.length)}`;
|
||||||
return `${getWordBoundary(origStr, offset - 1)}${url}${getWordBoundary(origStr, offset + match.length)}`;
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
@ -72,7 +72,7 @@ enum ActivityFlag {
|
|||||||
INSTANCE = 1 << 0,
|
INSTANCE = 1 << 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
const applicationId = "1043533871037284423";
|
const applicationId = "1108588077900898414";
|
||||||
const placeholderId = "2a96cbd8b46e442fc41c2b86b821562f";
|
const placeholderId = "2a96cbd8b46e442fc41c2b86b821562f";
|
||||||
|
|
||||||
const logger = new Logger("LastFMRichPresence");
|
const logger = new Logger("LastFMRichPresence");
|
||||||
@ -167,6 +167,7 @@ export default definePlugin({
|
|||||||
settings,
|
settings,
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
|
this.updatePresence();
|
||||||
this.updateInterval = setInterval(() => { this.updatePresence(); }, 16000);
|
this.updateInterval = setInterval(() => { this.updatePresence(); }, 16000);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -198,7 +199,7 @@ export default definePlugin({
|
|||||||
|
|
||||||
const trackData = json.recenttracks?.track[0];
|
const trackData = json.recenttracks?.track[0];
|
||||||
|
|
||||||
if (!trackData || !trackData["@attr"]?.nowplaying)
|
if (!trackData?.["@attr"]?.nowplaying)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// why does the json api have xml structure
|
// why does the json api have xml structure
|
||||||
|
105
src/plugins/partyMode.ts
Normal file
105
src/plugins/partyMode.ts
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Vencord, a modification for Discord's desktop app
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { definePluginSettings } from "@api/Settings";
|
||||||
|
import { Devs } from "@utils/constants";
|
||||||
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
|
import { findStoreLazy } from "@webpack";
|
||||||
|
import { GenericStore } from "@webpack/common";
|
||||||
|
|
||||||
|
const PoggerModeSettingsStore: GenericStore = findStoreLazy("PoggermodeSettingsStore");
|
||||||
|
|
||||||
|
const enum Intensity {
|
||||||
|
Normal,
|
||||||
|
Better,
|
||||||
|
ProjectX,
|
||||||
|
}
|
||||||
|
|
||||||
|
const settings = definePluginSettings({
|
||||||
|
superIntensePartyMode: {
|
||||||
|
description: "Party intensity",
|
||||||
|
type: OptionType.SELECT,
|
||||||
|
options: [
|
||||||
|
{ label: "Normal", value: Intensity.Normal, default: true },
|
||||||
|
{ label: "Better", value: Intensity.Better },
|
||||||
|
{ label: "Project X", value: Intensity.ProjectX },
|
||||||
|
],
|
||||||
|
restartNeeded: false,
|
||||||
|
onChange: setSettings
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "Party mode 🎉",
|
||||||
|
description: "Allows you to use party mode cause the party never ends ✨",
|
||||||
|
authors: [Devs.UwUDev],
|
||||||
|
settings,
|
||||||
|
|
||||||
|
start() {
|
||||||
|
setPoggerState(true);
|
||||||
|
setSettings(settings.store.superIntensePartyMode);
|
||||||
|
},
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
setPoggerState(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function setPoggerState(state: boolean) {
|
||||||
|
Object.assign(PoggerModeSettingsStore.__getLocalVars().state, {
|
||||||
|
enabled: state,
|
||||||
|
settingsVisible: state
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSettings(intensity: Intensity) {
|
||||||
|
const state = {
|
||||||
|
screenshakeEnabledLocations: { 0: true, 1: true, 2: true },
|
||||||
|
shakeIntensity: 1,
|
||||||
|
confettiSize: 16,
|
||||||
|
confettiCount: 5,
|
||||||
|
combosRequiredCount: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (intensity) {
|
||||||
|
case Intensity.Normal: {
|
||||||
|
Object.assign(state, {
|
||||||
|
screenshakeEnabledLocations: { 0: true, 1: false, 2: false },
|
||||||
|
combosRequiredCount: 5
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Intensity.Better: {
|
||||||
|
Object.assign(state, {
|
||||||
|
confettiSize: 12,
|
||||||
|
confettiCount: 8,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Intensity.ProjectX: {
|
||||||
|
Object.assign(state, {
|
||||||
|
shakeIntensity: 20,
|
||||||
|
confettiSize: 25,
|
||||||
|
confettiCount: 15,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(PoggerModeSettingsStore.__getLocalVars().state, state);
|
||||||
|
}
|
@ -23,7 +23,7 @@ import { filters, findBulk } from "@webpack";
|
|||||||
import { i18n, PermissionsBits, Text, Tooltip, useMemo, UserStore, useState } from "@webpack/common";
|
import { i18n, PermissionsBits, Text, Tooltip, useMemo, UserStore, useState } from "@webpack/common";
|
||||||
import type { Guild, GuildMember } from "discord-types/general";
|
import type { Guild, GuildMember } from "discord-types/general";
|
||||||
|
|
||||||
import { settings } from "..";
|
import { PermissionsSortOrder, settings } from "..";
|
||||||
import { cl, getPermissionString, getSortedRoles, sortUserRoles } from "../utils";
|
import { cl, getPermissionString, getSortedRoles, sortUserRoles } from "../utils";
|
||||||
import openRolesAndUsersPermissionsModal, { PermissionType, type RoleOrUserPermission } from "./RolesAndUsersPermissions";
|
import openRolesAndUsersPermissionsModal, { PermissionType, type RoleOrUserPermission } from "./RolesAndUsersPermissions";
|
||||||
|
|
||||||
@ -46,6 +46,7 @@ const Classes = proxyLazy(() => {
|
|||||||
}) as Record<"roles" | "rolePill" | "rolePillBorder" | "desaturateUserColors" | "flex" | "alignCenter" | "justifyCenter" | "svg" | "background" | "dot" | "dotBorderColor" | "roleCircle" | "dotBorderBase" | "flex" | "alignCenter" | "justifyCenter" | "wrap" | "root" | "role" | "roleRemoveButton" | "roleDot" | "roleFlowerStar" | "roleRemoveIcon" | "roleRemoveIconFocused" | "roleVerifiedIcon" | "roleName" | "roleNameOverflow" | "actionButton" | "overflowButton" | "addButton" | "addButtonIcon" | "overflowRolesPopout" | "overflowRolesPopoutArrowWrapper" | "overflowRolesPopoutArrow" | "popoutBottom" | "popoutTop" | "overflowRolesPopoutHeader" | "overflowRolesPopoutHeaderIcon" | "overflowRolesPopoutHeaderText" | "roleIcon", string>;
|
}) as Record<"roles" | "rolePill" | "rolePillBorder" | "desaturateUserColors" | "flex" | "alignCenter" | "justifyCenter" | "svg" | "background" | "dot" | "dotBorderColor" | "roleCircle" | "dotBorderBase" | "flex" | "alignCenter" | "justifyCenter" | "wrap" | "root" | "role" | "roleRemoveButton" | "roleDot" | "roleFlowerStar" | "roleRemoveIcon" | "roleRemoveIconFocused" | "roleVerifiedIcon" | "roleName" | "roleNameOverflow" | "actionButton" | "overflowButton" | "addButton" | "addButtonIcon" | "overflowRolesPopout" | "overflowRolesPopoutArrowWrapper" | "overflowRolesPopoutArrow" | "popoutBottom" | "popoutTop" | "overflowRolesPopoutHeader" | "overflowRolesPopoutHeaderIcon" | "overflowRolesPopoutHeaderText" | "roleIcon", string>;
|
||||||
|
|
||||||
function UserPermissionsComponent({ guild, guildMember }: { guild: Guild; guildMember: GuildMember; }) {
|
function UserPermissionsComponent({ guild, guildMember }: { guild: Guild; guildMember: GuildMember; }) {
|
||||||
|
const stns = settings.use(["permissionsSortOrder"]);
|
||||||
const [viewPermissions, setViewPermissions] = useState(settings.store.defaultPermissionsDropdownState);
|
const [viewPermissions, setViewPermissions] = useState(settings.store.defaultPermissionsDropdownState);
|
||||||
|
|
||||||
const [rolePermissions, userPermissions] = useMemo(() => {
|
const [rolePermissions, userPermissions] = useMemo(() => {
|
||||||
@ -91,7 +92,7 @@ function UserPermissionsComponent({ guild, guildMember }: { guild: Guild; guildM
|
|||||||
userPermissions.sort((a, b) => b.rolePosition - a.rolePosition);
|
userPermissions.sort((a, b) => b.rolePosition - a.rolePosition);
|
||||||
|
|
||||||
return [rolePermissions, userPermissions];
|
return [rolePermissions, userPermissions];
|
||||||
}, []);
|
}, [stns.permissionsSortOrder]);
|
||||||
|
|
||||||
const { root, role, roleRemoveButton, roleNameOverflow, roles, rolePill, rolePillBorder, roleCircle, roleName } = Classes;
|
const { root, role, roleRemoveButton, roleNameOverflow, roles, rolePill, rolePillBorder, roleCircle, roleName } = Classes;
|
||||||
|
|
||||||
@ -100,7 +101,28 @@ function UserPermissionsComponent({ guild, guildMember }: { guild: Guild; guildM
|
|||||||
<div className={cl("userperms-title-container")}>
|
<div className={cl("userperms-title-container")}>
|
||||||
<Text className={cl("userperms-title")} variant="eyebrow">Permissions</Text>
|
<Text className={cl("userperms-title")} variant="eyebrow">Permissions</Text>
|
||||||
|
|
||||||
<div>
|
<div className={cl("userperms-btns-container")}>
|
||||||
|
<Tooltip text={`Sorting by ${stns.permissionsSortOrder === PermissionsSortOrder.HighestRole ? "Highest Role" : "Lowest Role"}`}>
|
||||||
|
{tooltipProps => (
|
||||||
|
<button
|
||||||
|
{...tooltipProps}
|
||||||
|
className={cl("userperms-sortorder-btn")}
|
||||||
|
onClick={() => {
|
||||||
|
stns.permissionsSortOrder = stns.permissionsSortOrder === PermissionsSortOrder.HighestRole ? PermissionsSortOrder.LowestRole : PermissionsSortOrder.HighestRole;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 96 960 960"
|
||||||
|
transform={stns.permissionsSortOrder === PermissionsSortOrder.HighestRole ? "scale(1 1)" : "scale(1 -1)"}
|
||||||
|
>
|
||||||
|
<path fill="var(--text-normal)" d="M440 896V409L216 633l-56-57 320-320 320 320-56 57-224-224v487h-80Z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip text="Role Details">
|
<Tooltip text="Role Details">
|
||||||
{tooltipProps => (
|
{tooltipProps => (
|
||||||
<button
|
<button
|
||||||
|
@ -27,7 +27,7 @@ import type { Guild, GuildMember } from "discord-types/general";
|
|||||||
|
|
||||||
import openRolesAndUsersPermissionsModal, { PermissionType, RoleOrUserPermission } from "./components/RolesAndUsersPermissions";
|
import openRolesAndUsersPermissionsModal, { PermissionType, RoleOrUserPermission } from "./components/RolesAndUsersPermissions";
|
||||||
import UserPermissions from "./components/UserPermissions";
|
import UserPermissions from "./components/UserPermissions";
|
||||||
import { getSortedRoles } from "./utils";
|
import { getSortedRoles, sortPermissionOverwrites } from "./utils";
|
||||||
|
|
||||||
export const enum PermissionsSortOrder {
|
export const enum PermissionsSortOrder {
|
||||||
HighestRole,
|
HighestRole,
|
||||||
@ -94,12 +94,12 @@ function MenuItem(guildId: string, id?: string, type?: MenuItemParentType) {
|
|||||||
case MenuItemParentType.Channel: {
|
case MenuItemParentType.Channel: {
|
||||||
const channel = ChannelStore.getChannel(id!);
|
const channel = ChannelStore.getChannel(id!);
|
||||||
|
|
||||||
permissions = Object.values(channel.permissionOverwrites).map(({ id, allow, deny, type }) => ({
|
permissions = sortPermissionOverwrites(Object.values(channel.permissionOverwrites).map(({ id, allow, deny, type }) => ({
|
||||||
type: type as PermissionType,
|
type: type as PermissionType,
|
||||||
id,
|
id,
|
||||||
overwriteAllow: allow,
|
overwriteAllow: allow,
|
||||||
overwriteDeny: deny
|
overwriteDeny: deny
|
||||||
}));
|
})), guildId);
|
||||||
|
|
||||||
header = channel.name;
|
header = channel.name;
|
||||||
|
|
||||||
|
@ -3,21 +3,38 @@
|
|||||||
.vc-permviewer-userperms-title-container {
|
.vc-permviewer-userperms-title-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
align-items: center;
|
||||||
|
|
||||||
.vc-permviewer-userperms-title {
|
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vc-permviewer-userperms-btns-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vc-permviewer-userperms-sortorder-btn {
|
||||||
|
all: unset;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
.vc-permviewer-userperms-permdetails-btn {
|
.vc-permviewer-userperms-permdetails-btn {
|
||||||
all: unset;
|
all: unset;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vc-permviewer-userperms-toggleperms-btn {
|
.vc-permviewer-userperms-toggleperms-btn {
|
||||||
all: unset;
|
all: unset;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RolesAndUsersPermissions Component */
|
/* RolesAndUsersPermissions Component */
|
||||||
|
@ -18,11 +18,12 @@
|
|||||||
|
|
||||||
import { classNameFactory } from "@api/Styles";
|
import { classNameFactory } from "@api/Styles";
|
||||||
import { wordsToTitle } from "@utils/text";
|
import { wordsToTitle } from "@utils/text";
|
||||||
import { i18n, Parser } from "@webpack/common";
|
import { GuildStore, i18n, Parser } from "@webpack/common";
|
||||||
import { Guild, GuildMember, Role } from "discord-types/general";
|
import { Guild, GuildMember, Role } from "discord-types/general";
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
import { PermissionsSortOrder, settings } from ".";
|
import { PermissionsSortOrder, settings } from ".";
|
||||||
|
import { PermissionType } from "./components/RolesAndUsersPermissions";
|
||||||
|
|
||||||
export const cl = classNameFactory("vc-permviewer-");
|
export const cl = classNameFactory("vc-permviewer-");
|
||||||
|
|
||||||
@ -82,3 +83,16 @@ export function sortUserRoles(roles: Role[]) {
|
|||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function sortPermissionOverwrites<T extends { id: string; type: number; }>(overwrites: T[], guildId: string) {
|
||||||
|
const guild = GuildStore.getGuild(guildId);
|
||||||
|
|
||||||
|
return overwrites.sort((a, b) => {
|
||||||
|
if (a.type !== PermissionType.Role || b.type !== PermissionType.Role) return 0;
|
||||||
|
|
||||||
|
const roleA = guild.roles[a.id];
|
||||||
|
const roleB = guild.roles[b.id];
|
||||||
|
|
||||||
|
return roleB.position - roleA.position;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -26,6 +26,7 @@ import type { Channel } from "discord-types/general";
|
|||||||
import type { ComponentType } from "react";
|
import type { ComponentType } from "react";
|
||||||
|
|
||||||
import openRolesAndUsersPermissionsModal, { PermissionType, RoleOrUserPermission } from "../../permissionsViewer/components/RolesAndUsersPermissions";
|
import openRolesAndUsersPermissionsModal, { PermissionType, RoleOrUserPermission } from "../../permissionsViewer/components/RolesAndUsersPermissions";
|
||||||
|
import { sortPermissionOverwrites } from "../../permissionsViewer/utils";
|
||||||
import { settings, VIEW_CHANNEL } from "..";
|
import { settings, VIEW_CHANNEL } from "..";
|
||||||
|
|
||||||
enum SortOrderTypes {
|
enum SortOrderTypes {
|
||||||
@ -169,12 +170,12 @@ function HiddenChannelLockScreen({ channel }: { channel: ExtendedChannel; }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.plugins.PermissionsViewer.enabled) {
|
if (Settings.plugins.PermissionsViewer.enabled) {
|
||||||
setPermissions(Object.values(permissionOverwrites).map(overwrite => ({
|
setPermissions(sortPermissionOverwrites(Object.values(permissionOverwrites).map(overwrite => ({
|
||||||
type: overwrite.type as PermissionType,
|
type: overwrite.type as PermissionType,
|
||||||
id: overwrite.id,
|
id: overwrite.id,
|
||||||
overwriteAllow: overwrite.allow,
|
overwriteAllow: overwrite.allow,
|
||||||
overwriteDeny: overwrite.deny
|
overwriteDeny: overwrite.deny
|
||||||
})));
|
})), guild_id));
|
||||||
}
|
}
|
||||||
}, [channelId]);
|
}, [channelId]);
|
||||||
|
|
||||||
|
@ -107,13 +107,13 @@ export default definePlugin({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Prevent Discord from trying to connect to hidden channels
|
// Prevent Discord from trying to connect to hidden channels
|
||||||
match: /(?=\|\|\i\.default\.selectVoiceChannel\((\i)\.id\))/,
|
match: /if\(!\i&&!\i(?=.{0,50}?selectVoiceChannel\((\i)\.id\))/,
|
||||||
replace: (_, channel) => `||$self.isHiddenChannel(${channel})`
|
replace: (m, channel) => `${m}&&!$self.isHiddenChannel(${channel})`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Make Discord show inside the channel if clicking on a hidden or locked channel
|
// Make Discord show inside the channel if clicking on a hidden or locked channel
|
||||||
match: /(?<=\|\|\i\.default\.selectVoiceChannel\((\i)\.id\);!__OVERLAY__&&\()/,
|
match: /!__OVERLAY__&&\((?<=selectVoiceChannel\((\i)\.id\).+?)/,
|
||||||
replace: (_, channel) => `$self.isHiddenChannel(${channel},true)||`
|
replace: (m, channel) => `${m}$self.isHiddenChannel(${channel},true)||`
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -195,7 +195,7 @@ export default definePlugin({
|
|||||||
replace: (_, pushNotificationButtonExpression, channel) => `if($self.isHiddenChannel(${channel})){${pushNotificationButtonExpression}break;}`
|
replace: (_, pushNotificationButtonExpression, channel) => `if($self.isHiddenChannel(${channel})){${pushNotificationButtonExpression}break;}`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
match: /(?<=renderHeaderToolbar=function.+?case \i\.\i\.GUILD_FORUM:if\(!\i\){)(?=.+?;(.+?{channel:(\i)},"notifications"\)\)))/,
|
match: /(?<=renderHeaderToolbar=function.+?case \i\.\i\.GUILD_FORUM:.+?if\(!\i\){)(?=.+?;(.+?{channel:(\i)},"notifications"\)\)))/,
|
||||||
replace: (_, pushNotificationButtonExpression, channel) => `if($self.isHiddenChannel(${channel})){${pushNotificationButtonExpression};break;}`
|
replace: (_, pushNotificationButtonExpression, channel) => `if($self.isHiddenChannel(${channel})){${pushNotificationButtonExpression};break;}`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
import { DataStore } from "@api/index";
|
import { DataStore } from "@api/index";
|
||||||
import { Devs, SUPPORT_CHANNEL_ID } from "@utils/constants";
|
import { Devs, SUPPORT_CHANNEL_ID } from "@utils/constants";
|
||||||
|
import { isPluginDev } from "@utils/misc";
|
||||||
import { makeCodeblock } from "@utils/text";
|
import { makeCodeblock } from "@utils/text";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { isOutdated } from "@utils/updater";
|
import { isOutdated } from "@utils/updater";
|
||||||
@ -74,8 +75,7 @@ ${makeCodeblock(Object.keys(plugins).filter(Vencord.Plugins.isPluginEnabled).joi
|
|||||||
async CHANNEL_SELECT({ channelId }) {
|
async CHANNEL_SELECT({ channelId }) {
|
||||||
if (channelId !== SUPPORT_CHANNEL_ID) return;
|
if (channelId !== SUPPORT_CHANNEL_ID) return;
|
||||||
|
|
||||||
const myId = BigInt(UserStore.getCurrentUser().id);
|
if (isPluginDev(UserStore.getCurrentUser().id)) return;
|
||||||
if (Object.values(Devs).some(d => d.id === myId)) return;
|
|
||||||
|
|
||||||
if (isOutdated && gitHash !== await DataStore.get(REMEMBER_DISMISS_KEY)) {
|
if (isOutdated && gitHash !== await DataStore.get(REMEMBER_DISMISS_KEY)) {
|
||||||
const rememberDismiss = () => DataStore.set(REMEMBER_DISMISS_KEY, gitHash);
|
const rememberDismiss = () => DataStore.set(REMEMBER_DISMISS_KEY, gitHash);
|
||||||
|
@ -89,7 +89,7 @@ function TypingIndicator({ channelId }: { channelId: string; }) {
|
|||||||
<Tooltip text={tooltipText!}>
|
<Tooltip text={tooltipText!}>
|
||||||
{({ onMouseLeave, onMouseEnter }) => (
|
{({ onMouseLeave, onMouseEnter }) => (
|
||||||
<div
|
<div
|
||||||
style={{ marginLeft: 6, zIndex: 0, cursor: "pointer" }}
|
style={{ marginLeft: 6, height: 16, display: "flex", alignItems: "center", zIndex: 0, cursor: "pointer" }}
|
||||||
onMouseLeave={onMouseLeave}
|
onMouseLeave={onMouseLeave}
|
||||||
onMouseEnter={onMouseEnter}
|
onMouseEnter={onMouseEnter}
|
||||||
>
|
>
|
||||||
|
@ -89,7 +89,11 @@ const TypingUser = ErrorBoundary.wrap(function ({ user, guildId }: Props) {
|
|||||||
src={user.getAvatarURL(guildId, 128)} />
|
src={user.getAvatarURL(guildId, 128)} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{GuildMemberStore.getNick(guildId!, user.id) || !guildId && RelationshipStore.getNickname(user.id) || user.username}
|
{GuildMemberStore.getNick(guildId!, user.id)
|
||||||
|
|| (!guildId && RelationshipStore.getNickname(user.id))
|
||||||
|
|| (user as any).globalName
|
||||||
|
|| user.username
|
||||||
|
}
|
||||||
</strong>
|
</strong>
|
||||||
);
|
);
|
||||||
}, { noop: true });
|
}, { noop: true });
|
||||||
|
@ -17,8 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { findOption, RequiredMessageOption } from "@api/Commands";
|
import { findOption, RequiredMessageOption } from "@api/Commands";
|
||||||
|
import { addPreEditListener, addPreSendListener, MessageObject, removePreEditListener, removePreSendListener } from "@api/MessageEvents";
|
||||||
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
|
|
||||||
const endings = [
|
const endings = [
|
||||||
"rawr x3",
|
"rawr x3",
|
||||||
@ -65,6 +67,15 @@ const replacements = [
|
|||||||
["meow", "nya~"],
|
["meow", "nya~"],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const settings = definePluginSettings({
|
||||||
|
uwuEveryMessage: {
|
||||||
|
description: "Make every single message uwuified",
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
default: false,
|
||||||
|
restartNeeded: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function selectRandomElement(arr) {
|
function selectRandomElement(arr) {
|
||||||
// generate a random index based on the length of the array
|
// generate a random index based on the length of the array
|
||||||
const randomIndex = Math.floor(Math.random() * arr.length);
|
const randomIndex = Math.floor(Math.random() * arr.length);
|
||||||
@ -94,8 +105,9 @@ function uwuify(message: string): string {
|
|||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "UwUifier",
|
name: "UwUifier",
|
||||||
description: "Simply uwuify commands",
|
description: "Simply uwuify commands",
|
||||||
authors: [Devs.echo, Devs.skyevg],
|
authors: [Devs.echo, Devs.skyevg, Devs.PandaNinjas],
|
||||||
dependencies: ["CommandsAPI"],
|
dependencies: ["CommandsAPI", "MessageEventsAPI"],
|
||||||
|
settings,
|
||||||
|
|
||||||
commands: [
|
commands: [
|
||||||
{
|
{
|
||||||
@ -108,4 +120,23 @@ export default definePlugin({
|
|||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
|
onSend(msg: MessageObject) {
|
||||||
|
// Only run when it's enabled
|
||||||
|
if (settings.store.uwuEveryMessage) {
|
||||||
|
msg.content = uwuify(msg.content);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
start() {
|
||||||
|
this.preSend = addPreSendListener((_, msg) => this.onSend(msg));
|
||||||
|
this.preEdit = addPreEditListener((_cid, _mid, msg) =>
|
||||||
|
this.onSend(msg)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
removePreSendListener(this.preSend);
|
||||||
|
removePreEditListener(this.preEdit);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
@ -29,7 +29,18 @@ export const REACT_GLOBAL = "Vencord.Webpack.Common.React";
|
|||||||
export const VENCORD_USER_AGENT = `Vencord/${gitHash}${gitRemote ? ` (https://github.com/${gitRemote})` : ""}`;
|
export const VENCORD_USER_AGENT = `Vencord/${gitHash}${gitRemote ? ` (https://github.com/${gitRemote})` : ""}`;
|
||||||
export const SUPPORT_CHANNEL_ID = "1026515880080842772";
|
export const SUPPORT_CHANNEL_ID = "1026515880080842772";
|
||||||
|
|
||||||
// Add yourself here if you made a plugin
|
export interface Dev {
|
||||||
|
name: string;
|
||||||
|
id: bigint;
|
||||||
|
badge?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If you made a plugin or substantial contribution, add yourself here.
|
||||||
|
* This object is used for the plugin author list, as well as to add a contributor badge to your profile.
|
||||||
|
* If you wish to stay fully anonymous, feel free to set ID to 0n.
|
||||||
|
* If you are fine with attribution but don't want the badge, add badge: false
|
||||||
|
*/
|
||||||
export const Devs = /* #__PURE__*/ Object.freeze({
|
export const Devs = /* #__PURE__*/ Object.freeze({
|
||||||
Ven: {
|
Ven: {
|
||||||
name: "Vendicated",
|
name: "Vendicated",
|
||||||
@ -201,7 +212,8 @@ export const Devs = /* #__PURE__*/ Object.freeze({
|
|||||||
},
|
},
|
||||||
nick: {
|
nick: {
|
||||||
name: "nick",
|
name: "nick",
|
||||||
id: 347884694408265729n
|
id: 347884694408265729n,
|
||||||
|
badge: false
|
||||||
},
|
},
|
||||||
whqwert: {
|
whqwert: {
|
||||||
name: "whqwert",
|
name: "whqwert",
|
||||||
@ -287,6 +299,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
|
|||||||
name: "carince",
|
name: "carince",
|
||||||
id: 818323528755314698n
|
id: 818323528755314698n
|
||||||
},
|
},
|
||||||
|
PandaNinjas: {
|
||||||
|
name: "PandaNinjas",
|
||||||
|
id: 455128749071925248n
|
||||||
|
},
|
||||||
CatNoir: {
|
CatNoir: {
|
||||||
name: "CatNoir",
|
name: "CatNoir",
|
||||||
id: 260371016348336128n
|
id: 260371016348336128n
|
||||||
@ -295,4 +311,17 @@ export const Devs = /* #__PURE__*/ Object.freeze({
|
|||||||
name: "outfoxxed",
|
name: "outfoxxed",
|
||||||
id: 837425748435796060n
|
id: 837425748435796060n
|
||||||
},
|
},
|
||||||
});
|
UwUDev: {
|
||||||
|
name: "UwU",
|
||||||
|
id: 691413039156690994n,
|
||||||
|
},
|
||||||
|
} satisfies Record<string, Dev>);
|
||||||
|
|
||||||
|
// iife so #__PURE__ works correctly
|
||||||
|
export const DevsById = /* #__PURE__*/ (() =>
|
||||||
|
Object.freeze(Object.fromEntries(
|
||||||
|
Object.entries(Devs)
|
||||||
|
.filter(d => d[1].id !== 0n)
|
||||||
|
.map(([_, v]) => [v.id, v] as const)
|
||||||
|
))
|
||||||
|
)() as Record<string, Dev>;
|
||||||
|
@ -16,11 +16,13 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { findLazy } from "@webpack";
|
import { MessageObject } from "@api/MessageEvents";
|
||||||
|
import { findByPropsLazy, findLazy } from "@webpack";
|
||||||
import { ChannelStore, ComponentDispatch, GuildStore, PrivateChannelsStore, SelectedChannelStore } from "@webpack/common";
|
import { ChannelStore, ComponentDispatch, GuildStore, PrivateChannelsStore, SelectedChannelStore } from "@webpack/common";
|
||||||
import { Guild } from "discord-types/general";
|
import { Guild, Message } from "discord-types/general";
|
||||||
|
|
||||||
const PreloadedUserSettings = findLazy(m => m.ProtoClass?.typeName.endsWith("PreloadedUserSettings"));
|
const PreloadedUserSettings = findLazy(m => m.ProtoClass?.typeName.endsWith("PreloadedUserSettings"));
|
||||||
|
const MessageActions = findByPropsLazy("editMessage", "sendMessage");
|
||||||
|
|
||||||
export function getCurrentChannel() {
|
export function getCurrentChannel() {
|
||||||
return ChannelStore.getChannel(SelectedChannelStore.getChannelId());
|
return ChannelStore.getChannel(SelectedChannelStore.getChannelId());
|
||||||
@ -49,3 +51,29 @@ export function insertTextIntoChatInputBox(text: string) {
|
|||||||
plainText: text
|
plainText: text
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface MessageExtra {
|
||||||
|
messageReference: Message["messageReference"];
|
||||||
|
allowedMentions: {
|
||||||
|
parse: string[];
|
||||||
|
replied_user: boolean;
|
||||||
|
};
|
||||||
|
stickerIds: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sendMessage(
|
||||||
|
channelId: string,
|
||||||
|
data: Partial<MessageObject>,
|
||||||
|
waitForChannelReady?: boolean,
|
||||||
|
extra?: Partial<MessageExtra>
|
||||||
|
) {
|
||||||
|
const messageData = {
|
||||||
|
content: "",
|
||||||
|
invalidEmojis: [],
|
||||||
|
tts: false,
|
||||||
|
validNonShortcutEmojis: [],
|
||||||
|
...data
|
||||||
|
};
|
||||||
|
|
||||||
|
return MessageActions.sendMessage(channelId, messageData, waitForChannelReady, extra);
|
||||||
|
}
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
import { Clipboard, Toasts } from "@webpack/common";
|
import { Clipboard, Toasts } from "@webpack/common";
|
||||||
|
|
||||||
|
import { DevsById } from "./constants";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively merges defaults into an object and returns the same object
|
* Recursively merges defaults into an object and returns the same object
|
||||||
* @param obj Object
|
* @param obj Object
|
||||||
@ -100,3 +102,5 @@ export function identity<T>(value: T): T {
|
|||||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#mobile_tablet_or_desktop
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#mobile_tablet_or_desktop
|
||||||
// "In summary, we recommend looking for the string Mobi anywhere in the User Agent to detect a mobile device."
|
// "In summary, we recommend looking for the string Mobi anywhere in the User Agent to detect a mobile device."
|
||||||
export const isMobile = navigator.userAgent.includes("Mobi");
|
export const isMobile = navigator.userAgent.includes("Mobi");
|
||||||
|
|
||||||
|
export const isPluginDev = (id: string) => Object.hasOwn(DevsById, id);
|
||||||
|
@ -25,7 +25,7 @@ import * as t from "./types/stores";
|
|||||||
|
|
||||||
export const Flux: t.Flux = findByPropsLazy("connectStores");
|
export const Flux: t.Flux = findByPropsLazy("connectStores");
|
||||||
|
|
||||||
type GenericStore = t.FluxStore & Record<string, any>;
|
export type GenericStore = t.FluxStore & Record<string, any>;
|
||||||
|
|
||||||
export let MessageStore: Omit<Stores.MessageStore, "getMessages"> & {
|
export let MessageStore: Omit<Stores.MessageStore, "getMessages"> & {
|
||||||
getMessages(chanId: string): any;
|
getMessages(chanId: string): any;
|
||||||
@ -37,6 +37,7 @@ export let PermissionStore: GenericStore;
|
|||||||
export let GuildChannelStore: GenericStore;
|
export let GuildChannelStore: GenericStore;
|
||||||
export let ReadStateStore: GenericStore;
|
export let ReadStateStore: GenericStore;
|
||||||
export let PresenceStore: GenericStore;
|
export let PresenceStore: GenericStore;
|
||||||
|
export let PoggerModeSettingsStore: GenericStore;
|
||||||
|
|
||||||
export let GuildStore: Stores.GuildStore & t.FluxStore;
|
export let GuildStore: Stores.GuildStore & t.FluxStore;
|
||||||
export let UserStore: Stores.UserStore & t.FluxStore;
|
export let UserStore: Stores.UserStore & t.FluxStore;
|
||||||
|
Reference in New Issue
Block a user