mirror of
https://iceshrimp.dev/crimekillz/trashposs
synced 2024-11-24 01:39:06 +01:00
[backend] More Web API rewrite preparations
This commit is contained in:
parent
71d171a953
commit
b9c86d0d4c
@ -9,6 +9,6 @@ export class NoteController {
|
|||||||
@CurrentUser() me: ILocalUser | null,
|
@CurrentUser() me: ILocalUser | null,
|
||||||
@Params('id') id: string,
|
@Params('id') id: string,
|
||||||
) {
|
) {
|
||||||
NoteHandler.getNote(me, id);
|
NoteHandler.getNoteOrFail(me, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import { Controller, Get, CurrentUser, Params, } from "@iceshrimp/koa-openapi";
|
|||||||
import type { ILocalUser } from "@/models/entities/user.js";
|
import type { ILocalUser } from "@/models/entities/user.js";
|
||||||
import { NoteHandler } from "@/server/api/web/handlers/note.js";
|
import { NoteHandler } from "@/server/api/web/handlers/note.js";
|
||||||
import { NoteResponse } from "@/server/api/web/entities/note.js";
|
import { NoteResponse } from "@/server/api/web/entities/note.js";
|
||||||
|
import { notFound } from "@hapi/boom";
|
||||||
|
|
||||||
@Controller('/note')
|
@Controller('/note')
|
||||||
export class NoteController {
|
export class NoteController {
|
||||||
@ -10,6 +11,7 @@ export class NoteController {
|
|||||||
@CurrentUser() me: ILocalUser | null,
|
@CurrentUser() me: ILocalUser | null,
|
||||||
@Params('id') id: string,
|
@Params('id') id: string,
|
||||||
): Promise<NoteResponse> {
|
): Promise<NoteResponse> {
|
||||||
return NoteHandler.getNote(me, id);
|
return NoteHandler.getNoteOrFail(id, notFound("No such note"))
|
||||||
|
.then(note => NoteHandler.encodeOrFail(note, me));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Controller, CurrentUser, Get, Params, Query } from "@iceshrimp/koa-openapi";
|
import { Controller, CurrentUser, Get, Params, Query } from "@iceshrimp/koa-openapi";
|
||||||
import { UserDetailedResponse, UserResponse } from "@/server/api/web/entities/user.js";
|
import { UserResponse } from "@/server/api/web/entities/user.js";
|
||||||
import { TimelineResponse } from "@/server/api/web/entities/note.js";
|
import { TimelineResponse } from "@/server/api/web/entities/note.js";
|
||||||
import type { ILocalUser } from "@/models/entities/user.js";
|
import type { ILocalUser } from "@/models/entities/user.js";
|
||||||
import { UserHandler } from "@/server/api/web/handlers/user.js";
|
import { UserHandler } from "@/server/api/web/handlers/user.js";
|
||||||
@ -11,10 +11,8 @@ export class UserController {
|
|||||||
@CurrentUser() me: ILocalUser | null,
|
@CurrentUser() me: ILocalUser | null,
|
||||||
@Params('id') id: string,
|
@Params('id') id: string,
|
||||||
@Query('detail') detail: boolean
|
@Query('detail') detail: boolean
|
||||||
): Promise<UserResponse | UserDetailedResponse> {
|
): Promise<UserResponse> {
|
||||||
return detail
|
return UserHandler.getUser(me, id);
|
||||||
? UserHandler.getUser(me, id)
|
|
||||||
: UserHandler.getUserDetailed(me, id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('/:id/notes')
|
@Get('/:id/notes')
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
|
|
||||||
export namespace WebEntities {}
|
|
@ -1,13 +1,15 @@
|
|||||||
import { Note } from "@/models/entities/note.js";
|
import { Note } from "@/models/entities/note.js";
|
||||||
|
import { UserResponse } from "@/server/api/web/entities/user.js";
|
||||||
|
|
||||||
namespace WebEntities {
|
export type NoteResponse = {
|
||||||
export type NoteResponse = {
|
id: Note["id"];
|
||||||
id: Note["id"];
|
text: string | null;
|
||||||
|
user: UserResponse;
|
||||||
|
reply: NoteResponse | undefined | null; // Undefined if no record, null if not visible
|
||||||
|
renote: NoteResponse | undefined | null; // Undefined if no record, null if not visible
|
||||||
|
};
|
||||||
|
|
||||||
};
|
export type TimelineResponse = {
|
||||||
|
notes: NoteResponse[];
|
||||||
export type TimelineResponse = {
|
pagination: {}; //TODO
|
||||||
notes: NoteResponse[],
|
};
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
@ -4,8 +4,3 @@ export type UserResponse = {
|
|||||||
avatarUrl?: string;
|
avatarUrl?: string;
|
||||||
bannerUrl?: string;
|
bannerUrl?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserDetailedResponse = UserResponse & {
|
|
||||||
followers: number;
|
|
||||||
following: number;
|
|
||||||
}
|
|
||||||
|
@ -1,17 +1,41 @@
|
|||||||
import { ILocalUser } from "@/models/entities/user.js";
|
import { ILocalUser } from "@/models/entities/user.js";
|
||||||
import { NoteResponse } from "@/server/api/web/entities/note.js";
|
import { NoteResponse } from "@/server/api/web/entities/note.js";
|
||||||
import { Notes } from "@/models/index.js";
|
import { Notes } from "@/models/index.js";
|
||||||
import { notFound } from "@hapi/boom";
|
import { Boom, notFound, internal } from "@hapi/boom";
|
||||||
|
import { Note } from "@/models/entities/note.js";
|
||||||
|
import { UserHandler } from "@/server/api/web/handlers/user.js";
|
||||||
|
import isQuote from "@/misc/is-quote.js";
|
||||||
|
|
||||||
export class NoteHandler {
|
export class NoteHandler {
|
||||||
static async getNote(me: ILocalUser | null, id: string): Promise<NoteResponse> {
|
static async getNoteOrFail(id: string, error: Boom = internal('No such note')): Promise<Note> {
|
||||||
const note = await Notes.findOneBy({ id });
|
const note = await this.getNote(id);
|
||||||
if (!note) throw notFound('No such user');
|
if (!note) throw error;
|
||||||
|
|
||||||
return note;
|
return note;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async encode(me: ILocalUser | null, id: string): Promise<NoteResponse | null> {
|
static async getNote(id: string): Promise<Note | null> {
|
||||||
|
return Notes.findOneBy({ id });
|
||||||
|
}
|
||||||
|
|
||||||
|
static async encode(note: Note, me: ILocalUser | null, recurse: number = 2): Promise<NoteResponse | null> {
|
||||||
|
if (!await Notes.isVisibleForMe(note, me?.id ?? null)) return null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: note.id,
|
||||||
|
text: note.text,
|
||||||
|
user: note.user ? await UserHandler.encode(note.user, me) : await UserHandler.getUser(me, note.userId),
|
||||||
|
renote: note.renoteId && recurse > 0 ? await this.encode(note.renote ?? await this.getNoteOrFail(note.renoteId), me, isQuote(note) ? --recurse : 0) : undefined,
|
||||||
|
reply: note.replyId && recurse > 0 ? await this.encode(note.renote ?? await this.getNoteOrFail(note.replyId), me, 0) : undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static async encodeOrFail(note: Note, me: ILocalUser | null, error: Boom = internal("Cannot encode note not visible for user")): Promise<NoteResponse> {
|
||||||
|
const result = await this.encode(note, me);
|
||||||
|
if (!result) throw error;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async encodeMany(notes: Note[], me: ILocalUser | null): Promise<NoteResponse[]> {
|
||||||
|
return Promise.all(notes.map(n => this.encodeOrFail(n, me)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { TimelineResponse } from "@/server/api/web/entities/note.js";
|
import { TimelineResponse } from "@/server/api/web/entities/note.js";
|
||||||
import { UserDetailedResponse, UserResponse } from "@/server/api/web/entities/user.js";
|
import { UserResponse } from "@/server/api/web/entities/user.js";
|
||||||
import { Notes, UserProfiles, Users } from "@/models/index.js";
|
import { Notes, UserProfiles, Users } from "@/models/index.js";
|
||||||
import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js";
|
import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js";
|
||||||
import { generateVisibilityQuery } from "@/server/api/common/generate-visibility-query.js";
|
import { generateVisibilityQuery } from "@/server/api/common/generate-visibility-query.js";
|
||||||
import { generateMutedUserQuery } from "@/server/api/common/generate-muted-user-query.js";
|
import { generateMutedUserQuery } from "@/server/api/common/generate-muted-user-query.js";
|
||||||
import { generateBlockedUserQuery } from "@/server/api/common/generate-block-query.js";
|
import { generateBlockedUserQuery } from "@/server/api/common/generate-block-query.js";
|
||||||
import { ILocalUser } from "@/models/entities/user.js";
|
import { ILocalUser, User } from "@/models/entities/user.js";
|
||||||
import { notFound } from "@hapi/boom";
|
import { notFound } from "@hapi/boom";
|
||||||
|
import { NoteHandler } from "@/server/api/web/handlers/note.js";
|
||||||
|
|
||||||
export class UserHandler {
|
export class UserHandler {
|
||||||
public static async getUserNotes(me: ILocalUser | null, id: string, limit: number, replies: boolean): Promise<TimelineResponse> {
|
public static async getUserNotes(me: ILocalUser | null, id: string, limit: number, replies: boolean): Promise<TimelineResponse> {
|
||||||
@ -31,12 +32,21 @@ export class UserHandler {
|
|||||||
query.andWhere("note.replyId IS NULL");
|
query.andWhere("note.replyId IS NULL");
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.take(Math.min(limit, 100)).getMany();
|
const result = query.take(Math.min(limit, 100)).getMany();
|
||||||
|
return {
|
||||||
|
notes: await NoteHandler.encodeMany(await result, me),
|
||||||
|
pagination: {},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async getUser(me: ILocalUser | null, id: string): Promise<UserResponse> {
|
public static async getUser(me: ILocalUser | null, id: string): Promise<UserResponse> {
|
||||||
const user = await Users.findOneBy({ id });
|
const user = await Users.findOneBy({ id });
|
||||||
if (!user) throw notFound('No such user');
|
if (!user) throw notFound('No such user');
|
||||||
|
|
||||||
|
return this.encode(user, me);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async encode(user: User, me: ILocalUser | null): Promise<UserResponse> {
|
||||||
return {
|
return {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
username: user.username,
|
username: user.username,
|
||||||
@ -44,13 +54,4 @@ export class UserHandler {
|
|||||||
bannerUrl: user.bannerUrl ?? undefined,
|
bannerUrl: user.bannerUrl ?? undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async getUserDetailed(me: ILocalUser | null, id: string): Promise<UserDetailedResponse> {
|
|
||||||
const profile = await UserProfiles.findOneBy({ userId: id });
|
|
||||||
return {
|
|
||||||
followers: 0,
|
|
||||||
following: 0,
|
|
||||||
...await this.getUser(me, id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user