Merge branch 'master' of https://github.com/fosscord/fosscord-api
This commit is contained in:
commit
37533e28fd
@ -462,7 +462,11 @@
|
|||||||
"payload_json": {
|
"payload_json": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"file": {}
|
"file": {},
|
||||||
|
"attachments": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"definitions": {
|
"definitions": {
|
||||||
@ -709,7 +713,10 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"target_user_id": {
|
"target_user_id": {
|
||||||
"type": "string"
|
"type": [
|
||||||
|
"null",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"target_type": {
|
"target_type": {
|
||||||
"type": [
|
"type": [
|
||||||
@ -2544,7 +2551,10 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"system_channel_id": {
|
"system_channel_id": {
|
||||||
"type": "string"
|
"type": [
|
||||||
|
"null",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"rules_channel_id": {
|
"rules_channel_id": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -2798,13 +2808,22 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"banner": {
|
"banner": {
|
||||||
"type": "string"
|
"type": [
|
||||||
|
"null",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"splash": {
|
"splash": {
|
||||||
"type": "string"
|
"type": [
|
||||||
|
"null",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"type": "string"
|
"type": [
|
||||||
|
"null",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"features": {
|
"features": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
@ -2825,13 +2844,19 @@
|
|||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"public_updates_channel_id": {
|
"public_updates_channel_id": {
|
||||||
"type": "string"
|
"type": [
|
||||||
|
"null",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"afk_timeout": {
|
"afk_timeout": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"afk_channel_id": {
|
"afk_channel_id": {
|
||||||
"type": "string"
|
"type": [
|
||||||
|
"null",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"preferred_locale": {
|
"preferred_locale": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -2850,7 +2875,10 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"system_channel_id": {
|
"system_channel_id": {
|
||||||
"type": "string"
|
"type": [
|
||||||
|
"null",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"rules_channel_id": {
|
"rules_channel_id": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
@ -8,7 +8,7 @@ import { isTextChannel } from "./messages";
|
|||||||
const router: Router = Router();
|
const router: Router = Router();
|
||||||
|
|
||||||
export interface InviteCreateSchema {
|
export interface InviteCreateSchema {
|
||||||
target_user_id?: string;
|
target_user_id?: string | null;
|
||||||
target_type?: string | null;
|
target_type?: string | null;
|
||||||
validate?: string | null; // ? what is this
|
validate?: string | null; // ? what is this
|
||||||
max_age?: number;
|
max_age?: number;
|
||||||
|
@ -3,6 +3,7 @@ import { Router, Response, Request } from "express";
|
|||||||
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";
|
||||||
|
import { deleteMessageAttachments } from "@fosscord/api/util/Attachments";
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
// TODO: message content/embed string length limit
|
// TODO: message content/embed string length limit
|
||||||
@ -11,7 +12,7 @@ router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGE
|
|||||||
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;
|
||||||
|
|
||||||
const message = await Message.findOneOrFail({ id: message_id, channel_id });
|
const message = await Message.findOneOrFail({ where: { id: message_id, channel_id }, relations: ["attachments"] });
|
||||||
|
|
||||||
const permissions = await getPermission(req.user_id, undefined, channel_id);
|
const permissions = await getPermission(req.user_id, undefined, channel_id);
|
||||||
|
|
||||||
@ -33,6 +34,7 @@ router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGE
|
|||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
|
await deleteMessageAttachments(message_id, new_message.attachments), //This delete all the attachments not in the array
|
||||||
new_message!.save(),
|
new_message!.save(),
|
||||||
await emitEvent({
|
await emitEvent({
|
||||||
event: "MESSAGE_UPDATE",
|
event: "MESSAGE_UPDATE",
|
||||||
@ -46,8 +48,6 @@ router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGE
|
|||||||
return res.json(message);
|
return res.json(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: delete attachments in message
|
|
||||||
|
|
||||||
// permission check only if deletes messagr from other user
|
// permission check only if deletes messagr from other user
|
||||||
router.delete("/", route({}), async (req: Request, res: Response) => {
|
router.delete("/", route({}), async (req: Request, res: Response) => {
|
||||||
const { message_id, channel_id } = req.params;
|
const { message_id, channel_id } = req.params;
|
||||||
@ -60,6 +60,7 @@ router.delete("/", route({}), async (req: Request, res: Response) => {
|
|||||||
permission.hasThrow("MANAGE_MESSAGES");
|
permission.hasThrow("MANAGE_MESSAGES");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await deleteMessageAttachments(message_id);
|
||||||
await Message.delete({ id: message_id });
|
await Message.delete({ id: message_id });
|
||||||
|
|
||||||
await emitEvent({
|
await emitEvent({
|
||||||
|
@ -51,6 +51,7 @@ export interface MessageCreateSchema {
|
|||||||
};
|
};
|
||||||
payload_json?: string;
|
payload_json?: string;
|
||||||
file?: any;
|
file?: any;
|
||||||
|
attachments?: any[]; //TODO we should create an interface for attachments
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://discord.com/developers/docs/resources/channel#create-message
|
// https://discord.com/developers/docs/resources/channel#create-message
|
||||||
|
@ -9,17 +9,17 @@ import { GuildCreateSchema } from "../index";
|
|||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
export interface GuildUpdateSchema extends Omit<GuildCreateSchema, "channels"> {
|
export interface GuildUpdateSchema extends Omit<GuildCreateSchema, "channels"> {
|
||||||
banner?: string;
|
banner?: string | null;
|
||||||
splash?: string;
|
splash?: string | null;
|
||||||
description?: string;
|
description?: string | null;
|
||||||
features?: string[];
|
features?: string[];
|
||||||
verification_level?: number;
|
verification_level?: number;
|
||||||
default_message_notifications?: number;
|
default_message_notifications?: number;
|
||||||
system_channel_flags?: number;
|
system_channel_flags?: number;
|
||||||
explicit_content_filter?: number;
|
explicit_content_filter?: number;
|
||||||
public_updates_channel_id?: string;
|
public_updates_channel_id?: string | null;
|
||||||
afk_timeout?: number;
|
afk_timeout?: number;
|
||||||
afk_channel_id?: string;
|
afk_channel_id?: string | null;
|
||||||
preferred_locale?: string;
|
preferred_locale?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ export interface GuildCreateSchema {
|
|||||||
icon?: string;
|
icon?: string;
|
||||||
channels?: ChannelModifySchema[];
|
channels?: ChannelModifySchema[];
|
||||||
guild_template_code?: string;
|
guild_template_code?: string;
|
||||||
system_channel_id?: string;
|
system_channel_id?: string | null;
|
||||||
rules_channel_id?: string;
|
rules_channel_id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { Router, Request, Response } from "express";
|
import { Router, Request, Response } from "express";
|
||||||
import { getPermission, Guild, Invite, Member, PublicInviteRelation } from "@fosscord/util";
|
import { emitEvent, getPermission, Guild, Invite, InviteDeleteEvent, Member, PublicInviteRelation } from "@fosscord/util";
|
||||||
import { route } from "@fosscord/api";
|
import { route } from "@fosscord/api";
|
||||||
import { HTTPError } from "lambert-server";
|
import { HTTPError } from "lambert-server";
|
||||||
|
|
||||||
const router: Router = Router();
|
const router: Router = Router();
|
||||||
|
|
||||||
router.get("/:code", route({}), async (req: Request, res: Response) => {
|
router.get("/:code", route({}), async (req: Request, res: Response) => {
|
||||||
@ -35,7 +36,19 @@ router.delete("/:code", route({}), async (req: Request, res: Response) => {
|
|||||||
if (!permission.has("MANAGE_GUILD") && !permission.has("MANAGE_CHANNELS"))
|
if (!permission.has("MANAGE_GUILD") && !permission.has("MANAGE_CHANNELS"))
|
||||||
throw new HTTPError("You missing the MANAGE_GUILD or MANAGE_CHANNELS permission", 401);
|
throw new HTTPError("You missing the MANAGE_GUILD or MANAGE_CHANNELS permission", 401);
|
||||||
|
|
||||||
await Promise.all([Invite.delete({ code }), Guild.update({ vanity_url_code: code }, { vanity_url_code: undefined })]);
|
await Promise.all([
|
||||||
|
Invite.delete({ code }),
|
||||||
|
Guild.update({ vanity_url_code: code }, { vanity_url_code: undefined }),
|
||||||
|
emitEvent({
|
||||||
|
event: "INVITE_DELETE",
|
||||||
|
guild_id: guild_id,
|
||||||
|
data: {
|
||||||
|
channel_id: channel_id,
|
||||||
|
guild_id: guild_id,
|
||||||
|
code: code
|
||||||
|
}
|
||||||
|
} as InviteDeleteEvent)
|
||||||
|
]);
|
||||||
|
|
||||||
res.json({ invite: invite });
|
res.json({ invite: invite });
|
||||||
});
|
});
|
||||||
|
11
api/src/routes/store/applications.ts
Normal file
11
api/src/routes/store/applications.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { Request, Response, Router } from "express";
|
||||||
|
|
||||||
|
const router: Router = Router();
|
||||||
|
|
||||||
|
router.get("/applications/:id", async (req: Request, res: Response) => {
|
||||||
|
//TODO
|
||||||
|
const { id } = req.params;
|
||||||
|
res.json([]).status(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
11
api/src/routes/store/skus.ts
Normal file
11
api/src/routes/store/skus.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { Request, Response, Router } from "express";
|
||||||
|
|
||||||
|
const router: Router = Router();
|
||||||
|
|
||||||
|
router.get("/skus/:id", async (req: Request, res: Response) => {
|
||||||
|
//TODO
|
||||||
|
const { id } = req.params;
|
||||||
|
res.json([]).status(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
@ -1,5 +1,5 @@
|
|||||||
import { Router, Request, Response } from "express";
|
import { Router, Request, Response } from "express";
|
||||||
import { User, PrivateUserProjection } from "@fosscord/util";
|
import { User, PrivateUserProjection, emitEvent, UserUpdateEvent } from "@fosscord/util";
|
||||||
import { route } from "@fosscord/api";
|
import { route } from "@fosscord/api";
|
||||||
import { handleFile } from "@fosscord/api";
|
import { handleFile } from "@fosscord/api";
|
||||||
|
|
||||||
@ -33,8 +33,16 @@ router.patch("/", route({ body: "UserModifySchema" }), async (req: Request, res:
|
|||||||
if (body.avatar) body.avatar = await handleFile(`/avatars/${req.user_id}`, body.avatar as string);
|
if (body.avatar) body.avatar = await handleFile(`/avatars/${req.user_id}`, body.avatar as string);
|
||||||
if (body.banner) body.banner = await handleFile(`/banners/${req.user_id}`, body.banner as string);
|
if (body.banner) body.banner = await handleFile(`/banners/${req.user_id}`, body.banner as string);
|
||||||
|
|
||||||
const user = await new User({ ...body, id: req.user_id }).save();
|
await new User({ ...body, id: req.user_id }).save();
|
||||||
// TODO: dispatch user update event
|
|
||||||
|
//Need to reload user from db due to https://github.com/typeorm/typeorm/issues/3490
|
||||||
|
const user = await User.findOneOrFail({ where: { id: req.user_id }, select: PrivateUserProjection });
|
||||||
|
// TODO: send update member list event in gateway
|
||||||
|
await emitEvent({
|
||||||
|
event: "USER_UPDATE",
|
||||||
|
user_id: req.user_id,
|
||||||
|
data: user
|
||||||
|
} as UserUpdateEvent);
|
||||||
|
|
||||||
res.json(user);
|
res.json(user);
|
||||||
});
|
});
|
||||||
|
12
api/src/util/Attachments.ts
Normal file
12
api/src/util/Attachments.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { Attachment } from "@fosscord/util";
|
||||||
|
import { deleteFile } from "@fosscord/api";
|
||||||
|
import { URL } from "url";
|
||||||
|
|
||||||
|
export async function deleteMessageAttachments(messageId: string, keep?: Attachment[]) {
|
||||||
|
let attachments = await Attachment.find({ message_id: messageId });
|
||||||
|
if (keep)
|
||||||
|
attachments = attachments.filter(x => !keep.map(k => k.id).includes(x.id));
|
||||||
|
await Promise.all(attachments.map(a => a.remove()));
|
||||||
|
|
||||||
|
attachments.forEach(a => deleteFile((new URL(a.url)).pathname)); //We don't need to await since this is done on the cdn
|
||||||
|
}
|
@ -38,3 +38,16 @@ export async function handleFile(path: string, body?: string): Promise<string |
|
|||||||
throw new HTTPError("Invalid " + path);
|
throw new HTTPError("Invalid " + path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function deleteFile(path: string) {
|
||||||
|
const response = await fetch(`${Config.get().cdn.endpoint || "http://localhost:3003"}${path}`, {
|
||||||
|
headers: {
|
||||||
|
signature: Config.get().security.requestSignature,
|
||||||
|
},
|
||||||
|
method: "DELETE",
|
||||||
|
});
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
if (response.status !== 200) throw result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -37,6 +37,7 @@ export class FileStorage implements Storage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async delete(path: string) {
|
async delete(path: string) {
|
||||||
|
//TODO we should delete the parent directory if empty
|
||||||
fs.unlinkSync(getPath(path));
|
fs.unlinkSync(getPath(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ export class Message extends BaseClass {
|
|||||||
sticker_items?: Sticker[];
|
sticker_items?: Sticker[];
|
||||||
|
|
||||||
@JoinColumn({ name: "attachment_ids" })
|
@JoinColumn({ name: "attachment_ids" })
|
||||||
@OneToMany(() => Attachment, (attachment: Attachment) => attachment.message)
|
@OneToMany(() => Attachment, (attachment: Attachment) => attachment.message, { cascade: true })
|
||||||
attachments?: Attachment[];
|
attachments?: Attachment[];
|
||||||
|
|
||||||
@Column({ type: "simple-json" })
|
@Column({ type: "simple-json" })
|
||||||
|
Loading…
x
Reference in New Issue
Block a user