diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 00000000..76add878
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,2 @@
+node_modules
+dist
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index 4cdb93e6..39b4dd56 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,9 @@
FROM node:lts-alpine
+# needed for native packages (bcrypt, canvas)
+RUN apk add --no-cache make gcc g++ python cairo-dev jpeg-dev pango-dev giflib-dev
WORKDIR /usr/src/fosscord-api
COPY package.json .
+RUN npm rebuild bcrypt --build-from-source && npm rebuild canvas --build-from-source
RUN npm install
COPY . .
EXPOSE 3001
diff --git a/cache/widget/banner1.png b/assets/widget/banner1.png
index ed9bd5c0..ed9bd5c0 100644
--- a/cache/widget/banner1.png
+++ b/assets/widget/banner1.png
Binary files differdiff --git a/cache/widget/banner2.png b/assets/widget/banner2.png
index 90d3713d..90d3713d 100644
--- a/cache/widget/banner2.png
+++ b/assets/widget/banner2.png
Binary files differdiff --git a/cache/widget/banner3.png b/assets/widget/banner3.png
index 22351898..22351898 100644
--- a/cache/widget/banner3.png
+++ b/assets/widget/banner3.png
Binary files differdiff --git a/cache/widget/banner4.png b/assets/widget/banner4.png
index e6bd7b6f..e6bd7b6f 100644
--- a/cache/widget/banner4.png
+++ b/assets/widget/banner4.png
Binary files differdiff --git a/cache/widget/shield.png b/assets/widget/shield.png
index 30277db2..30277db2 100644
--- a/cache/widget/shield.png
+++ b/assets/widget/shield.png
Binary files differdiff --git a/src/middlewares/ErrorHandler.ts b/src/middlewares/ErrorHandler.ts
index 25a68865..2e6b1d8b 100644
--- a/src/middlewares/ErrorHandler.ts
+++ b/src/middlewares/ErrorHandler.ts
@@ -22,6 +22,8 @@ export function ErrorHandler(error: Error, req: Request, res: Response, next: Ne
code = httpcode = 500;
}
+ if (httpcode > 511) httpcode = 400;
+
res.status(httpcode).json({ code: code, message, errors });
return;
diff --git a/src/routes/channels/#channel_id/messages/index.ts b/src/routes/channels/#channel_id/messages/index.ts
index b42a886b..5f1f6c54 100644
--- a/src/routes/channels/#channel_id/messages/index.ts
+++ b/src/routes/channels/#channel_id/messages/index.ts
@@ -99,13 +99,16 @@ const messageUpload = multer({
// https://discord.com/developers/docs/resources/channel#create-message
// TODO: text channel slowdown
// TODO: trim and replace message content and every embed field
+// TODO: check allowed_mentions
// Send message
-router.post("/", check(MessageCreateSchema), messageUpload.single("file"), async (req: Request, res: Response) => {
+router.post("/", messageUpload.single("file"), async (req: Request, res: Response) => {
const { channel_id } = req.params;
var body = req.body as MessageCreateSchema;
const attachments: Attachment[] = [];
+ console.log(body);
+
if (req.file) {
try {
const file = await uploadFile(`/attachments/${channel_id}`, req.file);
@@ -117,10 +120,11 @@ router.post("/", check(MessageCreateSchema), messageUpload.single("file"), async
if (body.payload_json) {
body = JSON.parse(body.payload_json);
- const errors = instanceOf(MessageCreateSchema, body, { req });
- if (errors !== true) throw errors;
}
+ const errors = instanceOf(MessageCreateSchema, body, { req });
+ if (errors !== true) throw errors;
+
const embeds = [];
if (body.embed) embeds.push(body.embed);
const data = await sendMessage({ ...body, type: 0, pinned: false, author_id: req.user_id, embeds, channel_id, attachments });
diff --git a/src/routes/channels/#channel_id/permissions.ts b/src/routes/channels/#channel_id/permissions.ts
index 3993c424..43e61821 100644
--- a/src/routes/channels/#channel_id/permissions.ts
+++ b/src/routes/channels/#channel_id/permissions.ts
@@ -21,7 +21,7 @@ router.put("/:overwrite_id", check({ allow: String, deny: String, type: Number,
if (!(await RoleModel.exists({ id: overwrite_id }))) throw new HTTPError("role not found", 404);
} else if (body.type === 1) {
if (!(await MemberModel.exists({ id: overwrite_id }))) throw new HTTPError("user not found", 404);
- } else throw new HTTPError("type not supported");
+ } else throw new HTTPError("type not supported", 501);
// @ts-ignore
var overwrite: ChannelPermissionOverwrite = channel.permission_overwrites.find((x) => x.id === overwrite_id);
diff --git a/src/routes/guilds/#guild_id/widget.png.ts b/src/routes/guilds/#guild_id/widget.png.ts
index 3ddccf20..ea947c5d 100644
--- a/src/routes/guilds/#guild_id/widget.png.ts
+++ b/src/routes/guilds/#guild_id/widget.png.ts
@@ -35,7 +35,7 @@ router.get("/", async (req: Request, res: Response) => {
const sizeOf = require("image-size");
// TODO: Widget style templates need Fosscord branding
- const source = path.join(__dirname, "..", "..", "..", "..", "cache","widget", `${style}.png`)
+ const source = path.join(__dirname, "..", "..", "..", "..", "assets","widget", `${style}.png`)
if (!fs.existsSync(source)) {
throw new HTTPError("Widget template does not exist.", 400);
}
diff --git a/src/routes/users/@me/index.ts b/src/routes/users/@me/index.ts
index 4f17fbee..df477ef1 100644
--- a/src/routes/users/@me/index.ts
+++ b/src/routes/users/@me/index.ts
@@ -29,6 +29,7 @@ router.patch("/", check(UserModifySchema), async (req: Request, res: Response) =
}
const user = await UserModel.findOneAndUpdate({ id: req.user_id }, body).exec();
+ // TODO: dispatch user update event
res.json(toObject(user));
});
diff --git a/src/schema/Message.ts b/src/schema/Message.ts
index b2e4b1f7..8423d706 100644
--- a/src/schema/Message.ts
+++ b/src/schema/Message.ts
@@ -43,7 +43,12 @@ export const MessageCreateSchema = {
25
)
},
- $allowed_mentions: [],
+ $allowed_mentions: {
+ $parse: [String],
+ $roles: [String],
+ $users: [String],
+ $replied_user: Boolean
+ },
$message_reference: {
message_id: String,
channel_id: String,
@@ -60,7 +65,12 @@ export interface MessageCreateSchema {
tts?: boolean;
flags?: bigint;
embed?: Embed & { timestamp?: string };
- allowed_mentions?: [];
+ allowed_mentions?: {
+ parse?: string[];
+ roles?: string[];
+ users?: string[];
+ replied_user?: boolean;
+ };
message_reference?: {
message_id: string;
channel_id: string;
diff --git a/src/util/Message.ts b/src/util/Message.ts
index 9b928031..40367d8f 100644
--- a/src/util/Message.ts
+++ b/src/util/Message.ts
@@ -8,6 +8,7 @@ import { HTTPError } from "lambert-server";
import fetch from "node-fetch";
import cheerio from "cheerio";
import { emitEvent } from "./Event";
+import { MessageType } from "@fosscord/server-util/dist/util/Constants";
// TODO: check webhook, application, system author
const LINK_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g;
@@ -34,11 +35,14 @@ export async function handleMessage(opts: Partial<Message>) {
if (opts.message_reference) {
permissions.hasThrow("READ_MESSAGE_HISTORY");
if (opts.message_reference.guild_id !== channel.guild_id) throw new HTTPError("You can only reference messages from this guild");
- }
-
- if (opts.message_reference) {
if (opts.message_reference.channel_id !== opts.channel_id) throw new HTTPError("You can only reference messages from this channel");
// TODO: should be checked if the referenced message exists?
+ // @ts-ignore
+ opts.type = MessageType.REPLY;
+ }
+
+ if (!opts.content && !opts.embeds?.length) {
+ throw new HTTPError("Empty messages are not allowed", 50006);
}
// TODO: check and put it all in the body
@@ -114,7 +118,9 @@ export async function postHandleMessage(message: Message) {
export async function sendMessage(opts: Partial<Message>) {
const message = await handleMessage({ ...opts, id: Snowflake.generate(), timestamp: new Date() });
- const data = toObject(await new MessageModel(message).populate({ path: "member", select: PublicMemberProjection }).save());
+ const data = toObject(
+ await new MessageModel(message).populate({ path: "member", select: PublicMemberProjection }).populate("referenced_message").save()
+ );
await emitEvent({ event: "MESSAGE_CREATE", channel_id: opts.channel_id, data, guild_id: message.guild_id } as MessageCreateEvent);
|