mirror of
https://github.com/Equicord/Equicord.git
synced 2025-06-10 15:13:02 -04:00
Merge remote-tracking branch 'upstream/dev'
This commit is contained in:
commit
73a3c89935
21 changed files with 197 additions and 122 deletions
|
@ -61,7 +61,7 @@ export default definePlugin({
|
||||||
find: ".popularApplicationCommandIds,",
|
find: ".popularApplicationCommandIds,",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /lastSection:(!?\i)}\),/,
|
match: /lastSection:(!?\i)}\),/,
|
||||||
replace: "$&$self.patchPadding($1),"
|
replace: "$&$self.patchPadding({lastSection:$1}),"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -81,12 +81,10 @@ export default definePlugin({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
patchPadding(lastSection: any) {
|
patchPadding: ErrorBoundary.wrap(({ lastSection }) => {
|
||||||
if (!lastSection) return;
|
if (!lastSection) return null;
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary noop>
|
<div className={UserPopoutSectionCssClasses.lastSection} ></div>
|
||||||
<div className={UserPopoutSectionCssClasses.lastSection}></div>
|
|
||||||
</ErrorBoundary>
|
|
||||||
);
|
);
|
||||||
}
|
})
|
||||||
});
|
});
|
||||||
|
|
|
@ -22,7 +22,7 @@ import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy, findExportedComponentLazy, findStoreLazy } from "@webpack";
|
import { findByPropsLazy, findExportedComponentLazy, findStoreLazy } from "@webpack";
|
||||||
import { React, RestAPI, Tooltip } from "@webpack/common";
|
import { Constants, React, RestAPI, Tooltip } from "@webpack/common";
|
||||||
|
|
||||||
import { RenameButton } from "./components/RenameButton";
|
import { RenameButton } from "./components/RenameButton";
|
||||||
import { Session, SessionInfo } from "./types";
|
import { Session, SessionInfo } from "./types";
|
||||||
|
@ -168,7 +168,7 @@ export default definePlugin({
|
||||||
|
|
||||||
async checkNewSessions() {
|
async checkNewSessions() {
|
||||||
const data = await RestAPI.get({
|
const data = await RestAPI.get({
|
||||||
url: "/auth/sessions"
|
url: Constants.Endpoints.AUTH_SESSIONS
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const session of data.body.user_sessions) {
|
for (const session of data.body.user_sessions) {
|
||||||
|
|
|
@ -24,7 +24,7 @@ import { Margins } from "@utils/margins";
|
||||||
import { ModalContent, ModalHeader, ModalRoot, openModalLazy } from "@utils/modal";
|
import { ModalContent, ModalHeader, ModalRoot, openModalLazy } from "@utils/modal";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { findByPropsLazy, findStoreLazy } from "@webpack";
|
import { findByPropsLazy, findStoreLazy } from "@webpack";
|
||||||
import { EmojiStore, FluxDispatcher, Forms, GuildStore, Menu, PermissionsBits, PermissionStore, React, RestAPI, Toasts, Tooltip, UserStore } from "@webpack/common";
|
import { Constants, EmojiStore, FluxDispatcher, Forms, GuildStore, Menu, PermissionsBits, PermissionStore, React, RestAPI, Toasts, Tooltip, UserStore } from "@webpack/common";
|
||||||
import { Promisable } from "type-fest";
|
import { Promisable } from "type-fest";
|
||||||
|
|
||||||
const StickersStore = findStoreLazy("StickersStore");
|
const StickersStore = findStoreLazy("StickersStore");
|
||||||
|
@ -64,7 +64,7 @@ async function fetchSticker(id: string) {
|
||||||
if (cached) return cached;
|
if (cached) return cached;
|
||||||
|
|
||||||
const { body } = await RestAPI.get({
|
const { body } = await RestAPI.get({
|
||||||
url: `/stickers/${id}`
|
url: Constants.Endpoints.STICKER(id)
|
||||||
});
|
});
|
||||||
|
|
||||||
FluxDispatcher.dispatch({
|
FluxDispatcher.dispatch({
|
||||||
|
@ -83,7 +83,7 @@ async function cloneSticker(guildId: string, sticker: Sticker) {
|
||||||
data.append("file", await fetchBlob(getUrl(sticker)));
|
data.append("file", await fetchBlob(getUrl(sticker)));
|
||||||
|
|
||||||
const { body } = await RestAPI.post({
|
const { body } = await RestAPI.post({
|
||||||
url: `/guilds/${guildId}/stickers`,
|
url: Constants.Endpoints.GUILD_STICKER_PACKS(guildId),
|
||||||
body: data,
|
body: data,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -322,8 +322,9 @@ const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) =
|
||||||
switch (favoriteableType) {
|
switch (favoriteableType) {
|
||||||
case "emoji":
|
case "emoji":
|
||||||
const match = props.message.content.match(RegExp(`<a?:(\\w+)(?:~\\d+)?:${favoriteableId}>|https://cdn\\.discordapp\\.com/emojis/${favoriteableId}\\.`));
|
const match = props.message.content.match(RegExp(`<a?:(\\w+)(?:~\\d+)?:${favoriteableId}>|https://cdn\\.discordapp\\.com/emojis/${favoriteableId}\\.`));
|
||||||
if (!match) return;
|
const reaction = props.message.reactions.find(reaction => reaction.emoji.id === favoriteableId);
|
||||||
const name = match[1] ?? "FakeNitroEmoji";
|
if (!match && !reaction) return;
|
||||||
|
const name = (match && match[1]) ?? reaction?.emoji.name ?? "FakeNitroEmoji";
|
||||||
|
|
||||||
return buildMenuItem("Emoji", () => ({
|
return buildMenuItem("Emoji", () => ({
|
||||||
id: favoriteableId,
|
id: favoriteableId,
|
||||||
|
|
|
@ -39,6 +39,7 @@ const StickerStore = findStoreLazy("StickersStore") as {
|
||||||
|
|
||||||
const UserSettingsProtoStore = findStoreLazy("UserSettingsProtoStore");
|
const UserSettingsProtoStore = findStoreLazy("UserSettingsProtoStore");
|
||||||
const ProtoUtils = findByPropsLazy("BINARY_READ_OPTIONS");
|
const ProtoUtils = findByPropsLazy("BINARY_READ_OPTIONS");
|
||||||
|
const RoleSubscriptionEmojiUtils = findByPropsLazy("isUnusableRoleSubscriptionEmoji");
|
||||||
|
|
||||||
function searchProtoClassField(localName: string, protoClass: any) {
|
function searchProtoClassField(localName: string, protoClass: any) {
|
||||||
const field = protoClass?.fields?.find((field: any) => field.localName === localName);
|
const field = protoClass?.fields?.find((field: any) => field.localName === localName);
|
||||||
|
@ -408,6 +409,15 @@ export default definePlugin({
|
||||||
match: /canUseCustomNotificationSounds:function\(\i\){/,
|
match: /canUseCustomNotificationSounds:function\(\i\){/,
|
||||||
replace: "$&return true;"
|
replace: "$&return true;"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
// Allows the usage of subscription-locked emojis
|
||||||
|
{
|
||||||
|
find: "isUnusableRoleSubscriptionEmoji:function",
|
||||||
|
replacement: {
|
||||||
|
match: /isUnusableRoleSubscriptionEmoji:function/,
|
||||||
|
// replace the original export with a func that always returns false and alias the original
|
||||||
|
replace: "isUnusableRoleSubscriptionEmoji:()=>()=>false,isUnusableRoleSubscriptionEmojiOriginal:function"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -807,6 +817,9 @@ export default definePlugin({
|
||||||
if (e.require_colons === false) return true;
|
if (e.require_colons === false) return true;
|
||||||
if (e.available === false) return false;
|
if (e.available === false) return false;
|
||||||
|
|
||||||
|
const isUnusableRoleSubEmoji = RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmojiOriginal ?? RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmoji;
|
||||||
|
if (isUnusableRoleSubEmoji(e, this.guildId)) return false;
|
||||||
|
|
||||||
if (this.canUseEmotes)
|
if (this.canUseEmotes)
|
||||||
return e.guildId === this.guildId || hasExternalEmojiPerms(channelId);
|
return e.guildId === this.guildId || hasExternalEmojiPerms(channelId);
|
||||||
else
|
else
|
||||||
|
|
|
@ -20,7 +20,7 @@ import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption,
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByPropsLazy } from "@webpack";
|
||||||
import { RestAPI, UserStore } from "@webpack/common";
|
import { Constants, RestAPI, UserStore } from "@webpack/common";
|
||||||
|
|
||||||
const FriendInvites = findByPropsLazy("createFriendInvite");
|
const FriendInvites = findByPropsLazy("createFriendInvite");
|
||||||
const { uuid4 } = findByPropsLazy("uuid4");
|
const { uuid4 } = findByPropsLazy("uuid4");
|
||||||
|
@ -58,7 +58,7 @@ export default definePlugin({
|
||||||
if (uses === 1) {
|
if (uses === 1) {
|
||||||
const random = uuid4();
|
const random = uuid4();
|
||||||
const { body: { invite_suggestions } } = await RestAPI.post({
|
const { body: { invite_suggestions } } = await RestAPI.post({
|
||||||
url: "/friend-finder/find-friends",
|
url: Constants.Endpoints.FRIEND_FINDER,
|
||||||
body: {
|
body: {
|
||||||
modified_contacts: {
|
modified_contacts: {
|
||||||
[random]: [1, "", ""]
|
[random]: [1, "", ""]
|
||||||
|
|
|
@ -23,7 +23,7 @@ import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { getStegCloak } from "@utils/dependencies";
|
import { getStegCloak } from "@utils/dependencies";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { ChannelStore, FluxDispatcher, RestAPI, Tooltip } from "@webpack/common";
|
import { ChannelStore, Constants, FluxDispatcher, RestAPI, Tooltip } from "@webpack/common";
|
||||||
import { Message } from "discord-types/general";
|
import { Message } from "discord-types/general";
|
||||||
|
|
||||||
import { buildDecModal } from "./components/DecryptionModal";
|
import { buildDecModal } from "./components/DecryptionModal";
|
||||||
|
@ -149,7 +149,7 @@ export default definePlugin({
|
||||||
// Gets the Embed of a Link
|
// Gets the Embed of a Link
|
||||||
async getEmbed(url: URL): Promise<Object | {}> {
|
async getEmbed(url: URL): Promise<Object | {}> {
|
||||||
const { body } = await RestAPI.post({
|
const { body } = await RestAPI.post({
|
||||||
url: "/unfurler/embed-urls",
|
url: Constants.Endpoints.UNFURL_EMBED_URLS,
|
||||||
body: {
|
body: {
|
||||||
urls: [url]
|
urls: [url]
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,19 +24,27 @@ interface Diff {
|
||||||
seconds: number;
|
seconds: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DISCORD_KT_DELAY = 1471228.928;
|
||||||
const HiddenVisually = findExportedComponentLazy("HiddenVisually");
|
const HiddenVisually = findExportedComponentLazy("HiddenVisually");
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "MessageLatency",
|
name: "MessageLatency",
|
||||||
description: "Displays an indicator for messages that took ≥n seconds to send",
|
description: "Displays an indicator for messages that took ≥n seconds to send",
|
||||||
authors: [Devs.arHSM],
|
authors: [Devs.arHSM],
|
||||||
|
|
||||||
settings: definePluginSettings({
|
settings: definePluginSettings({
|
||||||
latency: {
|
latency: {
|
||||||
type: OptionType.NUMBER,
|
type: OptionType.NUMBER,
|
||||||
description: "Threshold in seconds for latency indicator",
|
description: "Threshold in seconds for latency indicator",
|
||||||
default: 2
|
default: 2
|
||||||
|
},
|
||||||
|
detectDiscordKotlin: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Detect old Discord Android clients",
|
||||||
|
default: true
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
find: "showCommunicationDisabledStyles",
|
find: "showCommunicationDisabledStyles",
|
||||||
|
@ -46,6 +54,7 @@ export default definePlugin({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
stringDelta(delta: number) {
|
stringDelta(delta: number) {
|
||||||
const diff: Diff = {
|
const diff: Diff = {
|
||||||
days: Math.round(delta / (60 * 60 * 24)),
|
days: Math.round(delta / (60 * 60 * 24)),
|
||||||
|
@ -71,15 +80,25 @@ export default definePlugin({
|
||||||
);
|
);
|
||||||
}, "");
|
}, "");
|
||||||
|
|
||||||
return [ts || "0 seconds", diff.days === 17 && diff.hours === 1] as const;
|
return ts || "0 seconds";
|
||||||
},
|
},
|
||||||
|
|
||||||
latencyTooltipData(message: Message) {
|
latencyTooltipData(message: Message) {
|
||||||
|
const { latency, detectDiscordKotlin } = this.settings.store;
|
||||||
const { id, nonce } = message;
|
const { id, nonce } = message;
|
||||||
|
|
||||||
// Message wasn't received through gateway
|
// Message wasn't received through gateway
|
||||||
if (!isNonNullish(nonce)) return null;
|
if (!isNonNullish(nonce)) return null;
|
||||||
|
|
||||||
const delta = Math.round((SnowflakeUtils.extractTimestamp(id) - SnowflakeUtils.extractTimestamp(nonce)) / 1000);
|
let isDiscordKotlin = false;
|
||||||
|
let delta = Math.round((SnowflakeUtils.extractTimestamp(id) - SnowflakeUtils.extractTimestamp(nonce)) / 1000);
|
||||||
|
|
||||||
|
// Old Discord Android clients have a delay of around 17 days
|
||||||
|
// This is a workaround for that
|
||||||
|
if (-delta >= DISCORD_KT_DELAY - 86400) { // One day of padding for good measure
|
||||||
|
isDiscordKotlin = detectDiscordKotlin;
|
||||||
|
delta += DISCORD_KT_DELAY;
|
||||||
|
}
|
||||||
|
|
||||||
// Thanks dziurwa (I hate you)
|
// Thanks dziurwa (I hate you)
|
||||||
// This is when the user's clock is ahead
|
// This is when the user's clock is ahead
|
||||||
|
@ -87,15 +106,13 @@ export default definePlugin({
|
||||||
const abs = Math.abs(delta);
|
const abs = Math.abs(delta);
|
||||||
const ahead = abs !== delta;
|
const ahead = abs !== delta;
|
||||||
|
|
||||||
const [stringDelta, isSuspectedKotlinDiscord] = this.stringDelta(abs);
|
const stringDelta = abs >= latency ? this.stringDelta(abs) : null;
|
||||||
const isKotlinDiscord = ahead && isSuspectedKotlinDiscord;
|
|
||||||
|
|
||||||
// Also thanks dziurwa
|
// Also thanks dziurwa
|
||||||
// 2 minutes
|
// 2 minutes
|
||||||
const TROLL_LIMIT = 2 * 60;
|
const TROLL_LIMIT = 2 * 60;
|
||||||
const { latency } = this.settings.store;
|
|
||||||
|
|
||||||
const fill: Fill = isKotlinDiscord
|
const fill: Fill = isDiscordKotlin
|
||||||
? ["status-positive", "status-positive", "text-muted"]
|
? ["status-positive", "status-positive", "text-muted"]
|
||||||
: delta >= TROLL_LIMIT || ahead
|
: delta >= TROLL_LIMIT || ahead
|
||||||
? ["text-muted", "text-muted", "text-muted"]
|
? ["text-muted", "text-muted", "text-muted"]
|
||||||
|
@ -103,17 +120,24 @@ export default definePlugin({
|
||||||
? ["status-danger", "text-muted", "text-muted"]
|
? ["status-danger", "text-muted", "text-muted"]
|
||||||
: ["status-warning", "status-warning", "text-muted"];
|
: ["status-warning", "status-warning", "text-muted"];
|
||||||
|
|
||||||
return abs >= latency ? { delta: stringDelta, ahead, fill, isKotlinDiscord } : null;
|
return (abs >= latency || isDiscordKotlin) ? { delta: stringDelta, ahead, fill, isDiscordKotlin } : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
Tooltip() {
|
Tooltip() {
|
||||||
return ErrorBoundary.wrap(({ message }: { message: Message; }) => {
|
return ErrorBoundary.wrap(({ message }: { message: Message; }) => {
|
||||||
|
|
||||||
const d = this.latencyTooltipData(message);
|
const d = this.latencyTooltipData(message);
|
||||||
|
|
||||||
if (!isNonNullish(d)) return null;
|
if (!isNonNullish(d)) return null;
|
||||||
|
|
||||||
|
let text: string;
|
||||||
|
if (!d.delta) {
|
||||||
|
text = "User is suspected to be on an old Discord Android client";
|
||||||
|
} else {
|
||||||
|
text = (d.ahead ? `This user's clock is ${d.delta} ahead.` : `This message was sent with a delay of ${d.delta}.`) + (d.isDiscordKotlin ? " User is suspected to be on an old Discord Android client." : "");
|
||||||
|
}
|
||||||
|
|
||||||
return <Tooltip
|
return <Tooltip
|
||||||
text={d.ahead ? `This user's clock is ${d.delta} ahead. ${d.isKotlinDiscord ? "User is suspected to be on an old mobile client" : ""}` : `This message was sent with a delay of ${d.delta}.`}
|
text={text}
|
||||||
position="top"
|
position="top"
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
|
@ -126,8 +150,9 @@ export default definePlugin({
|
||||||
</Tooltip>;
|
</Tooltip>;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
Icon({ delta, fill, props }: {
|
Icon({ delta, fill, props }: {
|
||||||
delta: string;
|
delta: string | null;
|
||||||
fill: Fill,
|
fill: Fill,
|
||||||
props: {
|
props: {
|
||||||
onClick(): void;
|
onClick(): void;
|
||||||
|
@ -147,7 +172,7 @@ export default definePlugin({
|
||||||
role="img"
|
role="img"
|
||||||
fill="none"
|
fill="none"
|
||||||
style={{ marginRight: "8px", verticalAlign: -1 }}
|
style={{ marginRight: "8px", verticalAlign: -1 }}
|
||||||
aria-label={delta}
|
aria-label={delta ?? "Old Discord Android client"}
|
||||||
aria-hidden="false"
|
aria-hidden="false"
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
ChannelStore,
|
ChannelStore,
|
||||||
|
Constants,
|
||||||
FluxDispatcher,
|
FluxDispatcher,
|
||||||
GuildStore,
|
GuildStore,
|
||||||
IconUtils,
|
IconUtils,
|
||||||
|
@ -132,7 +133,7 @@ async function fetchMessage(channelID: string, messageID: string) {
|
||||||
messageCache.set(messageID, { fetched: false });
|
messageCache.set(messageID, { fetched: false });
|
||||||
|
|
||||||
const res = await RestAPI.get({
|
const res = await RestAPI.get({
|
||||||
url: `/channels/${channelID}/messages`,
|
url: Constants.Endpoints.MESSAGES(channelID),
|
||||||
query: {
|
query: {
|
||||||
limit: 1,
|
limit: 1,
|
||||||
around: messageID
|
around: messageID
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
.messagelogger-deleted {
|
.messagelogger-deleted {
|
||||||
background-color: rgba(240 71 71 / 15%) !important;
|
background-color: hsla(var(--red-430-hsl, 0 85% 61%) / 15%) !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
/* Message content highlighting */
|
/* Message content highlighting */
|
||||||
.messagelogger-deleted [class*="contents"] > :is(div, h1, h2, h3, p) {
|
.messagelogger-deleted [class*="contents"] > :is(div, h1, h2, h3, p) {
|
||||||
color: #f04747 !important;
|
color: var(--status-danger, #f04747) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bot "thinking" text highlighting */
|
/* Bot "thinking" text highlighting */
|
||||||
.messagelogger-deleted [class*="colorStandard"] {
|
.messagelogger-deleted [class*="colorStandard"] {
|
||||||
color: #f04747 !important;
|
color: var(--status-danger, #f04747) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Embed highlighting */
|
/* Embed highlighting */
|
||||||
.messagelogger-deleted article :is(div, span, h1, h2, h3, p) {
|
.messagelogger-deleted article :is(div, span, h1, h2, h3, p) {
|
||||||
color: #f04747 !important;
|
color: var(--status-danger, #f04747) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.messagelogger-deleted a {
|
.messagelogger-deleted a {
|
||||||
color: #be3535 !important;
|
color: var(--red-460, #be3535) !important;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,12 +56,12 @@ export default definePlugin({
|
||||||
find: ".UserProfileSections.USER_INFO_CONNECTIONS:",
|
find: ".UserProfileSections.USER_INFO_CONNECTIONS:",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(?<={user:(\i),onClose:(\i)}\);)(?=case \i\.\i\.MUTUAL_FRIENDS)/,
|
match: /(?<={user:(\i),onClose:(\i)}\);)(?=case \i\.\i\.MUTUAL_FRIENDS)/,
|
||||||
replace: "case \"MUTUAL_GDMS\":return $self.renderMutualGDMs($1,$2);"
|
replace: "case \"MUTUAL_GDMS\":return $self.renderMutualGDMs({user: $1, onClose: $2});"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
renderMutualGDMs: ErrorBoundary.wrap((user: User, onClose: () => void) => {
|
renderMutualGDMs: ErrorBoundary.wrap(({ user, onClose }: { user: User, onClose: () => void; }) => {
|
||||||
const entries = ChannelStore.getSortedPrivateChannels().filter(c => c.isGroupDM() && c.recipients.includes(user.id)).map(c => (
|
const entries = ChannelStore.getSortedPrivateChannels().filter(c => c.isGroupDM() && c.recipients.includes(user.id)).map(c => (
|
||||||
<Clickable
|
<Clickable
|
||||||
className={ProfileListClasses.listRow}
|
className={ProfileListClasses.listRow}
|
||||||
|
|
|
@ -20,10 +20,26 @@ import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByPropsLazy } from "@webpack";
|
||||||
import { GuildStore, i18n, RestAPI } from "@webpack/common";
|
import { Constants, GuildStore, i18n, RestAPI } from "@webpack/common";
|
||||||
|
|
||||||
const { InvitesDisabledExperiment } = findByPropsLazy("InvitesDisabledExperiment");
|
const { InvitesDisabledExperiment } = findByPropsLazy("InvitesDisabledExperiment");
|
||||||
|
|
||||||
|
function showDisableInvites(guildId: string) {
|
||||||
|
// Once the experiment is removed, this should keep working
|
||||||
|
const { enableInvitesDisabled } = InvitesDisabledExperiment?.getCurrentConfig?.({ guildId }) ?? { enableInvitesDisabled: true };
|
||||||
|
// @ts-ignore
|
||||||
|
return enableInvitesDisabled && !GuildStore.getGuild(guildId).hasFeature("INVITES_DISABLED");
|
||||||
|
}
|
||||||
|
|
||||||
|
function disableInvites(guildId: string) {
|
||||||
|
const guild = GuildStore.getGuild(guildId);
|
||||||
|
const features = [...guild.features, "INVITES_DISABLED"];
|
||||||
|
RestAPI.patch({
|
||||||
|
url: Constants.Endpoints.GUILD(guildId),
|
||||||
|
body: { features },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "PauseInvitesForever",
|
name: "PauseInvitesForever",
|
||||||
tags: ["DisableInvitesForever"],
|
tags: ["DisableInvitesForever"],
|
||||||
|
@ -33,44 +49,29 @@ export default definePlugin({
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
find: "Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION",
|
find: "Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION",
|
||||||
replacement: [{
|
group: true,
|
||||||
match: /children:\i\.\i\.\i\.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION/,
|
replacement: [
|
||||||
replace: "children: $self.renderInvitesLabel(arguments[0].guildId, setChecked)",
|
{
|
||||||
},
|
match: /children:\i\.\i\.\i\.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION/,
|
||||||
{
|
replace: "children: $self.renderInvitesLabel({guildId:arguments[0].guildId,setChecked})",
|
||||||
match: /(\i\.hasDMsDisabled\)\(\i\),\[\i,(\i)\]=\i\.useState\(\i\))/,
|
},
|
||||||
replace: "$1,setChecked=$2"
|
{
|
||||||
}]
|
match: /(\i\.hasDMsDisabled\)\(\i\),\[\i,(\i)\]=\i\.useState\(\i\))/,
|
||||||
|
replace: "$1,setChecked=$2"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
showDisableInvites(guildId: string) {
|
renderInvitesLabel: ErrorBoundary.wrap(({ guildId, setChecked }) => {
|
||||||
// Once the experiment is removed, this should keep working
|
|
||||||
const { enableInvitesDisabled } = InvitesDisabledExperiment?.getCurrentConfig?.({ guildId }) ?? { enableInvitesDisabled: true };
|
|
||||||
// @ts-ignore
|
|
||||||
return enableInvitesDisabled && !GuildStore.getGuild(guildId).hasFeature("INVITES_DISABLED");
|
|
||||||
},
|
|
||||||
|
|
||||||
disableInvites(guildId: string) {
|
|
||||||
const guild = GuildStore.getGuild(guildId);
|
|
||||||
const features = [...guild.features, "INVITES_DISABLED"];
|
|
||||||
RestAPI.patch({
|
|
||||||
url: `/guilds/${guild.id}`,
|
|
||||||
body: { features },
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
renderInvitesLabel(guildId: string, setChecked: Function) {
|
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary noop>
|
<div>
|
||||||
<div>
|
{i18n.Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION}
|
||||||
{i18n.Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION}
|
{showDisableInvites(guildId) && <a role="button" onClick={() => {
|
||||||
{this.showDisableInvites(guildId) && <a role="button" onClick={() => {
|
setChecked(true);
|
||||||
setChecked(true);
|
disableInvites(guildId);
|
||||||
this.disableInvites(guildId);
|
}}> Pause Indefinitely.</a>}
|
||||||
}}> Pause Indefinitely.</a>}
|
</div>
|
||||||
</div>
|
|
||||||
</ErrorBoundary>
|
|
||||||
);
|
);
|
||||||
}
|
})
|
||||||
});
|
});
|
||||||
|
|
|
@ -83,7 +83,7 @@ export default definePlugin({
|
||||||
// Rendering
|
// Rendering
|
||||||
{
|
{
|
||||||
match: /"renderRow",(\i)=>{(?<="renderDM",.+?(\i\.default),\{channel:.+?)/,
|
match: /"renderRow",(\i)=>{(?<="renderDM",.+?(\i\.default),\{channel:.+?)/,
|
||||||
replace: "$&if($self.isChannelIndex($1.section, $1.row))return $self.renderChannel($1.section,$1.row,$2);"
|
replace: "$&if($self.isChannelIndex($1.section, $1.row))return $self.renderChannel($1.section,$1.row,$2)();"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
match: /"renderSection",(\i)=>{/,
|
match: /"renderSection",(\i)=>{/,
|
||||||
|
@ -320,25 +320,26 @@ export default definePlugin({
|
||||||
</svg>
|
</svg>
|
||||||
</h2>
|
</h2>
|
||||||
);
|
);
|
||||||
}),
|
}, { noop: true }),
|
||||||
|
|
||||||
renderChannel(sectionIndex: number, index: number, ChannelComponent: React.ComponentType<ChannelComponentProps>) {
|
renderChannel(sectionIndex: number, index: number, ChannelComponent: React.ComponentType<ChannelComponentProps>) {
|
||||||
const { channel, category } = this.getChannel(sectionIndex, index, this.instance.props.channels);
|
return ErrorBoundary.wrap(() => {
|
||||||
|
const { channel, category } = this.getChannel(sectionIndex, index, this.instance.props.channels);
|
||||||
|
|
||||||
if (!channel || !category) return null;
|
if (!channel || !category) return null;
|
||||||
if (this.isChannelHidden(sectionIndex, index)) return null;
|
if (this.isChannelHidden(sectionIndex, index)) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChannelComponent
|
<ChannelComponent
|
||||||
channel={channel}
|
channel={channel}
|
||||||
selected={this.instance.props.selectedChannelId === channel.id}
|
selected={this.instance.props.selectedChannelId === channel.id}
|
||||||
>
|
>
|
||||||
{channel.id}
|
{channel.id}
|
||||||
</ChannelComponent>
|
</ChannelComponent>
|
||||||
);
|
);
|
||||||
|
}, { noop: true });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
getChannel(sectionIndex: number, index: number, channels: Record<string, Channel>) {
|
getChannel(sectionIndex: number, index: number, channels: Record<string, Channel>) {
|
||||||
const category = categories[sectionIndex - 1];
|
const category = categories[sectionIndex - 1];
|
||||||
if (!category) return { channel: null, category: null };
|
if (!category) return { channel: null, category: null };
|
||||||
|
|
|
@ -41,13 +41,18 @@ const settings = definePluginSettings({
|
||||||
description: "Disable filters in Server Discovery search that hide servers that don't meet discovery criteria.",
|
description: "Disable filters in Server Discovery search that hide servers that don't meet discovery criteria.",
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
|
disableDisallowedDiscoveryFilters: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Disable filters in Server Discovery search that hide NSFW & disallowed servers.",
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
migratePluginSettings("ShowHiddenThings", "ShowTimeouts");
|
migratePluginSettings("ShowHiddenThings", "ShowTimeouts");
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "ShowHiddenThings",
|
name: "ShowHiddenThings",
|
||||||
tags: ["ShowTimeouts", "ShowInvitesPaused", "ShowModView", "DisableDiscoveryFilters"],
|
tags: ["ShowTimeouts", "ShowInvitesPaused", "ShowModView", "DisableDiscoveryFilters"],
|
||||||
description: "Displays various moderator-only elements regardless of permissions.",
|
description: "Displays various hidden & moderator-only things regardless of permissions.",
|
||||||
authors: [Devs.Dolfies],
|
authors: [Devs.Dolfies],
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
|
@ -81,6 +86,23 @@ export default definePlugin({
|
||||||
match: /filters:\i\.join\(" AND "\),facets:\[/,
|
match: /filters:\i\.join\(" AND "\),facets:\[/,
|
||||||
replace: "facets:["
|
replace: "facets:["
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: "DiscoveryBannedSearchWords.includes",
|
||||||
|
predicate: () => settings.store.disableDisallowedDiscoveryFilters,
|
||||||
|
replacement: {
|
||||||
|
match: /(?<=function\(\){)(?=.{0,130}DiscoveryBannedSearchWords\.includes)/,
|
||||||
|
replace: "return false;"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: "Endpoints.GUILD_DISCOVERY_VALID_TERM",
|
||||||
|
predicate: () => settings.store.disableDisallowedDiscoveryFilters,
|
||||||
|
all: true,
|
||||||
|
replacement: {
|
||||||
|
match: /\i\.HTTP\.get\(\{url:\i\.Endpoints\.GUILD_DISCOVERY_VALID_TERM,query:\{term:\i\},oldFormErrors:!0\}\);/g,
|
||||||
|
replace: "Promise.resolve({ body: { valid: true } });"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
settings,
|
settings,
|
||||||
|
|
|
@ -20,7 +20,7 @@ import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/Co
|
||||||
import { ImageInvisible, ImageVisible } from "@components/Icons";
|
import { ImageInvisible, ImageVisible } from "@components/Icons";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { Menu, PermissionsBits, PermissionStore, RestAPI, UserStore } from "@webpack/common";
|
import { Constants, Menu, PermissionsBits, PermissionStore, RestAPI, UserStore } from "@webpack/common";
|
||||||
|
|
||||||
const EMBED_SUPPRESSED = 1 << 2;
|
const EMBED_SUPPRESSED = 1 << 2;
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ const messageContextMenuPatch: NavContextMenuPatchCallback = (children, { channe
|
||||||
icon={isEmbedSuppressed ? ImageVisible : ImageInvisible}
|
icon={isEmbedSuppressed ? ImageVisible : ImageInvisible}
|
||||||
action={() =>
|
action={() =>
|
||||||
RestAPI.patch({
|
RestAPI.patch({
|
||||||
url: `/channels/${channel.id}/messages/${messageId}`,
|
url: Constants.Endpoints.MESSAGE(channel.id, messageId),
|
||||||
body: { flags: isEmbedSuppressed ? flags & ~EMBED_SUPPRESSED : flags | EMBED_SUPPRESSED }
|
body: { flags: isEmbedSuppressed ? flags & ~EMBED_SUPPRESSED : flags | EMBED_SUPPRESSED }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,28 +18,30 @@
|
||||||
|
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
|
import { isNonNullish } from "@utils/guards";
|
||||||
import { sleep } from "@utils/misc";
|
import { sleep } from "@utils/misc";
|
||||||
import { Queue } from "@utils/Queue";
|
import { Queue } from "@utils/Queue";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { Constants, FluxDispatcher, RestAPI, UserProfileStore, UserStore, useState } from "@webpack/common";
|
import { Constants, FluxDispatcher, RestAPI, UserProfileStore, UserStore, useState } from "@webpack/common";
|
||||||
import type { ComponentType, ReactNode } from "react";
|
import { type ComponentType, type ReactNode } from "react";
|
||||||
|
|
||||||
// LYING to the type checker here
|
// LYING to the type checker here
|
||||||
const UserFlags = Constants.UserFlags as Record<string, number>;
|
const UserFlags = Constants.UserFlags as Record<string, number>;
|
||||||
const badges: Record<string, ProfileBadge> = {
|
const badges: Record<string, ProfileBadge> = {
|
||||||
"active_developer": { id: "active_developer", description: "Active Developer", icon: "6bdc42827a38498929a4920da12695d9", link: "https://support-dev.discord.com/hc/en-us/articles/10113997751447" },
|
active_developer: { id: "active_developer", description: "Active Developer", icon: "6bdc42827a38498929a4920da12695d9", link: "https://support-dev.discord.com/hc/en-us/articles/10113997751447" },
|
||||||
"bug_hunter_level_1": { id: "bug_hunter_level_1", description: "Discord Bug Hunter", icon: "2717692c7dca7289b35297368a940dd0", link: "https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs" },
|
bug_hunter_level_1: { id: "bug_hunter_level_1", description: "Discord Bug Hunter", icon: "2717692c7dca7289b35297368a940dd0", link: "https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs" },
|
||||||
"bug_hunter_level_2": { id: "bug_hunter_level_2", description: "Discord Bug Hunter", icon: "848f79194d4be5ff5f81505cbd0ce1e6", link: "https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs" },
|
bug_hunter_level_2: { id: "bug_hunter_level_2", description: "Discord Bug Hunter", icon: "848f79194d4be5ff5f81505cbd0ce1e6", link: "https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs" },
|
||||||
"certified_moderator": { id: "certified_moderator", description: "Moderator Programs Alumni", icon: "fee1624003e2fee35cb398e125dc479b", link: "https://discord.com/safety" },
|
certified_moderator: { id: "certified_moderator", description: "Moderator Programs Alumni", icon: "fee1624003e2fee35cb398e125dc479b", link: "https://discord.com/safety" },
|
||||||
"discord_employee": { id: "staff", description: "Discord Staff", icon: "5e74e9b61934fc1f67c65515d1f7e60d", link: "https://discord.com/company" },
|
discord_employee: { id: "staff", description: "Discord Staff", icon: "5e74e9b61934fc1f67c65515d1f7e60d", link: "https://discord.com/company" },
|
||||||
"hypesquad": { id: "hypesquad", description: "HypeSquad Events", icon: "bf01d1073931f921909045f3a39fd264", link: "https://discord.com/hypesquad" },
|
get staff() { return this.discord_employee; },
|
||||||
"hypesquad_online_house_1": { id: "hypesquad_house_1", description: "HypeSquad Bravery", icon: "8a88d63823d8a71cd5e390baa45efa02", link: "https://discord.com/settings/hypesquad-online" },
|
hypesquad: { id: "hypesquad", description: "HypeSquad Events", icon: "bf01d1073931f921909045f3a39fd264", link: "https://discord.com/hypesquad" },
|
||||||
"hypesquad_online_house_2": { id: "hypesquad_house_2", description: "HypeSquad Brilliance", icon: "011940fd013da3f7fb926e4a1cd2e618", link: "https://discord.com/settings/hypesquad-online" },
|
hypesquad_online_house_1: { id: "hypesquad_house_1", description: "HypeSquad Bravery", icon: "8a88d63823d8a71cd5e390baa45efa02", link: "https://discord.com/settings/hypesquad-online" },
|
||||||
"hypesquad_online_house_3": { id: "hypesquad_house_3", description: "HypeSquad Balance", icon: "3aa41de486fa12454c3761e8e223442e", link: "https://discord.com/settings/hypesquad-online" },
|
hypesquad_online_house_2: { id: "hypesquad_house_2", description: "HypeSquad Brilliance", icon: "011940fd013da3f7fb926e4a1cd2e618", link: "https://discord.com/settings/hypesquad-online" },
|
||||||
"partner": { id: "partner", description: "Partnered Server Owner", icon: "3f9748e53446a137a052f3454e2de41e", link: "https://discord.com/partners" },
|
hypesquad_online_house_3: { id: "hypesquad_house_3", description: "HypeSquad Balance", icon: "3aa41de486fa12454c3761e8e223442e", link: "https://discord.com/settings/hypesquad-online" },
|
||||||
"premium": { id: "premium", description: "Subscriber", icon: "2ba85e8026a8614b640c2837bcdfe21b", link: "https://discord.com/settings/premium" },
|
partner: { id: "partner", description: "Partnered Server Owner", icon: "3f9748e53446a137a052f3454e2de41e", link: "https://discord.com/partners" },
|
||||||
"premium_early_supporter": { id: "early_supporter", description: "Early Supporter", icon: "7060786766c9c840eb3019e725d2b358", link: "https://discord.com/settings/premium" },
|
premium: { id: "premium", description: "Subscriber", icon: "2ba85e8026a8614b640c2837bcdfe21b", link: "https://discord.com/settings/premium" },
|
||||||
"verified_developer": { id: "verified_developer", description: "Early Verified Bot Developer", icon: "6df5892e0f35b051f8b61eace34f4967" },
|
premium_early_supporter: { id: "early_supporter", description: "Early Supporter", icon: "7060786766c9c840eb3019e725d2b358", link: "https://discord.com/settings/premium" },
|
||||||
|
verified_developer: { id: "verified_developer", description: "Early Verified Bot Developer", icon: "6df5892e0f35b051f8b61eace34f4967" },
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetching = new Set<string>();
|
const fetching = new Set<string>();
|
||||||
|
@ -73,7 +75,7 @@ async function getUser(id: string) {
|
||||||
if (userObj)
|
if (userObj)
|
||||||
return userObj;
|
return userObj;
|
||||||
|
|
||||||
const user: any = await RestAPI.get({ url: `/users/${id}` }).then(response => {
|
const user: any = await RestAPI.get({ url: Constants.Endpoints.USER(id) }).then(response => {
|
||||||
FluxDispatcher.dispatch({
|
FluxDispatcher.dispatch({
|
||||||
type: "USER_UPDATE",
|
type: "USER_UPDATE",
|
||||||
user: response.body,
|
user: response.body,
|
||||||
|
@ -93,7 +95,8 @@ async function getUser(id: string) {
|
||||||
userObj = UserStore.getUser(id);
|
userObj = UserStore.getUser(id);
|
||||||
const fakeBadges: ProfileBadge[] = Object.entries(UserFlags)
|
const fakeBadges: ProfileBadge[] = Object.entries(UserFlags)
|
||||||
.filter(([_, flag]) => !isNaN(flag) && userObj.hasFlag(flag))
|
.filter(([_, flag]) => !isNaN(flag) && userObj.hasFlag(flag))
|
||||||
.map(([key]) => badges[key.toLowerCase()]);
|
.map(([key]) => badges[key.toLowerCase()])
|
||||||
|
.filter(isNonNullish);
|
||||||
if (user.premium_type || !user.bot && (user.banner || user.avatar?.startsWith?.("a_")))
|
if (user.premium_type || !user.bot && (user.banner || user.avatar?.startsWith?.("a_")))
|
||||||
fakeBadges.push(badges.premium);
|
fakeBadges.push(badges.premium);
|
||||||
|
|
||||||
|
@ -202,6 +205,7 @@ export default definePlugin({
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary noop>
|
<ErrorBoundary noop>
|
||||||
<MentionWrapper
|
<MentionWrapper
|
||||||
|
key={"mention" + data.userId}
|
||||||
RoleMention={RoleMention}
|
RoleMention={RoleMention}
|
||||||
UserMention={UserMention}
|
UserMention={UserMention}
|
||||||
data={data}
|
data={data}
|
||||||
|
|
|
@ -28,7 +28,7 @@ import { useAwaiter } from "@utils/react";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { chooseFile } from "@utils/web";
|
import { chooseFile } from "@utils/web";
|
||||||
import { findByPropsLazy, findStoreLazy } from "@webpack";
|
import { findByPropsLazy, findStoreLazy } from "@webpack";
|
||||||
import { Button, Card, FluxDispatcher, Forms, lodash, Menu, MessageActions, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, SnowflakeUtils, Toasts, useEffect, useState } from "@webpack/common";
|
import { Button, Card, Constants, FluxDispatcher, Forms, lodash, Menu, MessageActions, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, SnowflakeUtils, Toasts, useEffect, useState } from "@webpack/common";
|
||||||
import { ComponentType } from "react";
|
import { ComponentType } from "react";
|
||||||
|
|
||||||
import { VoiceRecorderDesktop } from "./DesktopRecorder";
|
import { VoiceRecorderDesktop } from "./DesktopRecorder";
|
||||||
|
@ -98,7 +98,7 @@ function sendAudio(blob: Blob, meta: AudioMetadata) {
|
||||||
|
|
||||||
upload.on("complete", () => {
|
upload.on("complete", () => {
|
||||||
RestAPI.post({
|
RestAPI.post({
|
||||||
url: `/channels/${channelId}/messages`,
|
url: Constants.Endpoints.MESSAGES(channelId),
|
||||||
body: {
|
body: {
|
||||||
flags: 1 << 13,
|
flags: 1 << 13,
|
||||||
channel_id: channelId,
|
channel_id: channelId,
|
||||||
|
|
|
@ -23,7 +23,7 @@ import { Queue } from "@utils/Queue";
|
||||||
import { useForceUpdater } from "@utils/react";
|
import { useForceUpdater } from "@utils/react";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
|
import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
|
||||||
import { ChannelStore, FluxDispatcher, React, RestAPI, Tooltip } from "@webpack/common";
|
import { ChannelStore, Constants, FluxDispatcher, React, RestAPI, Tooltip } from "@webpack/common";
|
||||||
import { CustomEmoji } from "@webpack/types";
|
import { CustomEmoji } from "@webpack/types";
|
||||||
import { Message, ReactionEmoji, User } from "discord-types/general";
|
import { Message, ReactionEmoji, User } from "discord-types/general";
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ let reactions: Record<string, ReactionCacheEntry>;
|
||||||
function fetchReactions(msg: Message, emoji: ReactionEmoji, type: number) {
|
function fetchReactions(msg: Message, emoji: ReactionEmoji, type: number) {
|
||||||
const key = emoji.name + (emoji.id ? `:${emoji.id}` : "");
|
const key = emoji.name + (emoji.id ? `:${emoji.id}` : "");
|
||||||
return RestAPI.get({
|
return RestAPI.get({
|
||||||
url: `/channels/${msg.channel_id}/messages/${msg.id}/reactions/${key}`,
|
url: Constants.Endpoints.REACTIONS(msg.channel_id, msg.id, key),
|
||||||
query: {
|
query: {
|
||||||
limit: 100,
|
limit: 100,
|
||||||
type
|
type
|
||||||
|
|
|
@ -68,7 +68,6 @@ interface Call {
|
||||||
ringing: string[];
|
ringing: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const MuteStore = findByPropsLazy("isSuppressEveryoneEnabled");
|
|
||||||
const Notifs = findByPropsLazy("makeTextChatNotification");
|
const Notifs = findByPropsLazy("makeTextChatNotification");
|
||||||
const XSLog = new Logger("XSOverlay");
|
const XSLog = new Logger("XSOverlay");
|
||||||
|
|
||||||
|
@ -115,13 +114,13 @@ const settings = definePluginSettings({
|
||||||
},
|
},
|
||||||
timeout: {
|
timeout: {
|
||||||
type: OptionType.NUMBER,
|
type: OptionType.NUMBER,
|
||||||
description: "Notif duration (secs)",
|
description: "Notification duration (secs)",
|
||||||
default: 1.0,
|
default: 3,
|
||||||
},
|
},
|
||||||
timeoutPerCharacter: {
|
lengthBasedTimeout: {
|
||||||
type: OptionType.NUMBER,
|
type: OptionType.BOOLEAN,
|
||||||
description: "Duration multiplier per character",
|
description: "Extend duration with message length",
|
||||||
default: 0.5
|
default: true
|
||||||
},
|
},
|
||||||
opacity: {
|
opacity: {
|
||||||
type: OptionType.SLIDER,
|
type: OptionType.SLIDER,
|
||||||
|
@ -262,12 +261,11 @@ function shouldIgnoreForChannelType(channel: Channel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendMsgNotif(titleString: string, content: string, message: Message) {
|
function sendMsgNotif(titleString: string, content: string, message: Message) {
|
||||||
const timeout = Math.max(settings.store.timeout, content.length * settings.store.timeoutPerCharacter);
|
|
||||||
fetch(`https://cdn.discordapp.com/avatars/${message.author.id}/${message.author.avatar}.png?size=128`).then(response => response.arrayBuffer()).then(result => {
|
fetch(`https://cdn.discordapp.com/avatars/${message.author.id}/${message.author.avatar}.png?size=128`).then(response => response.arrayBuffer()).then(result => {
|
||||||
const msgData = {
|
const msgData = {
|
||||||
messageType: 1,
|
messageType: 1,
|
||||||
index: 0,
|
index: 0,
|
||||||
timeout,
|
timeout: settings.store.lengthBasedTimeout ? calculateTimeout(content) : settings.store.timeout,
|
||||||
height: calculateHeight(content),
|
height: calculateHeight(content),
|
||||||
opacity: settings.store.opacity,
|
opacity: settings.store.opacity,
|
||||||
volume: settings.store.volume,
|
volume: settings.store.volume,
|
||||||
|
@ -286,7 +284,7 @@ function sendOtherNotif(content: string, titleString: string) {
|
||||||
const msgData = {
|
const msgData = {
|
||||||
messageType: 1,
|
messageType: 1,
|
||||||
index: 0,
|
index: 0,
|
||||||
timeout: settings.store.timeout,
|
timeout: settings.store.lengthBasedTimeout ? calculateTimeout(content) : settings.store.timeout,
|
||||||
height: calculateHeight(content),
|
height: calculateHeight(content),
|
||||||
opacity: settings.store.opacity,
|
opacity: settings.store.opacity,
|
||||||
volume: settings.store.volume,
|
volume: settings.store.volume,
|
||||||
|
@ -313,3 +311,10 @@ function calculateHeight(content: string) {
|
||||||
if (content.length <= 300) return 200;
|
if (content.length <= 300) return 200;
|
||||||
return 250;
|
return 250;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function calculateTimeout(content: string) {
|
||||||
|
if (content.length <= 100) return 3;
|
||||||
|
if (content.length <= 200) return 4;
|
||||||
|
if (content.length <= 300) return 5;
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
|
|
@ -475,6 +475,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
|
||||||
ImBanana: {
|
ImBanana: {
|
||||||
name: "Im_Banana",
|
name: "Im_Banana",
|
||||||
id: 635250116688871425n
|
id: 635250116688871425n
|
||||||
|
},
|
||||||
|
xocherry: {
|
||||||
|
name: "xocherry",
|
||||||
|
id: 221288171013406720n
|
||||||
}
|
}
|
||||||
} satisfies Record<string, Dev>);
|
} satisfies Record<string, Dev>);
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { MessageObject } from "@api/MessageEvents";
|
import { MessageObject } from "@api/MessageEvents";
|
||||||
import { ChannelStore, ComponentDispatch, FluxDispatcher, GuildStore, InviteActions, MaskedLink, MessageActions, ModalImageClasses, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common";
|
import { ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, InviteActions, MaskedLink, MessageActions, ModalImageClasses, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common";
|
||||||
import { Guild, Message, User } from "discord-types/general";
|
import { Guild, Message, User } from "discord-types/general";
|
||||||
|
|
||||||
import { ImageModal, ModalRoot, ModalSize, openModal } from "./modal";
|
import { ImageModal, ModalRoot, ModalSize, openModal } from "./modal";
|
||||||
|
@ -162,7 +162,7 @@ export async function fetchUserProfile(id: string, options?: FetchUserProfileOpt
|
||||||
FluxDispatcher.dispatch({ type: "USER_PROFILE_FETCH_START", userId: id });
|
FluxDispatcher.dispatch({ type: "USER_PROFILE_FETCH_START", userId: id });
|
||||||
|
|
||||||
const { body } = await RestAPI.get({
|
const { body } = await RestAPI.get({
|
||||||
url: `/users/${id}/profile`,
|
url: Constants.Endpoints.USER_PROFILE(id),
|
||||||
query: {
|
query: {
|
||||||
with_mutual_guilds: false,
|
with_mutual_guilds: false,
|
||||||
with_mutual_friends_count: false,
|
with_mutual_friends_count: false,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue