Merge branch 'fosscord:master' into master
This commit is contained in:
commit
edd5cf651c
@ -37,7 +37,11 @@ export function isTextChannel(type: ChannelType): boolean {
|
|||||||
case ChannelType.GUILD_PUBLIC_THREAD:
|
case ChannelType.GUILD_PUBLIC_THREAD:
|
||||||
case ChannelType.GUILD_PRIVATE_THREAD:
|
case ChannelType.GUILD_PRIVATE_THREAD:
|
||||||
case ChannelType.GUILD_TEXT:
|
case ChannelType.GUILD_TEXT:
|
||||||
|
case ChannelType.ENCRYPTED:
|
||||||
|
case ChannelType.ENCRYPTED_THREAD:
|
||||||
return true;
|
return true;
|
||||||
|
default:
|
||||||
|
throw new HTTPError("unimplemented", 400);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +91,7 @@ router.get("/", async (req: Request, res: Response) => {
|
|||||||
permissions.hasThrow("VIEW_CHANNEL");
|
permissions.hasThrow("VIEW_CHANNEL");
|
||||||
if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json([]);
|
if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json([]);
|
||||||
|
|
||||||
var query: FindManyOptions<Message> & { where: { id?: any } } = {
|
var query: FindManyOptions<Message> & { where: { id?: any; }; } = {
|
||||||
order: { id: "DESC" },
|
order: { id: "DESC" },
|
||||||
take: limit,
|
take: limit,
|
||||||
where: { channel_id },
|
where: { channel_id },
|
||||||
@ -216,7 +220,7 @@ router.post(
|
|||||||
channel.save()
|
channel.save()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
postHandleMessage(message).catch((e) => {}); // no await as it shouldnt block the message send function and silently catch error
|
postHandleMessage(message).catch((e) => { }); // no await as it shouldnt block the message send function and silently catch error
|
||||||
|
|
||||||
return res.json(message);
|
return res.json(message);
|
||||||
}
|
}
|
||||||
|
@ -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 } from "../util";
|
import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial, InvisibleCharacters } 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";
|
||||||
@ -21,11 +21,14 @@ export enum ChannelType {
|
|||||||
GUILD_CATEGORY = 4, // an organizational category that contains up to 50 channels
|
GUILD_CATEGORY = 4, // an organizational category that contains up to 50 channels
|
||||||
GUILD_NEWS = 5, // a channel that users can follow and crosspost into their own server
|
GUILD_NEWS = 5, // a channel that users can follow and crosspost into their own server
|
||||||
GUILD_STORE = 6, // a channel in which game developers can sell their game on Discord
|
GUILD_STORE = 6, // a channel in which game developers can sell their game on Discord
|
||||||
// TODO: what are channel types between 7-9?
|
ENCRYPTED = 7, // end-to-end encrypted channel
|
||||||
|
ENCRYPTED_THREAD = 8, // end-to-end encrypted thread channel
|
||||||
GUILD_NEWS_THREAD = 10, // a temporary sub-channel within a GUILD_NEWS channel
|
GUILD_NEWS_THREAD = 10, // a temporary sub-channel within a GUILD_NEWS channel
|
||||||
GUILD_PUBLIC_THREAD = 11, // a temporary sub-channel within a GUILD_TEXT channel
|
GUILD_PUBLIC_THREAD = 11, // a temporary sub-channel within a GUILD_TEXT channel
|
||||||
GUILD_PRIVATE_THREAD = 12, // a temporary sub-channel within a GUILD_TEXT channel that is only viewable by those invited and those with the MANAGE_THREADS permission
|
GUILD_PRIVATE_THREAD = 12, // a temporary sub-channel within a GUILD_TEXT channel that is only viewable by those invited and those with the MANAGE_THREADS permission
|
||||||
GUILD_STAGE_VOICE = 13, // a voice channel for hosting events with an audience
|
GUILD_STAGE_VOICE = 13, // a voice channel for hosting events with an audience
|
||||||
|
CUSTOM_START = 64, // start custom channel types from here
|
||||||
|
UNHANDLED = 255 // unhandled unowned pass-through channel type
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity("channels")
|
@Entity("channels")
|
||||||
@ -147,6 +150,7 @@ export class Channel extends BaseClass {
|
|||||||
skipExistsCheck?: boolean;
|
skipExistsCheck?: boolean;
|
||||||
skipPermissionCheck?: boolean;
|
skipPermissionCheck?: boolean;
|
||||||
skipEventEmit?: boolean;
|
skipEventEmit?: boolean;
|
||||||
|
skipNameChecks?: boolean;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
if (!opts?.skipPermissionCheck) {
|
if (!opts?.skipPermissionCheck) {
|
||||||
@ -155,6 +159,27 @@ export class Channel extends BaseClass {
|
|||||||
permissions.hasThrow("MANAGE_CHANNELS");
|
permissions.hasThrow("MANAGE_CHANNELS");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!opts?.skipNameChecks) {
|
||||||
|
const guild = await Guild.findOneOrFail({ id: channel.guild_id });
|
||||||
|
if (!guild.features.includes("ALLOW_INVALID_CHANNEL_NAMES") && channel.name) {
|
||||||
|
for (var character of InvisibleCharacters)
|
||||||
|
if (channel.name.includes(character))
|
||||||
|
throw new HTTPError("Channel name cannot include invalid characters", 403);
|
||||||
|
|
||||||
|
if (channel.name.match(/\-\-+/g))
|
||||||
|
throw new HTTPError("Channel name cannot include multiple adjacent dashes.", 403)
|
||||||
|
|
||||||
|
if (channel.name.charAt(0) === "-" ||
|
||||||
|
channel.name.charAt(channel.name.length - 1) === "-")
|
||||||
|
throw new HTTPError("Channel name cannot start/end with dash.", 403)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!guild.features.includes("ALLOW_UNNAMED_CHANNELS")) {
|
||||||
|
if (!channel.name)
|
||||||
|
throw new HTTPError("Channel name cannot be empty.", 403);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (channel.type) {
|
switch (channel.type) {
|
||||||
case ChannelType.GUILD_TEXT:
|
case ChannelType.GUILD_TEXT:
|
||||||
case ChannelType.GUILD_VOICE:
|
case ChannelType.GUILD_VOICE:
|
||||||
@ -239,7 +264,7 @@ export class Channel extends BaseClass {
|
|||||||
channel = await new Channel({
|
channel = await new Channel({
|
||||||
name,
|
name,
|
||||||
type,
|
type,
|
||||||
owner_id: type === ChannelType.DM ? undefined : creator_user_id,
|
owner_id: type === ChannelType.DM ? undefined : null, // 1:1 DMs are ownerless in fosscord-server
|
||||||
created_at: new Date(),
|
created_at: new Date(),
|
||||||
last_message_id: null,
|
last_message_id: null,
|
||||||
recipients: channelRecipients.map(
|
recipients: channelRecipients.map(
|
||||||
@ -286,9 +311,9 @@ export class Channel extends BaseClass {
|
|||||||
user_id: user_id,
|
user_id: user_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
//If the owner leave we make the first recipient in the list the new owner
|
//If the owner leave the server user is the new owner
|
||||||
if (channel.owner_id === user_id) {
|
if (channel.owner_id === user_id) {
|
||||||
channel.owner_id = channel.recipients!.find((r) => r.user_id !== user_id)!.user_id; //Is there a criteria to choose the new owner?
|
channel.owner_id = "1"; // The channel is now owned by the server user
|
||||||
await emitEvent({
|
await emitEvent({
|
||||||
event: "CHANNEL_UPDATE",
|
event: "CHANNEL_UPDATE",
|
||||||
data: await DmChannelDTO.from(channel, [user_id]),
|
data: await DmChannelDTO.from(channel, [user_id]),
|
||||||
|
56
util/src/util/InvisibleCharacters.ts
Normal file
56
util/src/util/InvisibleCharacters.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// List from https://invisible-characters.com/
|
||||||
|
export const InvisibleCharacters = [
|
||||||
|
'\u{9}', //Tab
|
||||||
|
'\u{20}', //Space
|
||||||
|
'\u{ad}', //Soft hyphen
|
||||||
|
'\u{34f}', //Combining grapheme joiner
|
||||||
|
'\u{61c}', //Arabic letter mark
|
||||||
|
'\u{115f}', //Hangul choseong filler
|
||||||
|
'\u{1160}', //Hangul jungseong filler
|
||||||
|
'\u{17b4}', //Khmer vowel inherent AQ
|
||||||
|
'\u{17b5}', //Khmer vowel inherent AA
|
||||||
|
'\u{180e}', //Mongolian vowel separator
|
||||||
|
'\u{2000}', //En quad
|
||||||
|
'\u{2001}', //Em quad
|
||||||
|
'\u{2002}', //En space
|
||||||
|
'\u{2003}', //Em space
|
||||||
|
'\u{2004}', //Three-per-em space
|
||||||
|
'\u{2005}', //Four-per-em space
|
||||||
|
'\u{2006}', //Six-per-em space
|
||||||
|
'\u{2007}', //Figure space
|
||||||
|
'\u{2008}', //Punctuation space
|
||||||
|
'\u{2009}', //Thin space
|
||||||
|
'\u{200a}', //Hair space
|
||||||
|
'\u{200b}', //Zero width space
|
||||||
|
'\u{200c}', //Zero width non-joiner
|
||||||
|
'\u{200d}', //Zero width joiner
|
||||||
|
'\u{200e}', //Left-to-right mark
|
||||||
|
'\u{200f}', //Right-to-left mark
|
||||||
|
'\u{202f}', //Narrow no-break space
|
||||||
|
'\u{205f}', //Medium mathematical space
|
||||||
|
'\u{2060}', //Word joiner
|
||||||
|
'\u{2061}', //Function application
|
||||||
|
'\u{2062}', //Invisible times
|
||||||
|
'\u{2063}', //Invisible separator
|
||||||
|
'\u{2064}', //Invisible plus
|
||||||
|
'\u{206a}', //Inhibit symmetric swapping
|
||||||
|
'\u{206b}', //Activate symmetric swapping
|
||||||
|
'\u{206c}', //Inhibit arabic form shaping
|
||||||
|
'\u{206d}', //Activate arabic form shaping
|
||||||
|
'\u{206e}', //National digit shapes
|
||||||
|
'\u{206f}', //Nominal digit shapes
|
||||||
|
'\u{3000}', //Ideographic space
|
||||||
|
'\u{2800}', //Braille pattern blank
|
||||||
|
'\u{3164}', //Hangul filler
|
||||||
|
'\u{feff}', //Zero width no-break space
|
||||||
|
'\u{ffa0}', //Haldwidth hangul filler
|
||||||
|
'\u{1d159}', //Musical symbol null notehead
|
||||||
|
'\u{1d173}', //Musical symbol begin beam
|
||||||
|
'\u{1d174}', //Musical symbol end beam
|
||||||
|
'\u{1d175}', //Musical symbol begin tie
|
||||||
|
'\u{1d176}', //Musical symbol end tie
|
||||||
|
'\u{1d177}', //Musical symbol begin slur
|
||||||
|
'\u{1d178}', //Musical symbol end slur
|
||||||
|
'\u{1d179}', //Musical symbol begin phrase
|
||||||
|
'\u{1d17a}' //Musical symbol end phrase
|
||||||
|
];
|
@ -18,3 +18,4 @@ export * from "./Snowflake";
|
|||||||
export * from "./String";
|
export * from "./String";
|
||||||
export * from "./Array";
|
export * from "./Array";
|
||||||
export * from "./TraverseDirectory";
|
export * from "./TraverseDirectory";
|
||||||
|
export * from "./InvisibleCharacters";
|
Loading…
x
Reference in New Issue
Block a user