Merge branch 'fix/categoryNames' into slowcord
This commit is contained in:
commit
3183a3f1f5
@ -1,5 +1,18 @@
|
|||||||
import { Channel, emitEvent, getPermission, getRights, MessageDeleteEvent, Message, MessageUpdateEvent } from "@fosscord/util";
|
import {
|
||||||
|
Attachment,
|
||||||
|
Channel,
|
||||||
|
Embed,
|
||||||
|
emitEvent,
|
||||||
|
getPermission,
|
||||||
|
getRights,
|
||||||
|
Message,
|
||||||
|
MessageCreateEvent,
|
||||||
|
MessageDeleteEvent,
|
||||||
|
MessageUpdateEvent,
|
||||||
|
uploadFile
|
||||||
|
} from "@fosscord/util";
|
||||||
import { Router, Response, Request } from "express";
|
import { Router, Response, Request } from "express";
|
||||||
|
import multer from "multer";
|
||||||
import { route } from "@fosscord/api";
|
import { route } from "@fosscord/api";
|
||||||
import { handleMessage, postHandleMessage } from "@fosscord/api";
|
import { handleMessage, postHandleMessage } from "@fosscord/api";
|
||||||
import { MessageCreateSchema } from "../index";
|
import { MessageCreateSchema } from "../index";
|
||||||
@ -7,6 +20,15 @@ import { MessageCreateSchema } from "../index";
|
|||||||
const router = Router();
|
const router = Router();
|
||||||
// TODO: message content/embed string length limit
|
// TODO: message content/embed string length limit
|
||||||
|
|
||||||
|
const messageUpload = multer({
|
||||||
|
limits: {
|
||||||
|
fileSize: 1024 * 1024 * 100,
|
||||||
|
fields: 10,
|
||||||
|
files: 1
|
||||||
|
},
|
||||||
|
storage: multer.memoryStorage()
|
||||||
|
}); // max upload 50 mb
|
||||||
|
|
||||||
router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGES", right: "SEND_MESSAGES" }), async (req: Request, res: Response) => {
|
router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGES", right: "SEND_MESSAGES" }), async (req: Request, res: Response) => {
|
||||||
const { message_id, channel_id } = req.params;
|
const { message_id, channel_id } = req.params;
|
||||||
var body = req.body as MessageCreateSchema;
|
var body = req.body as MessageCreateSchema;
|
||||||
@ -51,6 +73,68 @@ router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGE
|
|||||||
return res.json(message);
|
return res.json(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Backfill message with specific timestamp
|
||||||
|
router.put(
|
||||||
|
"/",
|
||||||
|
messageUpload.single("file"),
|
||||||
|
async (req, res, next) => {
|
||||||
|
if (req.body.payload_json) {
|
||||||
|
req.body = JSON.parse(req.body.payload_json);
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
route({ body: "MessageCreateSchema", permission: "SEND_MESSAGES", right: "SEND_BACKDATED_EVENTS" }),
|
||||||
|
async (req: Request, res: Response) => {
|
||||||
|
const { channel_id, message_id } = req.params;
|
||||||
|
var body = req.body as MessageCreateSchema;
|
||||||
|
const attachments: Attachment[] = [];
|
||||||
|
|
||||||
|
if (req.file) {
|
||||||
|
try {
|
||||||
|
const file = await uploadFile(`/attachments/${req.params.channel_id}`, req.file);
|
||||||
|
attachments.push({ ...file, proxy_url: file.url });
|
||||||
|
} catch (error) {
|
||||||
|
return res.status(400).json(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients", "recipients.user"] });
|
||||||
|
|
||||||
|
// TODO: check the ID is not from the future, to prevent future-faking of channel histories
|
||||||
|
|
||||||
|
const embeds = body.embeds || [];
|
||||||
|
if (body.embed) embeds.push(body.embed);
|
||||||
|
let message = await handleMessage({
|
||||||
|
...body,
|
||||||
|
type: 0,
|
||||||
|
pinned: false,
|
||||||
|
author_id: req.user_id,
|
||||||
|
id: message_id,
|
||||||
|
embeds,
|
||||||
|
channel_id,
|
||||||
|
attachments,
|
||||||
|
edited_timestamp: undefined,
|
||||||
|
timestamp: undefined, // FIXME: calculate timestamp from snowflake
|
||||||
|
});
|
||||||
|
|
||||||
|
channel.last_message_id = message.id;
|
||||||
|
|
||||||
|
//Fix for the client bug
|
||||||
|
delete message.member
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
message.save(),
|
||||||
|
emitEvent({ event: "MESSAGE_CREATE", channel_id: channel_id, data: message } as MessageCreateEvent),
|
||||||
|
channel.save()
|
||||||
|
]);
|
||||||
|
|
||||||
|
postHandleMessage(message).catch((e) => { }); // no await as it shouldnt block the message send function and silently catch error
|
||||||
|
|
||||||
|
return res.json(message);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
router.get("/", route({ permission: "VIEW_CHANNEL" }), async (req: Request, res: Response) => {
|
router.get("/", route({ permission: "VIEW_CHANNEL" }), async (req: Request, res: Response) => {
|
||||||
const { message_id, channel_id } = req.params;
|
const { message_id, channel_id } = req.params;
|
||||||
|
|
||||||
|
@ -91,7 +91,8 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
|
|||||||
if (opts.message_reference.channel_id !== opts.channel_id) throw new HTTPError("You can only reference messages from this channel");
|
if (opts.message_reference.channel_id !== opts.channel_id) throw new HTTPError("You can only reference messages from this channel");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Q: should be checked if the referenced message exists? ANSWER: NO
|
/** Q: should be checked if the referenced message exists? ANSWER: NO
|
||||||
|
otherwise backfilling won't work **/
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
message.type = MessageType.REPLY;
|
message.type = MessageType.REPLY;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import { BaseClass } from "./BaseClass";
|
|||||||
import { Guild } from "./Guild";
|
import { Guild } from "./Guild";
|
||||||
import { PublicUserProjection, User } from "./User";
|
import { PublicUserProjection, User } from "./User";
|
||||||
import { HTTPError } from "lambert-server";
|
import { HTTPError } from "lambert-server";
|
||||||
import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial, InvisibleCharacters } from "../util";
|
import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial, InvisibleCharacters, ChannelTypes } from "../util";
|
||||||
import { ChannelCreateEvent, ChannelRecipientRemoveEvent } from "../interfaces";
|
import { ChannelCreateEvent, ChannelRecipientRemoveEvent } from "../interfaces";
|
||||||
import { Recipient } from "./Recipient";
|
import { Recipient } from "./Recipient";
|
||||||
import { Message } from "./Message";
|
import { Message } from "./Message";
|
||||||
@ -173,12 +173,20 @@ export class Channel extends BaseClass {
|
|||||||
if (channel.name.includes(character))
|
if (channel.name.includes(character))
|
||||||
throw new HTTPError("Channel name cannot include invalid characters", 403);
|
throw new HTTPError("Channel name cannot include invalid characters", 403);
|
||||||
|
|
||||||
|
// Categories skip these checks on discord.com
|
||||||
|
if (channel.type !== ChannelType.GUILD_CATEGORY) {
|
||||||
|
if (channel.name.includes(" "))
|
||||||
|
throw new HTTPError("Channel name cannot include invalid characters", 403);
|
||||||
|
|
||||||
if (channel.name.match(/\-\-+/g))
|
if (channel.name.match(/\-\-+/g))
|
||||||
throw new HTTPError("Channel name cannot include multiple adjacent dashes.", 403)
|
throw new HTTPError("Channel name cannot include multiple adjacent dashes.", 403);
|
||||||
|
|
||||||
if (channel.name.charAt(0) === "-" ||
|
if (channel.name.charAt(0) === "-" ||
|
||||||
channel.name.charAt(channel.name.length - 1) === "-")
|
channel.name.charAt(channel.name.length - 1) === "-")
|
||||||
throw new HTTPError("Channel name cannot start/end with dash.", 403)
|
throw new HTTPError("Channel name cannot start/end with dash.", 403);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
channel.name = channel.name.trim(); //category names are trimmed client side on discord.com
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!guild.features.includes("ALLOW_UNNAMED_CHANNELS")) {
|
if (!guild.features.includes("ALLOW_UNNAMED_CHANNELS")) {
|
||||||
@ -357,7 +365,6 @@ export class Channel extends BaseClass {
|
|||||||
isWritable() {
|
isWritable() {
|
||||||
const disallowedChannelTypes = [
|
const disallowedChannelTypes = [
|
||||||
ChannelType.GUILD_CATEGORY,
|
ChannelType.GUILD_CATEGORY,
|
||||||
ChannelType.GUILD_VOICE, // TODO: Remove this when clients can send messages to voice channels on discord.com
|
|
||||||
ChannelType.GUILD_STAGE_VOICE,
|
ChannelType.GUILD_STAGE_VOICE,
|
||||||
ChannelType.VOICELESS_WHITEBOARD,
|
ChannelType.VOICELESS_WHITEBOARD,
|
||||||
];
|
];
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// List from https://invisible-characters.com/
|
// List from https://invisible-characters.com/
|
||||||
export const InvisibleCharacters = [
|
export const InvisibleCharacters = [
|
||||||
'\u{9}', //Tab
|
'\u{9}', //Tab
|
||||||
'\u{20}', //Space
|
//'\u{20}', //Space //categories can have spaces in them
|
||||||
'\u{ad}', //Soft hyphen
|
'\u{ad}', //Soft hyphen
|
||||||
'\u{34f}', //Combining grapheme joiner
|
'\u{34f}', //Combining grapheme joiner
|
||||||
'\u{61c}', //Arabic letter mark
|
'\u{61c}', //Arabic letter mark
|
||||||
|
Loading…
x
Reference in New Issue
Block a user