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