wip
This commit is contained in:
parent
ae3ce71bb2
commit
726fdb9e93
10 changed files with 160 additions and 339 deletions
|
@ -5,6 +5,7 @@ import type { User } from '@/models/entities/User.js';
|
|||
import type { FollowRequest } from '@/models/entities/FollowRequest.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { Packed } from 'misskey-js';
|
||||
|
||||
@Injectable()
|
||||
export class FollowRequestEntityService {
|
||||
|
@ -20,7 +21,7 @@ export class FollowRequestEntityService {
|
|||
public async pack(
|
||||
src: FollowRequest['id'] | FollowRequest,
|
||||
me?: { id: User['id'] } | null | undefined,
|
||||
) {
|
||||
): Promise<Packed<'FollowRequest'>> {
|
||||
const request = typeof src === 'object' ? src : await this.followRequestsRepository.findOneByOrFail({ id: src });
|
||||
|
||||
return {
|
||||
|
|
|
@ -1,186 +0,0 @@
|
|||
export type Packed<x extends keyof typeof refs> = SchemaType<typeof refs[x]>;
|
||||
|
||||
|
||||
import {
|
||||
packedUserLiteSchema,
|
||||
packedUserDetailedNotMeOnlySchema,
|
||||
packedMeDetailedOnlySchema,
|
||||
packedUserDetailedNotMeSchema,
|
||||
packedMeDetailedSchema,
|
||||
packedUserDetailedSchema,
|
||||
packedUserSchema,
|
||||
} from '@/models/json-schema/user.js';
|
||||
import { packedNoteSchema } from '@/models/json-schema/note.js';
|
||||
import { packedUserListSchema } from '@/models/json-schema/user-list.js';
|
||||
import { packedAppSchema } from '@/models/json-schema/app.js';
|
||||
import { packedNotificationSchema } from '@/models/json-schema/notification.js';
|
||||
import { packedDriveFileSchema } from '@/models/json-schema/drive-file.js';
|
||||
import { packedDriveFolderSchema } from '@/models/json-schema/drive-folder.js';
|
||||
import { packedFollowingSchema } from '@/models/json-schema/following.js';
|
||||
import { packedMutingSchema } from '@/models/json-schema/muting.js';
|
||||
import { packedRenoteMutingSchema } from '@/models/json-schema/renote-muting.js';
|
||||
import { packedBlockingSchema } from '@/models/json-schema/blocking.js';
|
||||
import { packedNoteReactionSchema } from '@/models/json-schema/note-reaction.js';
|
||||
import { packedHashtagSchema } from '@/models/json-schema/hashtag.js';
|
||||
import { packedPageSchema } from '@/models/json-schema/page.js';
|
||||
import { packedNoteFavoriteSchema } from '@/models/json-schema/note-favorite.js';
|
||||
import { packedChannelSchema } from '@/models/json-schema/channel.js';
|
||||
import { packedAntennaSchema } from '@/models/json-schema/antenna.js';
|
||||
import { packedClipSchema } from '@/models/json-schema/clip.js';
|
||||
import { packedFederationInstanceSchema } from '@/models/json-schema/federation-instance.js';
|
||||
import { packedQueueCountSchema } from '@/models/json-schema/queue.js';
|
||||
import { packedGalleryPostSchema } from '@/models/json-schema/gallery-post.js';
|
||||
import { packedEmojiDetailedSchema, packedEmojiSimpleSchema } from '@/models/json-schema/emoji.js';
|
||||
import { packedFlashSchema } from '@/models/json-schema/flash.js';
|
||||
|
||||
export const refs = {
|
||||
UserLite: packedUserLiteSchema,
|
||||
UserDetailedNotMeOnly: packedUserDetailedNotMeOnlySchema,
|
||||
MeDetailedOnly: packedMeDetailedOnlySchema,
|
||||
UserDetailedNotMe: packedUserDetailedNotMeSchema,
|
||||
MeDetailed: packedMeDetailedSchema,
|
||||
UserDetailed: packedUserDetailedSchema,
|
||||
User: packedUserSchema,
|
||||
|
||||
UserList: packedUserListSchema,
|
||||
App: packedAppSchema,
|
||||
Note: packedNoteSchema,
|
||||
NoteReaction: packedNoteReactionSchema,
|
||||
NoteFavorite: packedNoteFavoriteSchema,
|
||||
Notification: packedNotificationSchema,
|
||||
DriveFile: packedDriveFileSchema,
|
||||
DriveFolder: packedDriveFolderSchema,
|
||||
Following: packedFollowingSchema,
|
||||
Muting: packedMutingSchema,
|
||||
RenoteMuting: packedRenoteMutingSchema,
|
||||
Blocking: packedBlockingSchema,
|
||||
Hashtag: packedHashtagSchema,
|
||||
Page: packedPageSchema,
|
||||
Channel: packedChannelSchema,
|
||||
QueueCount: packedQueueCountSchema,
|
||||
Antenna: packedAntennaSchema,
|
||||
Clip: packedClipSchema,
|
||||
FederationInstance: packedFederationInstanceSchema,
|
||||
GalleryPost: packedGalleryPostSchema,
|
||||
EmojiSimple: packedEmojiSimpleSchema,
|
||||
EmojiDetailed: packedEmojiDetailedSchema,
|
||||
Flash: packedFlashSchema,
|
||||
};
|
||||
|
||||
type TypeStringef = 'null' | 'boolean' | 'integer' | 'number' | 'string' | 'array' | 'object' | 'any';
|
||||
type StringDefToType<T extends TypeStringef> =
|
||||
T extends 'null' ? null :
|
||||
T extends 'boolean' ? boolean :
|
||||
T extends 'integer' ? number :
|
||||
T extends 'number' ? number :
|
||||
T extends 'string' ? string | Date :
|
||||
T extends 'array' ? ReadonlyArray<any> :
|
||||
T extends 'object' ? Record<string, any> :
|
||||
any;
|
||||
|
||||
// https://swagger.io/specification/?sbsearch=optional#schema-object
|
||||
type OfSchema = {
|
||||
readonly anyOf?: ReadonlyArray<Schema>;
|
||||
readonly oneOf?: ReadonlyArray<Schema>;
|
||||
readonly allOf?: ReadonlyArray<Schema>;
|
||||
}
|
||||
|
||||
export interface Schema extends OfSchema {
|
||||
readonly type?: TypeStringef;
|
||||
readonly nullable?: boolean;
|
||||
readonly optional?: boolean;
|
||||
readonly items?: Schema;
|
||||
readonly properties?: Obj;
|
||||
readonly required?: ReadonlyArray<Extract<keyof NonNullable<this['properties']>, string>>;
|
||||
readonly description?: string;
|
||||
readonly example?: any;
|
||||
readonly format?: string;
|
||||
readonly ref?: keyof typeof refs;
|
||||
readonly enum?: ReadonlyArray<string | null>;
|
||||
readonly default?: (this['type'] extends TypeStringef ? StringDefToType<this['type']> : any) | null;
|
||||
readonly maxLength?: number;
|
||||
readonly minLength?: number;
|
||||
readonly maximum?: number;
|
||||
readonly minimum?: number;
|
||||
readonly pattern?: string;
|
||||
}
|
||||
|
||||
type RequiredPropertyNames<s extends Obj> = {
|
||||
[K in keyof s]:
|
||||
// K is not optional
|
||||
s[K]['optional'] extends false ? K :
|
||||
// K has default value
|
||||
s[K]['default'] extends null | string | number | boolean | Record<string, unknown> ? K :
|
||||
never
|
||||
}[keyof s];
|
||||
|
||||
export type Obj = Record<string, Schema>;
|
||||
|
||||
// https://github.com/misskey-dev/misskey/issues/8535
|
||||
// To avoid excessive stack depth error,
|
||||
// deceive TypeScript with UnionToIntersection (or more precisely, `infer` expression within it).
|
||||
export type ObjType<s extends Obj, RequiredProps extends ReadonlyArray<keyof s>> =
|
||||
UnionToIntersection<
|
||||
{ -readonly [R in RequiredPropertyNames<s>]-?: SchemaType<s[R]> } &
|
||||
{ -readonly [R in RequiredProps[number]]-?: SchemaType<s[R]> } &
|
||||
{ -readonly [P in keyof s]?: SchemaType<s[P]> }
|
||||
>;
|
||||
|
||||
type NullOrUndefined<p extends Schema, T> =
|
||||
| (p['nullable'] extends true ? null : never)
|
||||
| (p['optional'] extends true ? undefined : never)
|
||||
| T;
|
||||
|
||||
// https://stackoverflow.com/questions/54938141/typescript-convert-union-to-intersection
|
||||
// Get intersection from union
|
||||
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
||||
type PartialIntersection<T> = Partial<UnionToIntersection<T>>;
|
||||
|
||||
// https://github.com/misskey-dev/misskey/pull/8144#discussion_r785287552
|
||||
// To get union, we use `Foo extends any ? Hoge<Foo> : never`
|
||||
type UnionSchemaType<a extends readonly any[], X extends Schema = a[number]> = X extends any ? SchemaType<X> : never;
|
||||
//type UnionObjectSchemaType<a extends readonly any[], X extends Schema = a[number]> = X extends any ? ObjectSchemaType<X> : never;
|
||||
type UnionObjType<s extends Obj, a extends readonly any[], X extends ReadonlyArray<keyof s> = a[number]> = X extends any ? ObjType<s, X> : never;
|
||||
type ArrayUnion<T> = T extends any ? Array<T> : never;
|
||||
|
||||
type ObjectSchemaTypeDef<p extends Schema> =
|
||||
p['ref'] extends keyof typeof refs ? Packed<p['ref']> :
|
||||
p['properties'] extends NonNullable<Obj> ?
|
||||
p['anyOf'] extends ReadonlyArray<Schema> ? p['anyOf'][number]['required'] extends ReadonlyArray<keyof p['properties']> ?
|
||||
UnionObjType<p['properties'], NonNullable<p['anyOf'][number]['required']>> & ObjType<p['properties'], NonNullable<p['required']>>
|
||||
: never
|
||||
: ObjType<p['properties'], NonNullable<p['required']>>
|
||||
:
|
||||
p['anyOf'] extends ReadonlyArray<Schema> ? never : // see CONTRIBUTING.md
|
||||
p['allOf'] extends ReadonlyArray<Schema> ? UnionToIntersection<UnionSchemaType<p['allOf']>> :
|
||||
any
|
||||
|
||||
type ObjectSchemaType<p extends Schema> = NullOrUndefined<p, ObjectSchemaTypeDef<p>>;
|
||||
|
||||
export type SchemaTypeDef<p extends Schema> =
|
||||
p['type'] extends 'null' ? null :
|
||||
p['type'] extends 'integer' ? number :
|
||||
p['type'] extends 'number' ? number :
|
||||
p['type'] extends 'string' ? (
|
||||
p['enum'] extends readonly (string | null)[] ?
|
||||
p['enum'][number] :
|
||||
p['format'] extends 'date-time' ? string : // Dateにする??
|
||||
string
|
||||
) :
|
||||
p['type'] extends 'boolean' ? boolean :
|
||||
p['type'] extends 'object' ? ObjectSchemaTypeDef<p> :
|
||||
p['type'] extends 'array' ? (
|
||||
p['items'] extends OfSchema ? (
|
||||
p['items']['anyOf'] extends ReadonlyArray<Schema> ? UnionSchemaType<NonNullable<p['items']['anyOf']>>[] :
|
||||
p['items']['oneOf'] extends ReadonlyArray<Schema> ? ArrayUnion<UnionSchemaType<NonNullable<p['items']['oneOf']>>> :
|
||||
p['items']['allOf'] extends ReadonlyArray<Schema> ? UnionToIntersection<UnionSchemaType<NonNullable<p['items']['allOf']>>>[] :
|
||||
never
|
||||
) :
|
||||
p['items'] extends NonNullable<Schema> ? SchemaTypeDef<p['items']>[] :
|
||||
any[]
|
||||
) :
|
||||
p['anyOf'] extends ReadonlyArray<Schema> ? UnionSchemaType<p['anyOf']> & PartialIntersection<UnionSchemaType<p['anyOf']>> :
|
||||
p['oneOf'] extends ReadonlyArray<Schema> ? UnionSchemaType<p['oneOf']> :
|
||||
any;
|
||||
|
||||
export type SchemaType<p extends Schema> = NullOrUndefined<p, SchemaTypeDef<p>>;
|
|
@ -4,51 +4,23 @@ import { GetterService } from '@/server/api/GetterService.js';
|
|||
import { UserFollowingService } from '@/core/UserFollowingService.js';
|
||||
import { ApiError } from '../../../error.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['following', 'account'],
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'write:following',
|
||||
|
||||
errors: {
|
||||
noSuchUser: {
|
||||
message: 'No such user.',
|
||||
code: 'NO_SUCH_USER',
|
||||
id: '66ce1645-d66c-46bb-8b79-96739af885bd',
|
||||
},
|
||||
noFollowRequest: {
|
||||
message: 'No follow request.',
|
||||
code: 'NO_FOLLOW_REQUEST',
|
||||
id: 'bcde4f8b-0913-4614-8881-614e522fb041',
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
userId: { type: 'string', format: 'misskey:id' },
|
||||
},
|
||||
required: ['userId'],
|
||||
} as const;
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
@Injectable()
|
||||
export default class extends Endpoint<typeof meta, typeof paramDef> {
|
||||
export default class extends Endpoint<'following/requests/accept'> {
|
||||
name = 'following/requests/accept' as const;
|
||||
constructor(
|
||||
private getterService: GetterService,
|
||||
private userFollowingService: UserFollowingService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
super(async (ps, me) => {
|
||||
// Fetch follower
|
||||
const follower = await this.getterService.getUser(ps.userId).catch(err => {
|
||||
if (err.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
|
||||
if (err.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(this.meta.errors.noSuchUser);
|
||||
throw err;
|
||||
});
|
||||
|
||||
await this.userFollowingService.acceptFollowRequest(me, follower).catch(err => {
|
||||
if (err.id === '8884c2dd-5795-4ac9-b27e-6a01d38190f9') throw new ApiError(meta.errors.noFollowRequest);
|
||||
if (err.id === '8884c2dd-5795-4ac9-b27e-6a01d38190f9') throw new ApiError(this.meta.errors.noFollowRequest);
|
||||
throw err;
|
||||
});
|
||||
|
||||
|
|
|
@ -8,45 +8,10 @@ import { UserFollowingService } from '@/core/UserFollowingService.js';
|
|||
import { DI } from '@/di-symbols.js';
|
||||
import { ApiError } from '../../../error.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['following', 'account'],
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'write:following',
|
||||
|
||||
errors: {
|
||||
noSuchUser: {
|
||||
message: 'No such user.',
|
||||
code: 'NO_SUCH_USER',
|
||||
id: '4e68c551-fc4c-4e46-bb41-7d4a37bf9dab',
|
||||
},
|
||||
|
||||
followRequestNotFound: {
|
||||
message: 'Follow request not found.',
|
||||
code: 'FOLLOW_REQUEST_NOT_FOUND',
|
||||
id: '089b125b-d338-482a-9a09-e2622ac9f8d4',
|
||||
},
|
||||
},
|
||||
|
||||
res: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
ref: 'UserLite',
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
userId: { type: 'string', format: 'misskey:id' },
|
||||
},
|
||||
required: ['userId'],
|
||||
} as const;
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
@Injectable()
|
||||
export default class extends Endpoint<typeof meta, typeof paramDef> {
|
||||
export default class extends Endpoint<'following/requests/cancel'> {
|
||||
name = 'following/requests/cancel' as const;
|
||||
constructor(
|
||||
@Inject(DI.followingsRepository)
|
||||
private followingsRepository: FollowingsRepository,
|
||||
|
@ -55,10 +20,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
private getterService: GetterService,
|
||||
private userFollowingService: UserFollowingService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
super(async (ps, me) => {
|
||||
// Fetch 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);
|
||||
if (err.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(this.meta.errors.noSuchUser);
|
||||
throw err;
|
||||
});
|
||||
|
||||
|
@ -66,7 +31,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
await this.userFollowingService.cancelFollowRequest(followee, me);
|
||||
} catch (err) {
|
||||
if (err instanceof IdentifiableError) {
|
||||
if (err.id === '17447091-ce07-46dd-b331-c1fd4f15b1e7') throw new ApiError(meta.errors.followRequestNotFound);
|
||||
if (err.id === '17447091-ce07-46dd-b331-c1fd4f15b1e7') throw new ApiError(this.meta.errors.followRequestNotFound);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
|
|
|
@ -5,53 +5,10 @@ import type { FollowRequestsRepository } from '@/models/index.js';
|
|||
import { FollowRequestEntityService } from '@/core/entities/FollowRequestEntityService.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['following', 'account'],
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'read:following',
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
optional: false, nullable: false,
|
||||
items: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
},
|
||||
follower: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
ref: 'UserLite',
|
||||
},
|
||||
followee: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
ref: 'UserLite',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
sinceId: { type: 'string', format: 'misskey:id' },
|
||||
untilId: { type: 'string', format: 'misskey:id' },
|
||||
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
|
||||
},
|
||||
required: [],
|
||||
} as const;
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
@Injectable()
|
||||
export default class extends Endpoint<typeof meta, typeof paramDef> {
|
||||
export default class extends Endpoint<'following/requests/list'> {
|
||||
name = 'following/requests/list' as const;
|
||||
constructor(
|
||||
@Inject(DI.followRequestsRepository)
|
||||
private followRequestsRepository: FollowRequestsRepository,
|
||||
|
@ -59,7 +16,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
private followRequestEntityService: FollowRequestEntityService,
|
||||
private queryService: QueryService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
super(async (ps, me) => {
|
||||
const query = this.queryService.makePaginationQuery(this.followRequestsRepository.createQueryBuilder('request'), ps.sinceId, ps.untilId)
|
||||
.andWhere('request.followeeId = :meId', { meId: me.id });
|
||||
|
||||
|
|
|
@ -4,41 +4,18 @@ import { GetterService } from '@/server/api/GetterService.js';
|
|||
import { UserFollowingService } from '@/core/UserFollowingService.js';
|
||||
import { ApiError } from '../../../error.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['following', 'account'],
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'write:following',
|
||||
|
||||
errors: {
|
||||
noSuchUser: {
|
||||
message: 'No such user.',
|
||||
code: 'NO_SUCH_USER',
|
||||
id: 'abc2ffa6-25b2-4380-ba99-321ff3a94555',
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
userId: { type: 'string', format: 'misskey:id' },
|
||||
},
|
||||
required: ['userId'],
|
||||
} as const;
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
@Injectable()
|
||||
export default class extends Endpoint<typeof meta, typeof paramDef> {
|
||||
export default class extends Endpoint<'following/requests/reject'> {
|
||||
name = 'following/requests/reject' as const;
|
||||
constructor(
|
||||
private getterService: GetterService,
|
||||
private userFollowingService: UserFollowingService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
super(async (ps, me) => {
|
||||
// Fetch follower
|
||||
const follower = await this.getterService.getUser(ps.userId).catch(err => {
|
||||
if (err.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
|
||||
if (err.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(this.meta.errors.noSuchUser);
|
||||
throw err;
|
||||
});
|
||||
|
||||
|
|
|
@ -4702,6 +4702,125 @@ export const endpoints = {
|
|||
}]
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//#region following
|
||||
'following/requests/accept': {
|
||||
tags: ['following', 'account'],
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'write:following',
|
||||
|
||||
errors: {
|
||||
noSuchUser: {
|
||||
message: 'No such user.',
|
||||
code: 'NO_SUCH_USER',
|
||||
id: '66ce1645-d66c-46bb-8b79-96739af885bd',
|
||||
},
|
||||
noFollowRequest: {
|
||||
message: 'No follow request.',
|
||||
code: 'NO_FOLLOW_REQUEST',
|
||||
id: 'bcde4f8b-0913-4614-8881-614e522fb041',
|
||||
},
|
||||
},
|
||||
|
||||
defines: [{
|
||||
req: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
userId: { type: 'string', format: 'misskey:id' },
|
||||
},
|
||||
required: ['userId'],
|
||||
},
|
||||
res: undefined,
|
||||
}]
|
||||
},
|
||||
'following/requests/cancel': {
|
||||
tags: ['following', 'account'],
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'write:following',
|
||||
|
||||
errors: {
|
||||
noSuchUser: {
|
||||
message: 'No such user.',
|
||||
code: 'NO_SUCH_USER',
|
||||
id: '4e68c551-fc4c-4e46-bb41-7d4a37bf9dab',
|
||||
},
|
||||
|
||||
followRequestNotFound: {
|
||||
message: 'Follow request not found.',
|
||||
code: 'FOLLOW_REQUEST_NOT_FOUND',
|
||||
id: '089b125b-d338-482a-9a09-e2622ac9f8d4',
|
||||
},
|
||||
},
|
||||
|
||||
defines: [{
|
||||
req: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
userId: { type: 'string', format: 'misskey:id' },
|
||||
},
|
||||
required: ['userId'],
|
||||
},
|
||||
res: {
|
||||
$ref: 'https://misskey-hub.net/api/schemas/UserLite',
|
||||
}
|
||||
}]
|
||||
},
|
||||
'following/requests/list': {
|
||||
tags: ['following', 'account'],
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'read:following',
|
||||
|
||||
defines: [{
|
||||
req: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
sinceId: { type: 'string', format: 'misskey:id' },
|
||||
untilId: { type: 'string', format: 'misskey:id' },
|
||||
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
|
||||
},
|
||||
required: [],
|
||||
},
|
||||
res: {
|
||||
type: 'array',
|
||||
items: {
|
||||
$ref: 'https://misskey-hub.net/api/schemas/FollowRequest',
|
||||
},
|
||||
}
|
||||
}]
|
||||
},
|
||||
'following/requests/reject': {
|
||||
tags: ['following', 'account'],
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'write:following',
|
||||
|
||||
errors: {
|
||||
noSuchUser: {
|
||||
message: 'No such user.',
|
||||
code: 'NO_SUCH_USER',
|
||||
id: 'abc2ffa6-25b2-4380-ba99-321ff3a94555',
|
||||
},
|
||||
},
|
||||
|
||||
defines: [{
|
||||
req: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
userId: { type: 'string', format: 'misskey:id' },
|
||||
},
|
||||
required: ['userId'],
|
||||
},
|
||||
res: undefined,
|
||||
}]
|
||||
},
|
||||
//#endregion
|
||||
} as const satisfies { [x: string]: IEndpointMeta; };
|
||||
|
||||
/**
|
||||
|
|
|
@ -122,11 +122,7 @@ export type Stats = {
|
|||
|
||||
export type AuthSession = Packed<'AuthSession'>;
|
||||
|
||||
export type FollowRequest = {
|
||||
id: ID;
|
||||
follower: User;
|
||||
followee: User;
|
||||
};
|
||||
export type FollowRequest = Packed<'FollowRequest'>;
|
||||
|
||||
export type FollowingFolloweePopulated = Following & {
|
||||
followee: UserDetailed;
|
||||
|
|
|
@ -18,7 +18,10 @@ import { packedUserListSchema } from './schemas/user-list.js';
|
|||
import { packedAppSchema } from './schemas/app.js';
|
||||
import { packedDriveFileSchema } from './schemas/drive-file.js';
|
||||
import { packedDriveFolderSchema } from './schemas/drive-folder.js';
|
||||
import { packedFollowingSchema } from './schemas/following.js';
|
||||
import {
|
||||
packedFollowingSchema,
|
||||
packedFollowRequestSchema,
|
||||
} from './schemas/following.js';
|
||||
import { packedMutingSchema } from './schemas/muting.js';
|
||||
import { packedRenoteMutingSchema } from './schemas/renote-muting.js';
|
||||
import { packedBlockingSchema } from './schemas/blocking.js';
|
||||
|
@ -82,6 +85,7 @@ export const refs = {
|
|||
DriveFile: packedDriveFileSchema,
|
||||
DriveFolder: packedDriveFolderSchema,
|
||||
Following: packedFollowingSchema,
|
||||
FollowRequest: packedFollowRequestSchema,
|
||||
Muting: packedMutingSchema,
|
||||
RenoteMuting: packedRenoteMutingSchema,
|
||||
Blocking: packedBlockingSchema,
|
||||
|
|
|
@ -22,3 +22,19 @@ export const packedFollowingSchema = {
|
|||
'followerId',
|
||||
],
|
||||
} as const satisfies JSONSchema7Definition;
|
||||
|
||||
export const packedFollowRequestSchema = {
|
||||
$id: 'https://misskey-hub.net/api/schemas/FollowRequest',
|
||||
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { $ref: 'https://misskey-hub.net/api/schemas/Id' },
|
||||
followee: { $ref: 'https://misskey-hub.net/api/schemas/UserLite' },
|
||||
follower: { $ref: 'https://misskey-hub.net/api/schemas/UserLite' },
|
||||
},
|
||||
required: [
|
||||
'id',
|
||||
'followee',
|
||||
'follower',
|
||||
],
|
||||
} as const satisfies JSONSchema7Definition;
|
||||
|
|
Loading…
Reference in a new issue