diff --git a/src/plusplugins/ToastNotifications/components/NotificationComponent.tsx b/src/plusplugins/ToastNotifications/components/NotificationComponent.tsx
index 2f7d7024..ee4b080e 100644
--- a/src/plusplugins/ToastNotifications/components/NotificationComponent.tsx
+++ b/src/plusplugins/ToastNotifications/components/NotificationComponent.tsx
@@ -1,20 +1,8 @@
/*
- * 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 .
-*/
+ * Vencord, a Discord client mod
+ * Copyright (c) 2025 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
import "./styles.css";
@@ -35,11 +23,21 @@ export default ErrorBoundary.wrap(function NotificationComponent({
dismissOnClick,
index,
onClick,
- onClose
+ onClose,
+ attachments
}: NotificationData & { index?: number; }) {
const [isHover, setIsHover] = useState(false);
const [elapsed, setElapsed] = useState(0);
+ let renderBody: boolean = true;
+ let footer: boolean = false;
+
+ if (attachments > 0)
+ footer = true;
+
+ if (body === "")
+ renderBody = false;
+
// Precompute appearance settings.
const AppearanceSettings = {
position: `toastnotifications-position-${PluginSettings.store.position || "bottom-left"}`,
@@ -115,11 +113,12 @@ export default ErrorBoundary.wrap(function NotificationComponent({
- {richBody ??
{body}
}
+ {renderBody ? richBody ??
{body}
: null}
+ {PluginSettings.store.renderImages && image &&

}
+ {footer &&
{`${attachments} attachment${attachments > 1 ? "s" : ""} ${attachments > 1 ? "were" : "was"} sent.`}
}
- {image &&
}
{AppearanceSettings.timeout !== 0 && !permanent && (
.
-*/
+ * Vencord, a Discord client mod
+ * Copyright (c) 2025 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
import { React, ReactDOM } from "@webpack/common";
-import type { ReactNode } from "react";
+import type { JSX, ReactNode } from "react";
import type { Root } from "react-dom/client";
import { settings as PluginSettings } from "../index";
@@ -51,6 +39,7 @@ export interface NotificationData {
image?: string; // Large image to display in the notification for attachments.
permanent?: boolean; // Whether or not the notification should be permanent or timeout.
dismissOnClick?: boolean; // Whether or not the notification should be dismissed when clicked.
+ attachments: number;
onClick?(): void;
onClose?(): void;
}
diff --git a/src/plusplugins/ToastNotifications/components/styles.css b/src/plusplugins/ToastNotifications/components/styles.css
index a7be76ca..89fd0ba0 100644
--- a/src/plusplugins/ToastNotifications/components/styles.css
+++ b/src/plusplugins/ToastNotifications/components/styles.css
@@ -97,11 +97,21 @@
.toastnotifications-notification-p {
margin: 0.5rem 0 0;
+ margin-bottom: 3px;
line-height: 140%;
+ word-break: break-all;
+}
+
+.toastnotifications-notification-footer {
+ margin: 0;
+ margin-top: 4px;
+ line-height: 140%;
+ font-size: 10px;
}
.toastnotifications-notification-img {
- width: 100%;
+ width: 75%;
+ border-radius: 3px;
}
/* Notification Positioning CSS */
@@ -129,7 +139,8 @@
.toastnotifications-mention-class {
color: var(--mention-foreground);
background: var(--mention-background);
+ /* stylelint-disable-next-line value-no-vendor-prefix */
unicode-bidi: -moz-plaintext;
unicode-bidi: plaintext;
font-weight: 500;
-}
\ No newline at end of file
+}
diff --git a/src/plusplugins/ToastNotifications/index.tsx b/src/plusplugins/ToastNotifications/index.tsx
index e173b611..c13b87f7 100644
--- a/src/plusplugins/ToastNotifications/index.tsx
+++ b/src/plusplugins/ToastNotifications/index.tsx
@@ -1,36 +1,26 @@
/*
- * 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 .
+ * Vencord, a Discord client mod
+ * Copyright (c) 2025 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
*/
import { definePluginSettings } from "@api/Settings";
import { makeRange } from "@components/PluginSettings/components";
-import { Devs } from "@utils/constants";
+import { EquicordDevs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
-import { findByPropsLazy } from "@webpack";
-import { Button, ChannelStore, GuildStore, RelationshipStore, SelectedChannelStore, UserStore } from "@webpack/common";
-import type { Channel, Message, User } from "discord-types/general";
+import { findByPropsLazy, findStore } from "@webpack";
+import { Button, ChannelStore, GuildStore, NavigationRouter, RelationshipStore, SelectedChannelStore, UserStore } from "@webpack/common";
+import { Channel, Message, User } from "discord-types/general";
import { ReactNode } from "react";
-import { Webpack } from "Vencord";
import { NotificationData, showNotification } from "./components/Notifications";
-import { MessageTypes } from "./types";
+import { MessageTypes, RelationshipType, StreamingTreatment } from "./types";
+
+let ignoredUsers: string[] = [];
+let notifyFor: string[] = [];
// Functional variables.
-const MuteStore = Webpack.findByPropsLazy("isSuppressEveryoneEnabled");
+const MuteStore = findByPropsLazy("isSuppressEveryoneEnabled");
const SelectedChannelActionCreators = findByPropsLazy("selectPrivateChannel");
const UserUtils = findByPropsLazy("getGlobalName");
@@ -79,6 +69,72 @@ export const settings = definePluginSettings({
default: 3,
markers: makeRange(1, 5, 1)
},
+ determineServerNotifications: {
+ type: OptionType.BOOLEAN,
+ description: "Automatically determine which server notifications to show based on your channel/guild settings",
+ default: true
+ },
+ disableInStreamerMode: {
+ type: OptionType.BOOLEAN,
+ description: "Disable notifications while in streamer mode",
+ default: true
+ },
+ renderImages: {
+ type: OptionType.BOOLEAN,
+ description: "Render images in notifications",
+ default: true
+ },
+ directMessages: {
+ type: OptionType.BOOLEAN,
+ description: "Show notifications for direct messages",
+ default: true
+ },
+ groupMessages: {
+ type: OptionType.BOOLEAN,
+ description: "Show notifications for group messages",
+ default: true
+ },
+ friendServerNotifications: {
+ type: OptionType.BOOLEAN,
+ description: "Show notifications when friends send messages in servers they share with you",
+ default: true
+ },
+ friendActivity: {
+ type: OptionType.BOOLEAN,
+ description: "Show notifications for adding someone or receiving a friend request",
+ default: true
+ },
+ streamingTreatment: {
+ type: OptionType.SELECT,
+ description: "How to treat notifications while sharing your screen",
+ options: [
+ {
+ label: "Normal - Show notifications as normal",
+ value: StreamingTreatment.NORMAL,
+ default: true
+ },
+ {
+ label: "No Content - Hide notifications body",
+ value: StreamingTreatment.NO_CONTENT
+ },
+ {
+ label: "Ignore - Don't show notifications at all",
+ value: StreamingTreatment.IGNORE
+ }
+ ]
+ },
+ notifyFor: {
+ type: OptionType.STRING,
+ description: "Create a list of channel IDs to receive notifications from (separate with commas)",
+ onChange: () => { notifyFor = stringToList(settings.store.notifyFor); },
+ default: ""
+ },
+ ignoreUsers: {
+ type: OptionType.STRING,
+ description: "Create a list of user IDs to not receive notifications from (separate with commas)",
+ onChange: () => { ignoredUsers = stringToList(settings.store.ignoreUsers); },
+ default: ""
+ },
exampleButton: {
type: OptionType.COMPONENT,
description: "Show an example toast notification",
@@ -89,26 +145,38 @@ export const settings = definePluginSettings({
}
});
-/**
- * getName()
- * Helper function to get a user's nickname if they have one, otherwise their username.
- *
- * @param {User} user The user to get the name of.
- * @returns {String} The name of the user.
- */
+function stringToList(str: string): string[] {
+ if (str !== "") {
+ const array: string[] = [];
+ const string = str.replace(/\s/g, "");
+ const splitArray = string.split(",");
+ splitArray.forEach(id => {
+ array.push(id);
+ });
+
+ return array;
+ }
+ return [];
+}
+
+function limitMessageLength(body: string, hasAttachments: boolean): string {
+ if (hasAttachments) {
+ if (body?.length > 30) {
+ return body.substring(0, 27) + "...";
+ }
+ }
+
+ if (body?.length > 165) {
+ return body.substring(0, 162) + "...";
+ }
+
+ return body;
+}
+
function getName(user: User): string {
return RelationshipStore.getNickname(user.id) ?? UserUtils.getName(user);
}
-/**
- * addMention()
- * Helper function to add a mention to a notification.
- *
- * @param {string} id The id of the user, channel or role.
- * @param {string} type The type of mention.
- * @param {string} guildId The id of the guild.
- * @returns {ReactNode} The mention as a ReactNode.
- */
const addMention = (id: string, type: string, guildId?: string): ReactNode => {
let name;
if (type === "user")
@@ -128,36 +196,51 @@ const addMention = (id: string, type: string, guildId?: string): ReactNode => {
export default definePlugin({
name: "ToastNotifications",
- description: "Show a toast notification whenever you receive a direct message.",
- authors: [Devs.Skully],
+ description: "Receive in-app notifications",
+ authors: [{ name: "Skully", id: 150298098516754432n }, EquicordDevs.Ethan, EquicordDevs.Buzzy],
settings,
flux: {
async MESSAGE_CREATE({ message }: { message: Message; }) {
+
const channel: Channel = ChannelStore.getChannel(message.channel_id);
const currentUser = UserStore.getCurrentUser();
- // Determine whether or not to show notifications.
+ const isStreaming = findStore("ApplicationStreamingStore").getAnyStreamForUser(UserStore.getCurrentUser()?.id);
+
+ const streamerMode = settings.store.disableInStreamerMode;
+ const currentUserStreamerMode = findStore("StreamerModeStore").enabled;
+
+ if (streamerMode && currentUserStreamerMode) return;
+ if (isStreaming && settings.store.streamingTreatment === StreamingTreatment.IGNORE) return;
+
if (
(
- (channel.guild_id) // If this is a guild message and not a private message.
- || (message.author.id === currentUser.id) // If message is from the user.
- || (!MuteStore.allowAllMessages(channel)) // If user has muted the channel.
+ (message.author.id === currentUser.id) // If message is from the user.
|| (channel.id === SelectedChannelStore.getChannelId()) // If the user is currently in the channel.
+ || (ignoredUsers.includes(message.author.id)) // If the user is ignored.
)
) return;
+ if (channel.guild_id) { // If this is a guild message and not a private message.
+ handleGuildMessage(message);
+ return;
+ }
+
+ if (!settings.store.directMessages && channel.isDM() || !settings.store.groupMessages && channel.isGroupDM() || MuteStore.isChannelMuted(null, channel.id)) return;
+
// Prepare the notification.
const Notification: NotificationData = {
title: getName(message.author),
icon: `https://cdn.discordapp.com/avatars/${message.author.id}/${message.author.avatar}.png?size=128`,
body: message.content,
+ attachments: message.attachments?.length,
richBody: null,
permanent: false,
onClick() { SelectedChannelActionCreators.selectPrivateChannel(message.channel_id); }
};
- const notificationText = message.content.length > 0 ? message.content : false;
- const richBodyElements: React.ReactNode[] = [];
+ const notificationText = message.content?.length > 0 ? message.content : false;
+ const richBodyElements: ReactNode[] = [];
// If this channel is a group DM, include the channel name.
if (channel.isGroupDM()) {
@@ -167,7 +250,7 @@ export default definePlugin({
}
// Finally, truncate the channel name if it's too long.
- const truncatedChannelName = channelName.length > 20 ? channelName.substring(0, 20) + "..." : channelName;
+ const truncatedChannelName = channelName?.length > 20 ? channelName.substring(0, 20) + "..." : channelName;
Notification.title = `${message.author.username} (${truncatedChannelName})`;
}
else if (channel.guild_id) // If this is a guild message and not a private message.
@@ -183,14 +266,16 @@ export default definePlugin({
}
case MessageTypes.CHANNEL_RECIPIENT_ADD: {
const actor = UserStore.getUser(message.author.id);
- const targetUser = UserStore.getUser(message.mentions[0]?.id);
+ const user = message.mentions[0];
+ const targetUser = UserStore.getUser((user as any).id);
Notification.body = `${getName(targetUser)} was added to the group by ${getName(actor)}.`;
break;
}
case MessageTypes.CHANNEL_RECIPIENT_REMOVE: {
const actor = UserStore.getUser(message.author.id);
- const targetUser = UserStore.getUser(message.mentions[0]?.id);
+ const user = message.mentions[0];
+ const targetUser = UserStore.getUser((user as any).id);
if (actor.id !== targetUser.id) {
Notification.body = `${getName(targetUser)} was removed from the group by ${getName(actor)}.`;
@@ -214,7 +299,7 @@ export default definePlugin({
}
// Message contains an embed.
- if (message.embeds.length !== 0) {
+ if (message.embeds?.length !== 0) {
Notification.body = notificationText || "Sent an embed.";
}
@@ -224,11 +309,11 @@ export default definePlugin({
}
// Message contains an attachment.
- if (message.attachments.length !== 0) {
+ if (message.attachments?.length !== 0) {
const images = message.attachments.filter(e => typeof e?.content_type === "string" && e?.content_type.startsWith("image"));
// Label the notification with the attachment type.
- if (images.length !== 0) {
- Notification.body = notificationText || "Sent an image.";
+ if (images?.length !== 0) {
+ Notification.body = notificationText || ""; // Dont show any body
Notification.image = images[0].url;
} else {
Notification.body += ` [Attachment: ${message.attachments[0].filename}]`;
@@ -244,7 +329,7 @@ export default definePlugin({
}
// Replace any mention of users, roles and channels.
- if (message.mentions.length !== 0 || message.mentionRoles?.length > 0) {
+ if (message.mentions?.length !== 0 || message.mentionRoles?.length > 0) {
let lastIndex = 0;
Notification.body.replace(USER_MENTION_REGEX, (match, userId, channelId, roleId, offset) => {
richBodyElements.push(Notification.body.slice(lastIndex, offset));
@@ -258,32 +343,229 @@ export default definePlugin({
richBodyElements.push(addMention(roleId, "role", channel.guild_id));
}
- lastIndex = offset + match.length;
+ lastIndex = offset + match?.length;
return match; // This value is not used but is necessary for the replace function
});
}
- if (richBodyElements.length > 0) {
+ if (richBodyElements?.length > 0) {
const MyRichBodyComponent = () => <>{richBodyElements}>;
Notification.richBody = ;
}
+ Notification.body = limitMessageLength(Notification.body, Notification.attachments > 0);
+
+ if (isStreaming && settings.store.streamingTreatment === StreamingTreatment.NO_CONTENT) {
+ Notification.body = "Message content has been redacted.";
+ }
+
+ if (!settings.store.renderImages) {
+ Notification.icon = undefined;
+ }
+
showNotification(Notification);
+ },
+
+ async RELATIONSHIP_ADD({ relationship }) {
+ if (ignoredUsers.includes(relationship.user.id)) return;
+ relationshipAdd(relationship.user, relationship.type);
}
+ },
+
+ start() {
+ ignoredUsers = stringToList(settings.store.ignoreUsers);
+ notifyFor = stringToList(settings.store.notifyFor);
}
});
-/**
- * showExampleNotification()
- * Helper function to show an example notification.
- *
- * @returns {Promise} A promise that resolves when the notification is shown.
- */
+function switchChannels(guildId: string | null, channelId: string) {
+ if (!ChannelStore.hasChannel(channelId)) return;
+ NavigationRouter.transitionTo(`/channels/${guildId ?? "@me"}/${channelId}/`);
+}
+
+enum NotificationLevel {
+ ALL_MESSAGES = 0,
+ ONLY_MENTIONS = 1,
+ NO_MESSAGES = 2
+}
+
+function findNotificationLevel(channel: Channel): NotificationLevel {
+ const store = findStore("UserGuildSettingsStore");
+ const userGuildSettings = store.getAllSettings().userGuildSettings[channel.guild_id];
+
+ if (!settings.store.determineServerNotifications || MuteStore.isGuildOrCategoryOrChannelMuted(channel.guild_id, channel.id)) {
+ return NotificationLevel.NO_MESSAGES;
+ }
+
+ if (userGuildSettings) {
+ const channelOverrides = userGuildSettings.channel_overrides?.[channel.id];
+ const guildDefault = userGuildSettings.message_notifications;
+
+ // Check if channel overrides exist and are in the expected format
+ if (channelOverrides && typeof channelOverrides === "object" && "message_notifications" in channelOverrides) {
+ return channelOverrides.message_notifications;
+ }
+
+ // Check if guild default is in the expected format
+ if (typeof guildDefault === "number") {
+ return guildDefault;
+ }
+ }
+
+ // Return a default value if no valid overrides or guild default is found
+ return NotificationLevel.NO_MESSAGES;
+}
+
+async function handleGuildMessage(message: Message) {
+ const c = ChannelStore.getChannel(message.channel_id);
+ const notificationLevel: number = findNotificationLevel(c);
+ let t = false;
+ // 0: All messages 1: Only mentions 2: No messages
+ // todo: check if the user who sent it is a friend
+ const all = notifyFor.includes(message.channel_id);
+ const friend = settings.store.friendServerNotifications && RelationshipStore.isFriend(message.author.id);
+
+
+
+ if (!all && !friend) {
+ t = true;
+ const isMention: boolean = message.content.includes(`<@${UserStore.getCurrentUser().id}>`);
+ const meetsMentionCriteria = notificationLevel !== NotificationLevel.ALL_MESSAGES && !isMention;
+
+ if (notificationLevel === NotificationLevel.NO_MESSAGES || meetsMentionCriteria) return;
+ }
+
+ const channel: Channel = ChannelStore.getChannel(message.channel_id);
+
+ const notificationText = message.content.length > 0 ? message.content : false;
+ const richBodyElements: React.ReactNode[] = [];
+
+ // Prepare the notification.
+ const Notification: NotificationData = {
+ title: `${getName(message.author)} (#${channel.name})`,
+ icon: `https://cdn.discordapp.com/avatars/${message.author.id}/${message.author.avatar}.png?size=128`,
+ body: message.content,
+ attachments: message.attachments?.length,
+ richBody: null,
+ permanent: false,
+ onClick() { switchChannels(channel.guild_id, channel.id); }
+ };
+
+ if (message.embeds?.length !== 0) {
+ Notification.body = notificationText || "Sent an embed.";
+ }
+
+ // Message contains a sticker.
+ if (message?.stickerItems) {
+ Notification.body = notificationText || "Sent a sticker.";
+ }
+
+ // Message contains an attachment.
+ if (message.attachments?.length !== 0) {
+ const images = message.attachments.filter(e => typeof e?.content_type === "string" && e?.content_type.startsWith("image"));
+ // Label the notification with the attachment type.
+ if (images?.length !== 0) {
+ Notification.body = notificationText || ""; // Dont show any body
+ Notification.image = images[0].url;
+ } else {
+ Notification.body += ` [Attachment: ${message.attachments[0].filename}]`;
+ }
+ }
+
+ // TODO: Format emotes properly.
+ const matches = Notification.body.match(new RegExp("()", "g"));
+ if (matches) {
+ for (const match of matches) {
+ Notification.body = Notification.body.replace(new RegExp(`${match}`, "g"), `:${match.split(":")[1]}:`);
+ }
+ }
+
+ // Replace any mention of users, roles and channels.
+ if (message.mentions?.length !== 0 || message.mentionRoles?.length > 0) {
+ let lastIndex = 0;
+ Notification.body.replace(USER_MENTION_REGEX, (match, userId, channelId, roleId, offset) => {
+ richBodyElements.push(Notification.body.slice(lastIndex, offset));
+
+ // Add the mention itself as a styled span.
+ if (userId) {
+ richBodyElements.push(addMention(userId, "user"));
+ } else if (channelId) {
+ richBodyElements.push(addMention(channelId, "channel"));
+ } else if (roleId) {
+ richBodyElements.push(addMention(roleId, "role", channel.guild_id));
+ }
+
+ lastIndex = offset + match?.length;
+ return match; // This value is not used but is necessary for the replace function
+ });
+ }
+
+ if (richBodyElements?.length > 0) {
+ const MyRichBodyComponent = () => <>{richBodyElements}>;
+ Notification.richBody = ;
+ }
+
+ Notification.body = limitMessageLength(Notification.body, Notification.attachments > 0);
+
+ const isStreaming = findStore("ApplicationStreamingStore").getAnyStreamForUser(UserStore.getCurrentUser()?.id);
+
+ if (isStreaming && settings.store.streamingTreatment === StreamingTreatment.NO_CONTENT) {
+ Notification.body = "Message content has been redacted.";
+ }
+
+ if (!settings.store.renderImages) {
+ Notification.icon = undefined;
+ }
+
+ console.log("Notification that went through: " + t);
+ await showNotification(Notification);
+
+}
+
+async function relationshipAdd(user: User, type: Number) {
+ user = UserStore.getUser(user.id);
+ if (!settings.store.friendActivity) return;
+
+ const Notification: NotificationData = {
+ title: "",
+ icon: user.getAvatarURL(),
+ body: "",
+ attachments: 0,
+ };
+
+ if (!settings.store.renderImages) {
+ Notification.icon = undefined;
+ }
+
+ if (type === RelationshipType.FRIEND) {
+ Notification.title = `${user.username} is now your friend`;
+ Notification.body = "You can now message them directly.";
+ Notification.onClick = () => switchChannels(null, user.id);
+
+
+ await showNotification(Notification);
+
+ } else if (type === RelationshipType.INCOMING_REQUEST) {
+
+ Notification.title = `${user.username} has sent you a friend request`;
+ Notification.body = "You can accept or decline it in the Friends tab.";
+ Notification.onClick = () => switchChannels(null, "");
+
+ await showNotification(Notification);
+ }
+}
+
function showExampleNotification(): Promise {
- return showNotification({
- title: "Example Notification",
+ const Notification: NotificationData = {
+ title: "Example notification",
icon: `https://cdn.discordapp.com/avatars/${UserStore.getCurrentUser().id}/${UserStore.getCurrentUser().avatar}.png?size=128`,
body: "This is an example toast notification!",
+ attachments: 0,
permanent: false
- });
+ };
+
+ if (!settings.store.renderImages) {
+ Notification.icon = undefined;
+ }
+ return showNotification(Notification);
}
diff --git a/src/plusplugins/ToastNotifications/types.ts b/src/plusplugins/ToastNotifications/types.ts
index cf9c2ab6..38cf17b0 100644
--- a/src/plusplugins/ToastNotifications/types.ts
+++ b/src/plusplugins/ToastNotifications/types.ts
@@ -1,20 +1,8 @@
/*
- * Vencord, a modification for Discord's desktop app
- * Copyright (c) 2022 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 .
-*/
+ * Vencord, a Discord client mod
+ * Copyright (c) 2025 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
export const enum MessageTypes {
CHANNEL_RECIPIENT_ADD = 1,
@@ -24,3 +12,16 @@ export const enum MessageTypes {
CHANNEL_ICON_CHANGE = 5,
CHANNEL_PINNED_MESSAGE = 6,
}
+
+export const enum RelationshipType {
+ FRIEND = 1,
+ BLOCKED = 2,
+ INCOMING_REQUEST = 3,
+ OUTGOING_REQUEST = 4,
+}
+
+export const enum StreamingTreatment {
+ NORMAL = 0,
+ NO_CONTENT = 1,
+ IGNORE = 2
+}