feat: 指定したユーザーの投稿通知

Resolve #11499
This commit is contained in:
syuilo
2023-09-21 18:48:15 +09:00
parent f195fa4ab9
commit e3f151e230
25 changed files with 238 additions and 31 deletions

View File

@@ -160,6 +160,7 @@ import * as ep___federation_users from './endpoints/federation/users.js';
import * as ep___federation_stats from './endpoints/federation/stats.js';
import * as ep___following_create from './endpoints/following/create.js';
import * as ep___following_delete from './endpoints/following/delete.js';
import * as ep___following_update from './endpoints/following/update.js';
import * as ep___following_invalidate from './endpoints/following/invalidate.js';
import * as ep___following_requests_accept from './endpoints/following/requests/accept.js';
import * as ep___following_requests_cancel from './endpoints/following/requests/cancel.js';
@@ -507,6 +508,7 @@ const $federation_users: Provider = { provide: 'ep:federation/users', useClass:
const $federation_stats: Provider = { provide: 'ep:federation/stats', useClass: ep___federation_stats.default };
const $following_create: Provider = { provide: 'ep:following/create', useClass: ep___following_create.default };
const $following_delete: Provider = { provide: 'ep:following/delete', useClass: ep___following_delete.default };
const $following_update: Provider = { provide: 'ep:following/update', useClass: ep___following_update.default };
const $following_invalidate: Provider = { provide: 'ep:following/invalidate', useClass: ep___following_invalidate.default };
const $following_requests_accept: Provider = { provide: 'ep:following/requests/accept', useClass: ep___following_requests_accept.default };
const $following_requests_cancel: Provider = { provide: 'ep:following/requests/cancel', useClass: ep___following_requests_cancel.default };
@@ -858,6 +860,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
$federation_stats,
$following_create,
$following_delete,
$following_update,
$following_invalidate,
$following_requests_accept,
$following_requests_cancel,
@@ -1203,6 +1206,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
$federation_stats,
$following_create,
$following_delete,
$following_update,
$following_invalidate,
$following_requests_accept,
$following_requests_cancel,

View File

@@ -160,6 +160,7 @@ import * as ep___federation_users from './endpoints/federation/users.js';
import * as ep___federation_stats from './endpoints/federation/stats.js';
import * as ep___following_create from './endpoints/following/create.js';
import * as ep___following_delete from './endpoints/following/delete.js';
import * as ep___following_update from './endpoints/following/update.js';
import * as ep___following_invalidate from './endpoints/following/invalidate.js';
import * as ep___following_requests_accept from './endpoints/following/requests/accept.js';
import * as ep___following_requests_cancel from './endpoints/following/requests/cancel.js';
@@ -505,6 +506,7 @@ const eps = [
['federation/stats', ep___federation_stats],
['following/create', ep___following_create],
['following/delete', ep___following_delete],
['following/update', ep___following_update],
['following/invalidate', ep___following_invalidate],
['following/requests/accept', ep___following_requests_accept],
['following/requests/cancel', ep___following_requests_cancel],

View File

@@ -19,7 +19,7 @@ export const meta = {
limit: {
duration: ms('1hour'),
max: 50,
max: 100,
},
requireCredential: true,

View File

@@ -29,7 +29,7 @@ export const meta = {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '5b12c78d-2b28-4dca-99d2-f56139b42ff8',
id: 'b77e6ae6-a3e5-40da-9cc8-c240115479cc',
},
followerIsYourself: {
@@ -41,7 +41,7 @@ export const meta = {
notFollowing: {
message: 'The other use is not following you.',
code: 'NOT_FOLLOWING',
id: '5dbf82f5-c92b-40b1-87d1-6c8c0741fd09',
id: '918faac3-074f-41ae-9c43-ed5d2946770d',
},
},

View File

@@ -0,0 +1,107 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
import ms from 'ms';
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import type { FollowingsRepository } from '@/models/_.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { UserFollowingService } from '@/core/UserFollowingService.js';
import { DI } from '@/di-symbols.js';
import { GetterService } from '@/server/api/GetterService.js';
import { ApiError } from '../../error.js';
export const meta = {
tags: ['following', 'users'],
limit: {
duration: ms('1hour'),
max: 100,
},
requireCredential: true,
kind: 'write:following',
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '14318698-f67e-492a-99da-5353a5ac52be',
},
followeeIsYourself: {
message: 'Followee is yourself.',
code: 'FOLLOWEE_IS_YOURSELF',
id: '4c4cbaf9-962a-463b-8418-a5e365dbf2eb',
},
notFollowing: {
message: 'You are not following that user.',
code: 'NOT_FOLLOWING',
id: 'b8dc75cf-1cb5-46c9-b14b-5f1ffbd782c9',
},
},
res: {
type: 'object',
optional: false, nullable: false,
ref: 'UserLite',
},
} as const;
export const paramDef = {
type: 'object',
properties: {
userId: { type: 'string', format: 'misskey:id' },
notify: { type: 'string', enum: ['normal', 'none'] },
},
required: ['userId', 'notify'],
} as const;
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor(
@Inject(DI.followingsRepository)
private followingsRepository: FollowingsRepository,
private userEntityService: UserEntityService,
private getterService: GetterService,
private userFollowingService: UserFollowingService,
) {
super(meta, paramDef, async (ps, me) => {
const follower = me;
// Check if the follower is yourself
if (me.id === ps.userId) {
throw new ApiError(meta.errors.followeeIsYourself);
}
// Get followee
const followee = await this.getterService.getUser(ps.userId).catch(err => {
if (err.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
throw err;
});
// Check not following
const exist = await this.followingsRepository.findOneBy({
followerId: follower.id,
followeeId: followee.id,
});
if (exist == null) {
throw new ApiError(meta.errors.notFollowing);
}
await this.followingsRepository.update({
id: exist.id,
}, {
notify: ps.notify === 'none' ? null : ps.notify,
});
return await this.userEntityService.pack(follower.id, me);
});
}
}