diff --git a/src/api/routes/guilds/#guild_id/messages/search.ts b/src/api/routes/guilds/#guild_id/messages/search.ts
index a762e529..eb9ecd6d 100644
--- a/src/api/routes/guilds/#guild_id/messages/search.ts
+++ b/src/api/routes/guilds/#guild_id/messages/search.ts
@@ -19,10 +19,10 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { route } from "@spacebar/api";
-import { Channel, FieldErrors, Message, getPermission } from "@spacebar/util";
+import { Channel, FieldErrors, Member, Message, Snowflake, getPermission } from "@spacebar/util";
import { Request, Response, Router } from "express";
import { HTTPError } from "lambert-server";
-import { FindManyOptions, In, Like } from "typeorm";
+import { Between, FindManyOptions, FindOptionsWhere, In, LessThan, Like, MoreThan } from "typeorm";
const router: Router = Router({ mergeParams: true });
@@ -43,16 +43,17 @@ router.get(
}),
async (req: Request, res: Response) => {
const {
- channel_id,
content,
// include_nsfw, // TODO
offset,
sort_order,
// sort_by, // TODO: Handle 'relevance'
limit,
- author_id,
+ max_id,
+ min_id,
} = req.query as Record<string, string>;
-
+ const { author_id } = req.query as Record<string, string[] | string>;
+ let { channel_id, mentions } = req.query as Record<string, string[] | string>;
const parsedLimit = Number(limit) || 50;
if (parsedLimit < 1 || parsedLimit > 100) throw new HTTPError("limit must be between 1 and 100", 422);
@@ -65,43 +66,98 @@ router.get(
},
}); // todo this is wrong
}
-
- const permissions = await getPermission(req.user_id, req.params.guild_id as string, channel_id as string | undefined);
- permissions.hasThrow("VIEW_CHANNEL");
- if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json({ messages: [], total_results: 0 });
+ if (channel_id) {
+ const ids = new Set(channel_id instanceof Array ? channel_id : [channel_id]);
+ Promise.all(
+ [...ids].map(async (id) => {
+ const permissions = await getPermission(req.user_id, req.params.guild_id as string, id);
+ permissions.hasThrow("VIEW_CHANNEL");
+ if (!permissions.has("READ_MESSAGE_HISTORY")) ids.delete(id);
+ }),
+ );
+ if (ids.size === 0) {
+ res.json({ messages: [], total_results: 0 });
+ } else if (ids.size === 1) {
+ channel_id = [...ids][0];
+ } else {
+ channel_id = [...ids];
+ }
+ } else {
+ const permissions = await getPermission(req.user_id, req.params.guild_id as string);
+ permissions.hasThrow("VIEW_CHANNEL");
+ if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json({ messages: [], total_results: 0 });
+ }
+ const minStamp = min_id ? Snowflake.deconstruct(min_id).timestamp : 0;
+ const maxStamp = max_id ? Snowflake.deconstruct(max_id).timestamp : 0;
+ const where: FindOptionsWhere<Message> = {
+ guild: {
+ id: req.params.guild_id as string,
+ },
+ ...(content ? { content: Like(`%${content}%`) } : {}),
+ ...(author_id ? (author_id instanceof Array ? { author_id: In(author_id) } : { author_id }) : {}),
+ ...(channel_id
+ ? channel_id instanceof Array
+ ? { channel_id: In(channel_id) }
+ : { channel_id }
+ : {
+ channel_id: In(
+ (
+ await Promise.all(
+ (
+ await Channel.find({
+ where: { guild_id: req.params.guild_id as string },
+ select: { id: true },
+ })
+ ).map(async (channel) => {
+ const perm = await getPermission(req.user_id, req.params.guild_id as string, channel.id);
+ return perm.has("VIEW_CHANNEL") && perm.has("READ_MESSAGE_HISTORY") ? channel : undefined;
+ }),
+ )
+ )
+ .filter((_) => _ !== undefined)
+ .map(({ id }) => id),
+ ),
+ }),
+ ...(minStamp
+ ? maxStamp
+ ? { timestamp: Between(new Date(minStamp), new Date(maxStamp)) }
+ : { timestamp: MoreThan(new Date(minStamp)) }
+ : maxStamp
+ ? { timestamp: LessThan(new Date(maxStamp)) }
+ : {}),
+ };
+ mentions = mentions instanceof Array ? mentions : mentions ? [mentions] : [];
+ let roleids = [] as string[];
+ if (mentions) {
+ const ms = await Member.find({ where: { id: In(mentions), guild_id: req.params.guild_id as string }, relations: ["roles"] });
+ const rSet = new Set<string>();
+ ms.forEach((memb) => {
+ memb.roles.forEach(({ id }) => rSet.add(id));
+ });
+ roleids = [...rSet];
+ }
const query: FindManyOptions<Message> = {
order: {
timestamp: sort_order ? (sort_order.toUpperCase() as "ASC" | "DESC") : "DESC",
},
- where: {
- guild: {
- id: req.params.guild_id as string,
- },
- ...(content ? { content: Like(`%${content}%`) } : {}),
- ...(author_id ? { author_id } : {}),
- ...(channel_id
- ? { channel_id }
- : {
- channel_id: In(
- (
- await Promise.all(
- (
- await Channel.find({
- where: { guild_id: req.params.guild_id as string },
- select: { id: true },
- })
- ).map(async (channel) => {
- const perm = await getPermission(req.user_id, req.params.guild_id as string, channel.id);
- return perm.has("VIEW_CHANNEL") && perm.has("READ_MESSAGE_HISTORY") ? channel : undefined;
- }),
- )
- )
- .filter((_) => _ !== undefined)
- .map(({ id }) => id),
- ),
- }),
- },
+ where: mentions.length
+ ? [
+ { ...where, mention_everyone: true },
+ {
+ ...where,
+ mentions: {
+ id: In(mentions),
+ },
+ },
+ {
+ ...where,
+ mention_roles: {
+ id: In(roleids),
+ },
+ },
+ ]
+ : where,
relations: { author: true, webhook: true, application: true, mentions: true, mention_roles: true, mention_channels: true, sticker_items: true, attachments: true },
};
|