forked from FoundKeyGang/FoundKey
Johann150
7b8333a21f
Instead of throwing an IdentifiableError which then just always gets converted into an ApiError, the getter can just throw the same ApiError directly. This makes it more convenient to use and thus more endpoints have been refactored to use it to reduce code repetition.
138 lines
3 KiB
TypeScript
138 lines
3 KiB
TypeScript
import { DriveFiles, UserGroups, UserGroupJoinings, Blockings } from '@/models/index.js';
|
|
import { User } from '@/models/entities/user.js';
|
|
import { UserGroup } from '@/models/entities/user-group.js';
|
|
import { createMessage } from '@/services/messages/create.js';
|
|
import define from '@/server/api/define.js';
|
|
import { ApiError } from '@/server/api/error.js';
|
|
import { getUser } from '@/server/api/common/getters.js';
|
|
|
|
export const meta = {
|
|
tags: ['messaging'],
|
|
|
|
requireCredential: true,
|
|
|
|
kind: 'write:messaging',
|
|
|
|
res: {
|
|
type: 'object',
|
|
optional: false, nullable: false,
|
|
ref: 'MessagingMessage',
|
|
},
|
|
|
|
errors: ['ACCESS_DENIED', 'BLOCKED', 'NO_SUCH_FILE', 'NO_SUCH_USER', 'NO_SUCH_GROUP', 'RECIPIENT_IS_YOURSELF'],
|
|
} as const;
|
|
|
|
export const paramDef = {
|
|
type: 'object',
|
|
anyOf: [
|
|
{
|
|
properties: {
|
|
text: {
|
|
type: 'string',
|
|
minLength: 1,
|
|
maxLength: 3000,
|
|
},
|
|
fileId: {
|
|
type: 'string',
|
|
format: 'misskey:id',
|
|
},
|
|
userId: {
|
|
type: 'string',
|
|
format: 'misskey:id',
|
|
},
|
|
},
|
|
required: ['text', 'userId'],
|
|
},
|
|
{
|
|
properties: {
|
|
fileId: {
|
|
type: 'string',
|
|
format: 'misskey:id',
|
|
},
|
|
userId: {
|
|
type: 'string',
|
|
format: 'misskey:id',
|
|
},
|
|
},
|
|
required: ['fileId', 'userId'],
|
|
},
|
|
{
|
|
properties: {
|
|
text: {
|
|
type: 'string',
|
|
minLength: 1,
|
|
maxLength: 3000,
|
|
},
|
|
fileId: {
|
|
type: 'string',
|
|
format: 'misskey:id',
|
|
},
|
|
groupId: {
|
|
type: 'string',
|
|
format: 'misskey:id',
|
|
},
|
|
},
|
|
required: ['text', 'groupId'],
|
|
},
|
|
{
|
|
properties: {
|
|
fileId: {
|
|
type: 'string',
|
|
format: 'misskey:id',
|
|
},
|
|
groupId: {
|
|
type: 'string',
|
|
format: 'misskey:id',
|
|
},
|
|
},
|
|
required: ['fileId', 'groupId'],
|
|
},
|
|
],
|
|
} as const;
|
|
|
|
// eslint-disable-next-line import/no-default-export
|
|
export default define(meta, paramDef, async (ps, user) => {
|
|
let recipientUser: User | null;
|
|
let recipientGroup: UserGroup | null;
|
|
|
|
if (ps.userId != null) {
|
|
// Myself
|
|
if (ps.userId === user.id) throw new ApiError('RECIPIENT_IS_YOURSELF');
|
|
|
|
// Fetch recipient (user)
|
|
recipientUser = await getUser(ps.userId);
|
|
|
|
// Check blocking
|
|
const block = await Blockings.countBy({
|
|
blockerId: recipientUser.id,
|
|
blockeeId: user.id,
|
|
});
|
|
if (block) throw new ApiError('BLOCKED');
|
|
} else if (ps.groupId != null) {
|
|
// Fetch recipient (group)
|
|
recipientGroup = await UserGroups.findOneBy({ id: ps.groupId! });
|
|
|
|
if (recipientGroup == null) throw new ApiError('NO_SUCH_GROUP');
|
|
|
|
// check joined
|
|
const joined = await UserGroupJoinings.countBy({
|
|
userId: user.id,
|
|
userGroupId: recipientGroup.id,
|
|
});
|
|
|
|
if (!joined) throw new ApiError('ACCESS_DENIED', 'You have to join a group to send a message in it.');
|
|
}
|
|
|
|
let file = null;
|
|
if (ps.fileId != null) {
|
|
file = await DriveFiles.findOneBy({
|
|
id: ps.fileId,
|
|
userId: user.id,
|
|
});
|
|
|
|
if (file == null) throw new ApiError('NO_SUCH_FILE');
|
|
}
|
|
|
|
return await createMessage(user, recipientUser, recipientGroup, ps.text, file);
|
|
});
|