fix up searching

This commit is contained in:
MathMan05
2026-02-23 16:14:47 -06:00
parent 7d0a5f5d96
commit f9d2c50aa9

View File

@@ -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 },
};