feat: support for everyone/online/role mentions on messages

This commit is contained in:
izzy
2025-06-04 15:46:17 +01:00
parent 35f95ca0b6
commit c4a5db51fe
5 changed files with 102 additions and 6 deletions
+25 -1
View File
@@ -11,12 +11,14 @@ import { decodeTime } from "ulid";
import type { Client } from "../Client.js";
import type { MessageCollection } from "../collections/MessageCollection.js";
import { MessageFlags } from "../hydration/message.js";
import type { Channel } from "./Channel.js";
import { File } from "./File.js";
import type { MessageEmbed } from "./MessageEmbed.js";
import type { Server } from "./Server.js";
import type { ServerMember } from "./ServerMember.js";
import { ServerRole } from "./ServerRole.js";
import type { SystemMessage } from "./SystemMessage.js";
import type { User } from "./User.js";
@@ -177,11 +179,33 @@ export class Message {
return this.#collection.getUnderlyingObject(this.id).mentionIds;
}
/**
* IDs of roles this message mentions
*/
get roleMentionIds(): string[] | undefined {
return this.#collection.getUnderlyingObject(this.id).roleMentionIds;
}
/**
* Roles this message mentions
*/
get roleMentions(): ServerRole[] | undefined {
return this.roleMentionIds
?.map((roleId) => this.server?.roles.get(roleId) as ServerRole)
.filter((role) => role);
}
/**
* Whether this message mentions us
*/
get mentioned(): boolean {
return this.mentionIds?.includes(this.#collection.client.user!.id) ?? false;
return (
!!(this.flags & MessageFlags.MentionsEveryone) ||
!!(this.flags & MessageFlags.MentionsOnline) ||
this.mentionIds?.includes(this.#collection.client.user!.id) ||
this.roleMentions?.some((role) => role.assigned) ||
false
);
}
/**
+47
View File
@@ -0,0 +1,47 @@
import type { Role as APIRole, OverrideField } from "revolt-api";
import type { Client } from "../Client.js";
/**
* Server Role
*/
export class ServerRole {
protected client: Client;
protected serverId: string;
readonly id: string;
readonly name: string;
readonly permissions: OverrideField;
readonly colour?: string;
readonly hoist: boolean;
readonly rank: number;
/**
* Construct server role
* @param client Client
* @param serverId Server ID
* @param id Role ID
* @param data Role data
*/
constructor(client: Client, serverId: string, id: string, data: APIRole) {
this.client = client;
this.serverId = serverId;
this.id = id;
this.name = data.name;
this.permissions = data.permissions;
this.colour = data.colour ?? undefined;
this.hoist = data.hoist || false;
this.rank = data.rank ?? 0;
}
/**
* Whether this role is assigned to our server member
*/
get assigned() {
return (
this.client.servers.get(this.serverId)?.member?.roles.includes(this.id) ||
false
);
}
}
+1
View File
@@ -10,6 +10,7 @@ export * from "./Message.js";
export * from "./MessageEmbed.js";
export * from "./PublicBot.js";
export * from "./PublicInvite.js";
export * from "./ServerRole.js";
export * from "./Server.js";
export * from "./ServerBan.js";
export * from "./ServerMember.js";
+22 -1
View File
@@ -23,11 +23,12 @@ export type HydratedMessage = {
editedAt?: Date;
embeds?: MessageEmbed[];
mentionIds?: string[];
roleMentionIds?: string[];
replyIds?: string[];
reactions: ReactiveMap<string, ReactiveSet<string>>;
interactions?: Interactions;
masquerade?: Masquerade;
flags?: number;
flags?: MessageFlags;
};
export const messageHydration: Hydrate<Merge<Message>, HydratedMessage> = {
@@ -58,6 +59,7 @@ export const messageHydration: Hydrate<Merge<Message>, HydratedMessage> = {
embeds: (message, ctx) =>
message.embeds!.map((embed) => MessageEmbed.from(ctx as Client, embed)),
mentionIds: (message) => message.mentions!,
roleMentionIds: (message) => message.role_mentions!,
replyIds: (message) => message.replies!,
reactions: (message) => {
const map = new ReactiveMap<string, ReactiveSet<string>>();
@@ -76,3 +78,22 @@ export const messageHydration: Hydrate<Merge<Message>, HydratedMessage> = {
reactions: new ReactiveMap(),
}),
};
/**
* Flags attributed to messages
*/
export enum MessageFlags {
/**
* Message will not send push / desktop notifications
*/
SuppressNotifications = 1,
/**
* Message will mention all users who can see the channel
*/
MentionsEveryone = 2,
/**
* Message will mention all users who are online and can see the channel.
* This cannot be true if MentionsEveryone is true
*/
MentionsOnline = 3,
}
+7 -4
View File
@@ -3,12 +3,12 @@ import { ReactiveSet } from "@solid-primitives/set";
import type {
Server as APIServer,
Category,
Role,
SystemMessageChannels,
} from "revolt-api";
import type { Client } from "../Client.js";
import { File } from "../classes/File.js";
import { ServerRole } from "../classes/ServerRole.js";
import type { Hydrate } from "./index.js";
@@ -26,7 +26,7 @@ export type HydratedServer = {
categories?: Category[];
systemMessages?: SystemMessageChannels;
roles: ReactiveMap<string, Role>;
roles: ReactiveMap<string, ServerRole>;
defaultPermissions: number;
flags: ServerFlags;
@@ -51,9 +51,12 @@ export const serverHydration: Hydrate<APIServer, HydratedServer> = {
channelIds: (server) => new ReactiveSet(server.channels),
categories: (server) => server.categories ?? [],
systemMessages: (server) => server.system_messages ?? {},
roles: (server) =>
roles: (server, ctx) =>
new ReactiveMap(
Object.keys(server.roles!).map((id) => [id, server.roles![id]]),
Object.keys(server.roles!).map((id) => [
id,
new ServerRole(ctx as Client, server._id, id, server.roles![id]),
]),
),
defaultPermissions: (server) => server.default_permissions,
icon: (server, ctx) => new File(ctx as Client, server.icon!),