mirror of
https://github.com/spacebarchat/server.git
synced 2024-09-20 01:31:34 +02:00
channels
This commit is contained in:
parent
3335f16ad1
commit
4a7811a25c
128846
assets/schemas.json
128846
assets/schemas.json
File diff suppressed because it is too large
Load Diff
@ -16,18 +16,18 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { route } from "@spacebar/api";
|
||||
import {
|
||||
Channel,
|
||||
ChannelDeleteEvent,
|
||||
ChannelModifySchema,
|
||||
ChannelType,
|
||||
ChannelUpdateEvent,
|
||||
emitEvent,
|
||||
Recipient,
|
||||
emitEvent,
|
||||
handleFile,
|
||||
ChannelModifySchema,
|
||||
} from "@spacebar/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@spacebar/api";
|
||||
|
||||
const router: Router = Router();
|
||||
// TODO: delete channel
|
||||
@ -35,7 +35,15 @@ const router: Router = Router();
|
||||
|
||||
router.get(
|
||||
"/",
|
||||
route({ permission: "VIEW_CHANNEL" }),
|
||||
route({
|
||||
permission: "VIEW_CHANNEL",
|
||||
responses: {
|
||||
200: {
|
||||
body: "Channel",
|
||||
},
|
||||
404: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id } = req.params;
|
||||
|
||||
@ -49,7 +57,15 @@ router.get(
|
||||
|
||||
router.delete(
|
||||
"/",
|
||||
route({ permission: "MANAGE_CHANNELS" }),
|
||||
route({
|
||||
permission: "MANAGE_CHANNELS",
|
||||
responses: {
|
||||
200: {
|
||||
body: "Channel",
|
||||
},
|
||||
404: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id } = req.params;
|
||||
|
||||
@ -90,7 +106,19 @@ router.delete(
|
||||
|
||||
router.patch(
|
||||
"/",
|
||||
route({ body: "ChannelModifySchema", permission: "MANAGE_CHANNELS" }),
|
||||
route({
|
||||
body: "ChannelModifySchema",
|
||||
permission: "MANAGE_CHANNELS",
|
||||
responses: {
|
||||
200: {
|
||||
body: "Channel",
|
||||
},
|
||||
404: {},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const payload = req.body as ChannelModifySchema;
|
||||
const { channel_id } = req.params;
|
||||
|
@ -16,19 +16,18 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Router, Request, Response } from "express";
|
||||
import { HTTPError } from "lambert-server";
|
||||
import { route } from "@spacebar/api";
|
||||
import { random } from "@spacebar/api";
|
||||
import { random, route } from "@spacebar/api";
|
||||
import {
|
||||
Channel,
|
||||
Guild,
|
||||
Invite,
|
||||
InviteCreateEvent,
|
||||
emitEvent,
|
||||
User,
|
||||
Guild,
|
||||
PublicInviteRelation,
|
||||
User,
|
||||
emitEvent,
|
||||
} from "@spacebar/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { HTTPError } from "lambert-server";
|
||||
import { isTextChannel } from "./messages";
|
||||
|
||||
const router: Router = Router();
|
||||
@ -39,6 +38,15 @@ router.post(
|
||||
body: "InviteCreateSchema",
|
||||
permission: "CREATE_INSTANT_INVITE",
|
||||
right: "CREATE_INVITES",
|
||||
responses: {
|
||||
201: {
|
||||
body: "Invite",
|
||||
},
|
||||
404: {},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { user_id } = req;
|
||||
@ -84,7 +92,15 @@ router.post(
|
||||
|
||||
router.get(
|
||||
"/",
|
||||
route({ permission: "MANAGE_CHANNELS" }),
|
||||
route({
|
||||
permission: "MANAGE_CHANNELS",
|
||||
responses: {
|
||||
200: {
|
||||
body: "ChannelInvitesResponse",
|
||||
},
|
||||
404: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id } = req.params;
|
||||
const channel = await Channel.findOneOrFail({
|
||||
|
@ -16,6 +16,7 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { route } from "@spacebar/api";
|
||||
import {
|
||||
emitEvent,
|
||||
getPermission,
|
||||
@ -23,7 +24,6 @@ import {
|
||||
ReadState,
|
||||
} from "@spacebar/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@spacebar/api";
|
||||
|
||||
const router = Router();
|
||||
|
||||
@ -33,7 +33,13 @@ const router = Router();
|
||||
|
||||
router.post(
|
||||
"/",
|
||||
route({ body: "MessageAcknowledgeSchema" }),
|
||||
route({
|
||||
body: "MessageAcknowledgeSchema",
|
||||
responses: {
|
||||
200: {},
|
||||
403: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id, message_id } = req.params;
|
||||
|
||||
|
@ -16,14 +16,21 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@spacebar/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.post(
|
||||
"/",
|
||||
route({ permission: "MANAGE_MESSAGES" }),
|
||||
route({
|
||||
permission: "MANAGE_MESSAGES",
|
||||
responses: {
|
||||
200: {
|
||||
body: "Message",
|
||||
},
|
||||
},
|
||||
}),
|
||||
(req: Request, res: Response) => {
|
||||
// TODO:
|
||||
res.json({
|
||||
|
@ -19,24 +19,23 @@
|
||||
import {
|
||||
Attachment,
|
||||
Channel,
|
||||
emitEvent,
|
||||
SpacebarApiErrors,
|
||||
getPermission,
|
||||
getRights,
|
||||
Message,
|
||||
MessageCreateEvent,
|
||||
MessageCreateSchema,
|
||||
MessageDeleteEvent,
|
||||
MessageEditSchema,
|
||||
MessageUpdateEvent,
|
||||
Snowflake,
|
||||
SpacebarApiErrors,
|
||||
emitEvent,
|
||||
getPermission,
|
||||
getRights,
|
||||
uploadFile,
|
||||
MessageCreateSchema,
|
||||
MessageEditSchema,
|
||||
} from "@spacebar/util";
|
||||
import { Router, Response, Request } from "express";
|
||||
import multer from "multer";
|
||||
import { route } from "@spacebar/api";
|
||||
import { handleMessage, postHandleMessage } from "@spacebar/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { HTTPError } from "lambert-server";
|
||||
import multer from "multer";
|
||||
import { handleMessage, postHandleMessage, route } from "../../../../../util";
|
||||
|
||||
const router = Router();
|
||||
// TODO: message content/embed string length limit
|
||||
@ -56,6 +55,16 @@ router.patch(
|
||||
body: "MessageEditSchema",
|
||||
permission: "SEND_MESSAGES",
|
||||
right: "SEND_MESSAGES",
|
||||
responses: {
|
||||
200: {
|
||||
body: "Message",
|
||||
},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
403: {},
|
||||
404: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { message_id, channel_id } = req.params;
|
||||
@ -146,6 +155,16 @@ router.put(
|
||||
body: "MessageCreateSchema",
|
||||
permission: "SEND_MESSAGES",
|
||||
right: "SEND_BACKDATED_EVENTS",
|
||||
responses: {
|
||||
200: {
|
||||
body: "Message",
|
||||
},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
403: {},
|
||||
404: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id, message_id } = req.params;
|
||||
@ -230,7 +249,19 @@ router.put(
|
||||
|
||||
router.get(
|
||||
"/",
|
||||
route({ permission: "VIEW_CHANNEL" }),
|
||||
route({
|
||||
permission: "VIEW_CHANNEL",
|
||||
responses: {
|
||||
200: {
|
||||
body: "Message",
|
||||
},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
403: {},
|
||||
404: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { message_id, channel_id } = req.params;
|
||||
|
||||
@ -252,38 +283,54 @@ router.get(
|
||||
},
|
||||
);
|
||||
|
||||
router.delete("/", route({}), async (req: Request, res: Response) => {
|
||||
const { message_id, channel_id } = req.params;
|
||||
|
||||
const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
|
||||
const message = await Message.findOneOrFail({ where: { id: message_id } });
|
||||
|
||||
const rights = await getRights(req.user_id);
|
||||
|
||||
if (message.author_id !== req.user_id) {
|
||||
if (!rights.has("MANAGE_MESSAGES")) {
|
||||
const permission = await getPermission(
|
||||
req.user_id,
|
||||
channel.guild_id,
|
||||
channel_id,
|
||||
);
|
||||
permission.hasThrow("MANAGE_MESSAGES");
|
||||
}
|
||||
} else rights.hasThrow("SELF_DELETE_MESSAGES");
|
||||
|
||||
await Message.delete({ id: message_id });
|
||||
|
||||
await emitEvent({
|
||||
event: "MESSAGE_DELETE",
|
||||
channel_id,
|
||||
data: {
|
||||
id: message_id,
|
||||
channel_id,
|
||||
guild_id: channel.guild_id,
|
||||
router.delete(
|
||||
"/",
|
||||
route({
|
||||
responses: {
|
||||
204: {},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
404: {},
|
||||
},
|
||||
} as MessageDeleteEvent);
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { message_id, channel_id } = req.params;
|
||||
|
||||
res.sendStatus(204);
|
||||
});
|
||||
const channel = await Channel.findOneOrFail({
|
||||
where: { id: channel_id },
|
||||
});
|
||||
const message = await Message.findOneOrFail({
|
||||
where: { id: message_id },
|
||||
});
|
||||
|
||||
const rights = await getRights(req.user_id);
|
||||
|
||||
if (message.author_id !== req.user_id) {
|
||||
if (!rights.has("MANAGE_MESSAGES")) {
|
||||
const permission = await getPermission(
|
||||
req.user_id,
|
||||
channel.guild_id,
|
||||
channel_id,
|
||||
);
|
||||
permission.hasThrow("MANAGE_MESSAGES");
|
||||
}
|
||||
} else rights.hasThrow("SELF_DELETE_MESSAGES");
|
||||
|
||||
await Message.delete({ id: message_id });
|
||||
|
||||
await emitEvent({
|
||||
event: "MESSAGE_DELETE",
|
||||
channel_id,
|
||||
data: {
|
||||
id: message_id,
|
||||
channel_id,
|
||||
guild_id: channel.guild_id,
|
||||
},
|
||||
} as MessageDeleteEvent);
|
||||
|
||||
res.sendStatus(204);
|
||||
},
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
@ -16,6 +16,7 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { route } from "@spacebar/api";
|
||||
import {
|
||||
Channel,
|
||||
emitEvent,
|
||||
@ -32,8 +33,7 @@ import {
|
||||
PublicUserProjection,
|
||||
User,
|
||||
} from "@spacebar/util";
|
||||
import { route } from "@spacebar/api";
|
||||
import { Router, Response, Request } from "express";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { HTTPError } from "lambert-server";
|
||||
import { In } from "typeorm";
|
||||
|
||||
@ -57,7 +57,17 @@ function getEmoji(emoji: string): PartialEmoji {
|
||||
|
||||
router.delete(
|
||||
"/",
|
||||
route({ permission: "MANAGE_MESSAGES" }),
|
||||
route({
|
||||
permission: "MANAGE_MESSAGES",
|
||||
responses: {
|
||||
204: {},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
404: {},
|
||||
403: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { message_id, channel_id } = req.params;
|
||||
|
||||
@ -83,7 +93,17 @@ router.delete(
|
||||
|
||||
router.delete(
|
||||
"/:emoji",
|
||||
route({ permission: "MANAGE_MESSAGES" }),
|
||||
route({
|
||||
permission: "MANAGE_MESSAGES",
|
||||
responses: {
|
||||
204: {},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
404: {},
|
||||
403: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { message_id, channel_id } = req.params;
|
||||
const emoji = getEmoji(req.params.emoji);
|
||||
@ -120,7 +140,19 @@ router.delete(
|
||||
|
||||
router.get(
|
||||
"/:emoji",
|
||||
route({ permission: "VIEW_CHANNEL" }),
|
||||
route({
|
||||
permission: "VIEW_CHANNEL",
|
||||
responses: {
|
||||
200: {
|
||||
body: "UserPublic",
|
||||
},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
404: {},
|
||||
403: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { message_id, channel_id } = req.params;
|
||||
const emoji = getEmoji(req.params.emoji);
|
||||
@ -148,7 +180,18 @@ router.get(
|
||||
|
||||
router.put(
|
||||
"/:emoji/:user_id",
|
||||
route({ permission: "READ_MESSAGE_HISTORY", right: "SELF_ADD_REACTIONS" }),
|
||||
route({
|
||||
permission: "READ_MESSAGE_HISTORY",
|
||||
right: "SELF_ADD_REACTIONS",
|
||||
responses: {
|
||||
204: {},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
404: {},
|
||||
403: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { message_id, channel_id, user_id } = req.params;
|
||||
if (user_id !== "@me") throw new HTTPError("Invalid user");
|
||||
@ -219,7 +262,16 @@ router.put(
|
||||
|
||||
router.delete(
|
||||
"/:emoji/:user_id",
|
||||
route({}),
|
||||
route({
|
||||
responses: {
|
||||
204: {},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
404: {},
|
||||
403: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
let { user_id } = req.params;
|
||||
const { message_id, channel_id } = req.params;
|
||||
|
@ -16,18 +16,18 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@spacebar/api";
|
||||
import {
|
||||
Channel,
|
||||
Config,
|
||||
emitEvent,
|
||||
getPermission,
|
||||
getRights,
|
||||
MessageDeleteBulkEvent,
|
||||
Message,
|
||||
MessageDeleteBulkEvent,
|
||||
} from "@spacebar/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { HTTPError } from "lambert-server";
|
||||
import { route } from "@spacebar/api";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@ -38,7 +38,17 @@ export default router;
|
||||
// https://discord.com/developers/docs/resources/channel#bulk-delete-messages
|
||||
router.post(
|
||||
"/",
|
||||
route({ body: "BulkDeleteSchema" }),
|
||||
route({
|
||||
body: "BulkDeleteSchema",
|
||||
responses: {
|
||||
204: {},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
403: {},
|
||||
404: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id } = req.params;
|
||||
const channel = await Channel.findOneOrFail({
|
||||
|
@ -16,7 +16,7 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Router, Response, Request } from "express";
|
||||
import { handleMessage, postHandleMessage, route } from "@spacebar/api";
|
||||
import {
|
||||
Attachment,
|
||||
Channel,
|
||||
@ -26,19 +26,19 @@ import {
|
||||
emitEvent,
|
||||
FieldErrors,
|
||||
getPermission,
|
||||
Member,
|
||||
Message,
|
||||
MessageCreateEvent,
|
||||
Snowflake,
|
||||
uploadFile,
|
||||
Member,
|
||||
MessageCreateSchema,
|
||||
Reaction,
|
||||
ReadState,
|
||||
Rights,
|
||||
Reaction,
|
||||
Snowflake,
|
||||
uploadFile,
|
||||
User,
|
||||
} from "@spacebar/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { HTTPError } from "lambert-server";
|
||||
import { handleMessage, postHandleMessage, route } from "@spacebar/api";
|
||||
import multer from "multer";
|
||||
import { FindManyOptions, FindOperator, LessThan, MoreThan } from "typeorm";
|
||||
import { URL } from "url";
|
||||
@ -73,108 +73,123 @@ export function isTextChannel(type: ChannelType): boolean {
|
||||
|
||||
// https://discord.com/developers/docs/resources/channel#create-message
|
||||
// get messages
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
const channel_id = req.params.channel_id;
|
||||
const channel = await Channel.findOneOrFail({
|
||||
where: { id: channel_id },
|
||||
});
|
||||
if (!channel) throw new HTTPError("Channel not found", 404);
|
||||
router.get(
|
||||
"/",
|
||||
route({
|
||||
responses: {
|
||||
200: {
|
||||
body: "ChannelMessagesResponse",
|
||||
},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
403: {},
|
||||
404: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const channel_id = req.params.channel_id;
|
||||
const channel = await Channel.findOneOrFail({
|
||||
where: { id: channel_id },
|
||||
});
|
||||
if (!channel) throw new HTTPError("Channel not found", 404);
|
||||
|
||||
isTextChannel(channel.type);
|
||||
const around = req.query.around ? `${req.query.around}` : undefined;
|
||||
const before = req.query.before ? `${req.query.before}` : undefined;
|
||||
const after = req.query.after ? `${req.query.after}` : undefined;
|
||||
const limit = Number(req.query.limit) || 50;
|
||||
if (limit < 1 || limit > 100)
|
||||
throw new HTTPError("limit must be between 1 and 100", 422);
|
||||
isTextChannel(channel.type);
|
||||
const around = req.query.around ? `${req.query.around}` : undefined;
|
||||
const before = req.query.before ? `${req.query.before}` : undefined;
|
||||
const after = req.query.after ? `${req.query.after}` : undefined;
|
||||
const limit = Number(req.query.limit) || 50;
|
||||
if (limit < 1 || limit > 100)
|
||||
throw new HTTPError("limit must be between 1 and 100", 422);
|
||||
|
||||
const halfLimit = Math.floor(limit / 2);
|
||||
const halfLimit = Math.floor(limit / 2);
|
||||
|
||||
const permissions = await getPermission(
|
||||
req.user_id,
|
||||
channel.guild_id,
|
||||
channel_id,
|
||||
);
|
||||
permissions.hasThrow("VIEW_CHANNEL");
|
||||
if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json([]);
|
||||
const permissions = await getPermission(
|
||||
req.user_id,
|
||||
channel.guild_id,
|
||||
channel_id,
|
||||
);
|
||||
permissions.hasThrow("VIEW_CHANNEL");
|
||||
if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json([]);
|
||||
|
||||
const query: FindManyOptions<Message> & {
|
||||
where: { id?: FindOperator<string> | FindOperator<string>[] };
|
||||
} = {
|
||||
order: { timestamp: "DESC" },
|
||||
take: limit,
|
||||
where: { channel_id },
|
||||
relations: [
|
||||
"author",
|
||||
"webhook",
|
||||
"application",
|
||||
"mentions",
|
||||
"mention_roles",
|
||||
"mention_channels",
|
||||
"sticker_items",
|
||||
"attachments",
|
||||
],
|
||||
};
|
||||
const query: FindManyOptions<Message> & {
|
||||
where: { id?: FindOperator<string> | FindOperator<string>[] };
|
||||
} = {
|
||||
order: { timestamp: "DESC" },
|
||||
take: limit,
|
||||
where: { channel_id },
|
||||
relations: [
|
||||
"author",
|
||||
"webhook",
|
||||
"application",
|
||||
"mentions",
|
||||
"mention_roles",
|
||||
"mention_channels",
|
||||
"sticker_items",
|
||||
"attachments",
|
||||
],
|
||||
};
|
||||
|
||||
if (after) {
|
||||
if (BigInt(after) > BigInt(Snowflake.generate()))
|
||||
return res.status(422);
|
||||
query.where.id = MoreThan(after);
|
||||
} else if (before) {
|
||||
if (BigInt(before) < BigInt(req.params.channel_id))
|
||||
return res.status(422);
|
||||
query.where.id = LessThan(before);
|
||||
} else if (around) {
|
||||
query.where.id = [
|
||||
MoreThan((BigInt(around) - BigInt(halfLimit)).toString()),
|
||||
LessThan((BigInt(around) + BigInt(halfLimit)).toString()),
|
||||
];
|
||||
if (after) {
|
||||
if (BigInt(after) > BigInt(Snowflake.generate()))
|
||||
return res.status(422);
|
||||
query.where.id = MoreThan(after);
|
||||
} else if (before) {
|
||||
if (BigInt(before) < BigInt(req.params.channel_id))
|
||||
return res.status(422);
|
||||
query.where.id = LessThan(before);
|
||||
} else if (around) {
|
||||
query.where.id = [
|
||||
MoreThan((BigInt(around) - BigInt(halfLimit)).toString()),
|
||||
LessThan((BigInt(around) + BigInt(halfLimit)).toString()),
|
||||
];
|
||||
|
||||
return res.json([]); // TODO: fix around
|
||||
}
|
||||
return res.json([]); // TODO: fix around
|
||||
}
|
||||
|
||||
const messages = await Message.find(query);
|
||||
const endpoint = Config.get().cdn.endpointPublic;
|
||||
const messages = await Message.find(query);
|
||||
const endpoint = Config.get().cdn.endpointPublic;
|
||||
|
||||
return res.json(
|
||||
messages.map((x: Partial<Message>) => {
|
||||
(x.reactions || []).forEach((y: Partial<Reaction>) => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
if ((y.user_ids || []).includes(req.user_id)) y.me = true;
|
||||
delete y.user_ids;
|
||||
});
|
||||
if (!x.author)
|
||||
x.author = User.create({
|
||||
id: "4",
|
||||
discriminator: "0000",
|
||||
username: "Spacebar Ghost",
|
||||
public_flags: 0,
|
||||
return res.json(
|
||||
messages.map((x: Partial<Message>) => {
|
||||
(x.reactions || []).forEach((y: Partial<Reaction>) => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
if ((y.user_ids || []).includes(req.user_id)) y.me = true;
|
||||
delete y.user_ids;
|
||||
});
|
||||
if (!x.author)
|
||||
x.author = User.create({
|
||||
id: "4",
|
||||
discriminator: "0000",
|
||||
username: "Fosscord Ghost",
|
||||
public_flags: 0,
|
||||
});
|
||||
x.attachments?.forEach((y: Attachment) => {
|
||||
// dynamically set attachment proxy_url in case the endpoint changed
|
||||
const uri = y.proxy_url.startsWith("http")
|
||||
? y.proxy_url
|
||||
: `https://example.org${y.proxy_url}`;
|
||||
y.proxy_url = `${endpoint == null ? "" : endpoint}${
|
||||
new URL(uri).pathname
|
||||
}`;
|
||||
});
|
||||
x.attachments?.forEach((y: Attachment) => {
|
||||
// dynamically set attachment proxy_url in case the endpoint changed
|
||||
const uri = y.proxy_url.startsWith("http")
|
||||
? y.proxy_url
|
||||
: `https://example.org${y.proxy_url}`;
|
||||
y.proxy_url = `${endpoint == null ? "" : endpoint}${
|
||||
new URL(uri).pathname
|
||||
}`;
|
||||
});
|
||||
|
||||
/**
|
||||
/**
|
||||
Some clients ( discord.js ) only check if a property exists within the response,
|
||||
which causes errors when, say, the `application` property is `null`.
|
||||
**/
|
||||
|
||||
// for (var curr in x) {
|
||||
// if (x[curr] === null)
|
||||
// delete x[curr];
|
||||
// }
|
||||
// for (var curr in x) {
|
||||
// if (x[curr] === null)
|
||||
// delete x[curr];
|
||||
// }
|
||||
|
||||
return x;
|
||||
}),
|
||||
);
|
||||
});
|
||||
return x;
|
||||
}),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
// TODO: config max upload size
|
||||
const messageUpload = multer({
|
||||
@ -208,6 +223,16 @@ router.post(
|
||||
body: "MessageCreateSchema",
|
||||
permission: "SEND_MESSAGES",
|
||||
right: "SEND_MESSAGES",
|
||||
responses: {
|
||||
200: {
|
||||
body: "Message",
|
||||
},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
403: {},
|
||||
404: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id } = req.params;
|
||||
|
@ -19,13 +19,13 @@
|
||||
import {
|
||||
Channel,
|
||||
ChannelPermissionOverwrite,
|
||||
ChannelPermissionOverwriteSchema,
|
||||
ChannelUpdateEvent,
|
||||
emitEvent,
|
||||
Member,
|
||||
Role,
|
||||
ChannelPermissionOverwriteSchema,
|
||||
} from "@spacebar/util";
|
||||
import { Router, Response, Request } from "express";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { HTTPError } from "lambert-server";
|
||||
|
||||
import { route } from "@spacebar/api";
|
||||
@ -38,6 +38,12 @@ router.put(
|
||||
route({
|
||||
body: "ChannelPermissionOverwriteSchema",
|
||||
permission: "MANAGE_ROLES",
|
||||
responses: {
|
||||
204: {},
|
||||
404: {},
|
||||
501: {},
|
||||
400: { body: "APIErrorResponse" },
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id, overwrite_id } = req.params;
|
||||
@ -92,7 +98,7 @@ router.put(
|
||||
// TODO: check permission hierarchy
|
||||
router.delete(
|
||||
"/:overwrite_id",
|
||||
route({ permission: "MANAGE_ROLES" }),
|
||||
route({ permission: "MANAGE_ROLES", responses: { 204: {}, 404: {} } }),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id, overwrite_id } = req.params;
|
||||
|
||||
|
@ -16,23 +16,33 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { route } from "@spacebar/api";
|
||||
import {
|
||||
Channel,
|
||||
ChannelPinsUpdateEvent,
|
||||
Config,
|
||||
DiscordApiErrors,
|
||||
emitEvent,
|
||||
Message,
|
||||
MessageUpdateEvent,
|
||||
DiscordApiErrors,
|
||||
} from "@spacebar/util";
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@spacebar/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
router.put(
|
||||
"/:message_id",
|
||||
route({ permission: "VIEW_CHANNEL" }),
|
||||
route({
|
||||
permission: "VIEW_CHANNEL",
|
||||
responses: {
|
||||
204: {},
|
||||
403: {},
|
||||
404: {},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id, message_id } = req.params;
|
||||
|
||||
@ -74,7 +84,17 @@ router.put(
|
||||
|
||||
router.delete(
|
||||
"/:message_id",
|
||||
route({ permission: "VIEW_CHANNEL" }),
|
||||
route({
|
||||
permission: "VIEW_CHANNEL",
|
||||
responses: {
|
||||
204: {},
|
||||
403: {},
|
||||
404: {},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id, message_id } = req.params;
|
||||
|
||||
@ -114,7 +134,17 @@ router.delete(
|
||||
|
||||
router.get(
|
||||
"/",
|
||||
route({ permission: ["READ_MESSAGE_HISTORY"] }),
|
||||
route({
|
||||
permission: ["READ_MESSAGE_HISTORY"],
|
||||
responses: {
|
||||
200: {
|
||||
body: "ChannelPinsResponse",
|
||||
},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id } = req.params;
|
||||
|
||||
|
@ -16,20 +16,20 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { HTTPError } from "lambert-server";
|
||||
import { route } from "@spacebar/api";
|
||||
import { isTextChannel } from "./messages";
|
||||
import { FindManyOptions, Between, Not, FindOperator } from "typeorm";
|
||||
import {
|
||||
Channel,
|
||||
emitEvent,
|
||||
getPermission,
|
||||
getRights,
|
||||
Message,
|
||||
MessageDeleteBulkEvent,
|
||||
PurgeSchema,
|
||||
emitEvent,
|
||||
getPermission,
|
||||
getRights,
|
||||
} from "@spacebar/util";
|
||||
import { Router, Response, Request } from "express";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { HTTPError } from "lambert-server";
|
||||
import { Between, FindManyOptions, FindOperator, Not } from "typeorm";
|
||||
import { isTextChannel } from "./messages";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@ -42,6 +42,14 @@ router.post(
|
||||
"/",
|
||||
route({
|
||||
/*body: "PurgeSchema",*/
|
||||
responses: {
|
||||
204: {},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
404: {},
|
||||
403: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id } = req.params;
|
||||
|
@ -16,7 +16,7 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@spacebar/api";
|
||||
import {
|
||||
Channel,
|
||||
ChannelRecipientAddEvent,
|
||||
@ -28,80 +28,98 @@ import {
|
||||
Recipient,
|
||||
User,
|
||||
} from "@spacebar/util";
|
||||
import { route } from "@spacebar/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
router.put("/:user_id", route({}), async (req: Request, res: Response) => {
|
||||
const { channel_id, user_id } = req.params;
|
||||
const channel = await Channel.findOneOrFail({
|
||||
where: { id: channel_id },
|
||||
relations: ["recipients"],
|
||||
});
|
||||
router.put(
|
||||
"/:user_id",
|
||||
route({
|
||||
responses: {
|
||||
201: {},
|
||||
404: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id, user_id } = req.params;
|
||||
const channel = await Channel.findOneOrFail({
|
||||
where: { id: channel_id },
|
||||
relations: ["recipients"],
|
||||
});
|
||||
|
||||
if (channel.type !== ChannelType.GROUP_DM) {
|
||||
const recipients = [
|
||||
...(channel.recipients?.map((r) => r.user_id) || []),
|
||||
user_id,
|
||||
].unique();
|
||||
if (channel.type !== ChannelType.GROUP_DM) {
|
||||
const recipients = [
|
||||
...(channel.recipients?.map((r) => r.user_id) || []),
|
||||
user_id,
|
||||
].unique();
|
||||
|
||||
const new_channel = await Channel.createDMChannel(
|
||||
recipients,
|
||||
req.user_id,
|
||||
);
|
||||
return res.status(201).json(new_channel);
|
||||
} else {
|
||||
if (channel.recipients?.map((r) => r.user_id).includes(user_id)) {
|
||||
const new_channel = await Channel.createDMChannel(
|
||||
recipients,
|
||||
req.user_id,
|
||||
);
|
||||
return res.status(201).json(new_channel);
|
||||
} else {
|
||||
if (channel.recipients?.map((r) => r.user_id).includes(user_id)) {
|
||||
throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error?
|
||||
}
|
||||
|
||||
channel.recipients?.push(
|
||||
Recipient.create({ channel_id: channel_id, user_id: user_id }),
|
||||
);
|
||||
await channel.save();
|
||||
|
||||
await emitEvent({
|
||||
event: "CHANNEL_CREATE",
|
||||
data: await DmChannelDTO.from(channel, [user_id]),
|
||||
user_id: user_id,
|
||||
});
|
||||
|
||||
await emitEvent({
|
||||
event: "CHANNEL_RECIPIENT_ADD",
|
||||
data: {
|
||||
channel_id: channel_id,
|
||||
user: await User.findOneOrFail({
|
||||
where: { id: user_id },
|
||||
select: PublicUserProjection,
|
||||
}),
|
||||
},
|
||||
channel_id: channel_id,
|
||||
} as ChannelRecipientAddEvent);
|
||||
return res.sendStatus(204);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
router.delete(
|
||||
"/:user_id",
|
||||
route({
|
||||
responses: {
|
||||
204: {},
|
||||
404: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id, user_id } = req.params;
|
||||
const channel = await Channel.findOneOrFail({
|
||||
where: { id: channel_id },
|
||||
relations: ["recipients"],
|
||||
});
|
||||
if (
|
||||
!(
|
||||
channel.type === ChannelType.GROUP_DM &&
|
||||
(channel.owner_id === req.user_id || user_id === req.user_id)
|
||||
)
|
||||
)
|
||||
throw DiscordApiErrors.MISSING_PERMISSIONS;
|
||||
|
||||
if (!channel.recipients?.map((r) => r.user_id).includes(user_id)) {
|
||||
throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error?
|
||||
}
|
||||
|
||||
channel.recipients?.push(
|
||||
Recipient.create({ channel_id: channel_id, user_id: user_id }),
|
||||
);
|
||||
await channel.save();
|
||||
await Channel.removeRecipientFromChannel(channel, user_id);
|
||||
|
||||
await emitEvent({
|
||||
event: "CHANNEL_CREATE",
|
||||
data: await DmChannelDTO.from(channel, [user_id]),
|
||||
user_id: user_id,
|
||||
});
|
||||
|
||||
await emitEvent({
|
||||
event: "CHANNEL_RECIPIENT_ADD",
|
||||
data: {
|
||||
channel_id: channel_id,
|
||||
user: await User.findOneOrFail({
|
||||
where: { id: user_id },
|
||||
select: PublicUserProjection,
|
||||
}),
|
||||
},
|
||||
channel_id: channel_id,
|
||||
} as ChannelRecipientAddEvent);
|
||||
return res.sendStatus(204);
|
||||
}
|
||||
});
|
||||
|
||||
router.delete("/:user_id", route({}), async (req: Request, res: Response) => {
|
||||
const { channel_id, user_id } = req.params;
|
||||
const channel = await Channel.findOneOrFail({
|
||||
where: { id: channel_id },
|
||||
relations: ["recipients"],
|
||||
});
|
||||
if (
|
||||
!(
|
||||
channel.type === ChannelType.GROUP_DM &&
|
||||
(channel.owner_id === req.user_id || user_id === req.user_id)
|
||||
)
|
||||
)
|
||||
throw DiscordApiErrors.MISSING_PERMISSIONS;
|
||||
|
||||
if (!channel.recipients?.map((r) => r.user_id).includes(user_id)) {
|
||||
throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error?
|
||||
}
|
||||
|
||||
await Channel.removeRecipientFromChannel(channel, user_id);
|
||||
|
||||
return res.sendStatus(204);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
@ -16,15 +16,22 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Channel, emitEvent, Member, TypingStartEvent } from "@spacebar/util";
|
||||
import { route } from "@spacebar/api";
|
||||
import { Router, Request, Response } from "express";
|
||||
import { Channel, emitEvent, Member, TypingStartEvent } from "@spacebar/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
router.post(
|
||||
"/",
|
||||
route({ permission: "SEND_MESSAGES" }),
|
||||
route({
|
||||
permission: "SEND_MESSAGES",
|
||||
responses: {
|
||||
204: {},
|
||||
404: {},
|
||||
403: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id } = req.params;
|
||||
const user_id = req.user_id;
|
||||
|
@ -16,34 +16,56 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@spacebar/api";
|
||||
import {
|
||||
Channel,
|
||||
Config,
|
||||
handleFile,
|
||||
trimSpecial,
|
||||
DiscordApiErrors,
|
||||
User,
|
||||
Webhook,
|
||||
WebhookCreateSchema,
|
||||
WebhookType,
|
||||
handleFile,
|
||||
trimSpecial,
|
||||
} from "@spacebar/util";
|
||||
import crypto from "crypto";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { HTTPError } from "lambert-server";
|
||||
import { isTextChannel } from "./messages/index";
|
||||
import { DiscordApiErrors } from "@spacebar/util";
|
||||
import crypto from "crypto";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
//TODO: implement webhooks
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
res.json([]);
|
||||
});
|
||||
router.get(
|
||||
"/",
|
||||
route({
|
||||
responses: {
|
||||
200: {
|
||||
body: "ChannelWebhooksResponse",
|
||||
},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
res.json([]);
|
||||
},
|
||||
);
|
||||
|
||||
// TODO: use Image Data Type for avatar instead of String
|
||||
router.post(
|
||||
"/",
|
||||
route({ body: "WebhookCreateSchema", permission: "MANAGE_WEBHOOKS" }),
|
||||
route({
|
||||
body: "WebhookCreateSchema",
|
||||
permission: "MANAGE_WEBHOOKS",
|
||||
responses: {
|
||||
200: {
|
||||
body: "WebhookCreateResponse",
|
||||
},
|
||||
400: {
|
||||
body: "APIErrorResponse",
|
||||
},
|
||||
403: {},
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const channel_id = req.params.channel_id;
|
||||
const channel = await Channel.findOneOrFail({
|
||||
|
3
src/util/schemas/responses/ChannelInvitesResponse.ts
Normal file
3
src/util/schemas/responses/ChannelInvitesResponse.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { Invite } from "../../entities";
|
||||
|
||||
export type ChannelInvitesResponse = Invite[];
|
3
src/util/schemas/responses/ChannelMessagesResponse.ts
Normal file
3
src/util/schemas/responses/ChannelMessagesResponse.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { Message } from "../../entities";
|
||||
|
||||
export type ChannelMessagesResponse = Message[];
|
3
src/util/schemas/responses/ChannelPinsResponse.ts
Normal file
3
src/util/schemas/responses/ChannelPinsResponse.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { Message } from "../../entities";
|
||||
|
||||
export type ChannelPinsResponse = Message[];
|
3
src/util/schemas/responses/ChannelWebhooksResponse.ts
Normal file
3
src/util/schemas/responses/ChannelWebhooksResponse.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { Webhook } from "../../entities";
|
||||
|
||||
export type ChannelWebhooksResponse = Webhook[];
|
6
src/util/schemas/responses/WebhookCreateResponse.ts
Normal file
6
src/util/schemas/responses/WebhookCreateResponse.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { User, Webhook } from "../../entities";
|
||||
|
||||
export interface WebhookCreateResponse {
|
||||
user: User;
|
||||
hook: Webhook;
|
||||
}
|
@ -6,6 +6,10 @@ export * from "./ApplicationSkusResponse";
|
||||
export * from "./ApplicationsResponse";
|
||||
export * from "./BackupCodesChallengeResponse";
|
||||
export * from "./CaptchaRequiredResponse";
|
||||
export * from "./ChannelInvitesResponse";
|
||||
export * from "./ChannelPinsResponse";
|
||||
export * from "./ChannelWebhooksResponse";
|
||||
export * from "./GenerateRegistrationTokensResponse";
|
||||
export * from "./LocationMetadataResponse";
|
||||
export * from "./TokenResponse";
|
||||
export * from "./WebhookCreateResponse";
|
||||
|
Loading…
Reference in New Issue
Block a user