mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 08:28:19 +01:00
refactor(api): ♻️ Refactor more routes into OpenAPI-compatible formats
This commit is contained in:
parent
02cb8bcd4f
commit
bcbc9e6bf1
|
|
@ -39,7 +39,7 @@ const route = createRoute({
|
|||
middleware: [auth(meta.auth, meta.permissions)],
|
||||
responses: {
|
||||
200: {
|
||||
description: "User blocked",
|
||||
description: "Updated relationship",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: Relationship.schema,
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ const route = createRoute({
|
|||
middleware: [auth(meta.auth, meta.permissions)],
|
||||
responses: {
|
||||
200: {
|
||||
description: "User followed",
|
||||
description: "Updated relationship",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: Relationship.schema,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { apiRoute, applyConfig, auth, handleZodError } from "@/api";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import { apiRoute, applyConfig, auth } from "@/api";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { z } from "zod";
|
||||
import { RolePermissions } from "~/drizzle/schema";
|
||||
import { User } from "~/packages/database-interface/user";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["GET"],
|
||||
|
|
@ -26,23 +27,46 @@ export const schemas = {
|
|||
}),
|
||||
};
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.on(
|
||||
meta.allowedMethods,
|
||||
meta.route,
|
||||
zValidator("param", schemas.param, handleZodError),
|
||||
auth(meta.auth, meta.permissions),
|
||||
async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user } = context.get("auth");
|
||||
|
||||
const foundUser = await User.fromId(id);
|
||||
|
||||
if (!foundUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
return context.json(foundUser.toApi(user?.id === foundUser.id));
|
||||
const route = createRoute({
|
||||
method: "get",
|
||||
path: "/api/v1/accounts/{id}",
|
||||
summary: "Get account data",
|
||||
description: "Gets the specified account data",
|
||||
middleware: [auth(meta.auth, meta.permissions)],
|
||||
request: {
|
||||
params: schemas.param,
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: "Account data",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: User.schema,
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
404: {
|
||||
description: "User not found",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.openapi(route, async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user } = context.get("auth");
|
||||
|
||||
const foundUser = await User.fromId(id);
|
||||
|
||||
if (!foundUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
return context.json(foundUser.toApi(user?.id === foundUser.id), 200);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { apiRoute, applyConfig, auth, handleZodError } from "@/api";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import { apiRoute, applyConfig, auth } from "@/api";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { z } from "zod";
|
||||
import { RolePermissions } from "~/drizzle/schema";
|
||||
import { Relationship } from "~/packages/database-interface/relationship";
|
||||
import { User } from "~/packages/database-interface/user";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["POST"],
|
||||
|
|
@ -39,41 +40,78 @@ export const schemas = {
|
|||
}),
|
||||
};
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.on(
|
||||
meta.allowedMethods,
|
||||
meta.route,
|
||||
zValidator("param", schemas.param, handleZodError),
|
||||
zValidator("json", schemas.json, handleZodError),
|
||||
auth(meta.auth, meta.permissions),
|
||||
async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user } = context.get("auth");
|
||||
// TODO: Add duration support
|
||||
const { notifications } = context.req.valid("json");
|
||||
|
||||
if (!user) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const foundRelationship = await Relationship.fromOwnerAndSubject(
|
||||
user,
|
||||
otherUser,
|
||||
);
|
||||
|
||||
// TODO: Implement duration
|
||||
await foundRelationship.update({
|
||||
muting: true,
|
||||
mutingNotifications: notifications ?? true,
|
||||
});
|
||||
|
||||
return context.json(foundRelationship.toApi());
|
||||
const route = createRoute({
|
||||
method: "post",
|
||||
path: "/api/v1/accounts/{id}/mute",
|
||||
summary: "Mute user",
|
||||
description: "Mute a user",
|
||||
middleware: [auth(meta.auth, meta.permissions)],
|
||||
request: {
|
||||
params: schemas.param,
|
||||
body: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: schemas.json,
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: "Updated relationship",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: Relationship.schema,
|
||||
},
|
||||
},
|
||||
},
|
||||
401: {
|
||||
description: "Unauthorized",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
404: {
|
||||
description: "User not found",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.openapi(route, async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user } = context.get("auth");
|
||||
// TODO: Add duration support
|
||||
const { notifications } = context.req.valid("json");
|
||||
|
||||
if (!user) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const foundRelationship = await Relationship.fromOwnerAndSubject(
|
||||
user,
|
||||
otherUser,
|
||||
);
|
||||
|
||||
// TODO: Implement duration
|
||||
await foundRelationship.update({
|
||||
muting: true,
|
||||
mutingNotifications: notifications ?? true,
|
||||
});
|
||||
|
||||
return context.json(foundRelationship.toApi(), 200);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { apiRoute, applyConfig, auth, handleZodError } from "@/api";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import { apiRoute, applyConfig, auth } from "@/api";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { z } from "zod";
|
||||
import { RolePermissions } from "~/drizzle/schema";
|
||||
import { Relationship } from "~/packages/database-interface/relationship";
|
||||
import { User } from "~/packages/database-interface/user";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["POST"],
|
||||
|
|
@ -33,38 +34,75 @@ export const schemas = {
|
|||
}),
|
||||
};
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.on(
|
||||
meta.allowedMethods,
|
||||
meta.route,
|
||||
zValidator("param", schemas.param, handleZodError),
|
||||
zValidator("json", schemas.json, handleZodError),
|
||||
auth(meta.auth, meta.permissions),
|
||||
async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user } = context.get("auth");
|
||||
const { comment } = context.req.valid("json");
|
||||
|
||||
if (!user) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const foundRelationship = await Relationship.fromOwnerAndSubject(
|
||||
user,
|
||||
otherUser,
|
||||
);
|
||||
|
||||
await foundRelationship.update({
|
||||
note: comment,
|
||||
});
|
||||
|
||||
return context.json(foundRelationship.toApi());
|
||||
const route = createRoute({
|
||||
method: "post",
|
||||
path: "/api/v1/accounts/{id}/note",
|
||||
summary: "Set note",
|
||||
description: "Set a note on a user's profile, visible only to you",
|
||||
middleware: [auth(meta.auth, meta.permissions)],
|
||||
request: {
|
||||
params: schemas.param,
|
||||
body: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: schemas.json,
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: "Updated relationship",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: Relationship.schema,
|
||||
},
|
||||
},
|
||||
},
|
||||
401: {
|
||||
description: "Unauthorized",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
404: {
|
||||
description: "User not found",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.openapi(route, async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user } = context.get("auth");
|
||||
const { comment } = context.req.valid("json");
|
||||
|
||||
if (!user) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const foundRelationship = await Relationship.fromOwnerAndSubject(
|
||||
user,
|
||||
otherUser,
|
||||
);
|
||||
|
||||
await foundRelationship.update({
|
||||
note: comment,
|
||||
});
|
||||
|
||||
return context.json(foundRelationship.toApi(), 200);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { apiRoute, applyConfig, auth, handleZodError } from "@/api";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import { apiRoute, applyConfig, auth } from "@/api";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { z } from "zod";
|
||||
import { RolePermissions } from "~/drizzle/schema";
|
||||
import { Relationship } from "~/packages/database-interface/relationship";
|
||||
import { User } from "~/packages/database-interface/user";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["POST"],
|
||||
|
|
@ -30,36 +31,67 @@ export const schemas = {
|
|||
}),
|
||||
};
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.on(
|
||||
meta.allowedMethods,
|
||||
meta.route,
|
||||
zValidator("param", schemas.param, handleZodError),
|
||||
auth(meta.auth, meta.permissions),
|
||||
async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user } = context.get("auth");
|
||||
|
||||
if (!user) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const foundRelationship = await Relationship.fromOwnerAndSubject(
|
||||
user,
|
||||
otherUser,
|
||||
);
|
||||
|
||||
await foundRelationship.update({
|
||||
endorsed: true,
|
||||
});
|
||||
|
||||
return context.json(foundRelationship.toApi());
|
||||
const route = createRoute({
|
||||
method: "post",
|
||||
path: "/api/v1/accounts/{id}/pin",
|
||||
summary: "Pin user",
|
||||
description: "Pin a user to your profile",
|
||||
middleware: [auth(meta.auth, meta.permissions)],
|
||||
request: {
|
||||
params: schemas.param,
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: "Updated relationship",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: Relationship.schema,
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
401: {
|
||||
description: "Unauthorized",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
404: {
|
||||
description: "User not found",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.openapi(route, async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user } = context.get("auth");
|
||||
|
||||
if (!user) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const foundRelationship = await Relationship.fromOwnerAndSubject(
|
||||
user,
|
||||
otherUser,
|
||||
);
|
||||
|
||||
await foundRelationship.update({
|
||||
endorsed: true,
|
||||
});
|
||||
|
||||
return context.json(foundRelationship.toApi(), 200);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { apiRoute, applyConfig, auth, handleZodError } from "@/api";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import { apiRoute, applyConfig, auth } from "@/api";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { z } from "zod";
|
||||
import { RolePermissions } from "~/drizzle/schema";
|
||||
import { User } from "~/packages/database-interface/user";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["POST"],
|
||||
|
|
@ -26,29 +27,72 @@ export const schemas = {
|
|||
}),
|
||||
};
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.on(
|
||||
meta.allowedMethods,
|
||||
meta.route,
|
||||
zValidator("param", schemas.param, handleZodError),
|
||||
auth(meta.auth, meta.permissions),
|
||||
async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user } = context.get("auth");
|
||||
|
||||
if (!user) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const newUser = await otherUser.updateFromRemote();
|
||||
|
||||
return context.json(newUser.toApi(false));
|
||||
const route = createRoute({
|
||||
method: "post",
|
||||
path: "/api/v1/accounts/{id}/refetch",
|
||||
summary: "Refetch user",
|
||||
description: "Refetch a user's profile from the remote server",
|
||||
middleware: [auth(meta.auth, meta.permissions)],
|
||||
request: {
|
||||
params: schemas.param,
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: "Updated user data",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: User.schema,
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
401: {
|
||||
description: "Unauthorized",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
404: {
|
||||
description: "User not found",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
400: {
|
||||
description: "User is local",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.openapi(route, async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user } = context.get("auth");
|
||||
|
||||
if (!user) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
if (otherUser.isLocal()) {
|
||||
return context.json({ error: "Cannot refetch a local user" }, 400);
|
||||
}
|
||||
|
||||
const newUser = await otherUser.updateFromRemote();
|
||||
|
||||
return context.json(newUser.toApi(false), 200);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { apiRoute, applyConfig, auth, handleZodError } from "@/api";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import { apiRoute, applyConfig, auth } from "@/api";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { z } from "zod";
|
||||
import { RolePermissions } from "~/drizzle/schema";
|
||||
import { Relationship } from "~/packages/database-interface/relationship";
|
||||
import { User } from "~/packages/database-interface/user";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["POST"],
|
||||
|
|
@ -30,43 +31,74 @@ export const schemas = {
|
|||
}),
|
||||
};
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.on(
|
||||
meta.allowedMethods,
|
||||
meta.route,
|
||||
zValidator("param", schemas.param, handleZodError),
|
||||
auth(meta.auth, meta.permissions),
|
||||
async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user: self } = context.get("auth");
|
||||
|
||||
if (!self) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const oppositeRelationship = await Relationship.fromOwnerAndSubject(
|
||||
otherUser,
|
||||
self,
|
||||
);
|
||||
|
||||
if (oppositeRelationship.data.following) {
|
||||
await oppositeRelationship.update({
|
||||
following: false,
|
||||
});
|
||||
}
|
||||
|
||||
const foundRelationship = await Relationship.fromOwnerAndSubject(
|
||||
self,
|
||||
otherUser,
|
||||
);
|
||||
|
||||
return context.json(foundRelationship.toApi());
|
||||
const route = createRoute({
|
||||
method: "post",
|
||||
path: "/api/v1/accounts/{id}/remove_from_followers",
|
||||
summary: "Remove user from followers",
|
||||
description: "Remove a user from your followers",
|
||||
middleware: [auth(meta.auth, meta.permissions)],
|
||||
request: {
|
||||
params: schemas.param,
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: "Updated relationship",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: Relationship.schema,
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
401: {
|
||||
description: "Unauthorized",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
404: {
|
||||
description: "User not found",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.openapi(route, async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user: self } = context.get("auth");
|
||||
|
||||
if (!self) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const oppositeRelationship = await Relationship.fromOwnerAndSubject(
|
||||
otherUser,
|
||||
self,
|
||||
);
|
||||
|
||||
if (oppositeRelationship.data.following) {
|
||||
await oppositeRelationship.update({
|
||||
following: false,
|
||||
});
|
||||
}
|
||||
|
||||
const foundRelationship = await Relationship.fromOwnerAndSubject(
|
||||
self,
|
||||
otherUser,
|
||||
);
|
||||
|
||||
return context.json(foundRelationship.toApi(), 200);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,16 +1,12 @@
|
|||
import {
|
||||
apiRoute,
|
||||
applyConfig,
|
||||
auth,
|
||||
handleZodError,
|
||||
idValidator,
|
||||
} from "@/api";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import { apiRoute, applyConfig, auth, idValidator } from "@/api";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { and, eq, gt, gte, isNull, lt, sql } from "drizzle-orm";
|
||||
import { z } from "zod";
|
||||
import { Notes, RolePermissions } from "~/drizzle/schema";
|
||||
import { Note } from "~/packages/database-interface/note";
|
||||
import { Timeline } from "~/packages/database-interface/timeline";
|
||||
import { User } from "~/packages/database-interface/user";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["GET"],
|
||||
|
|
@ -60,61 +56,89 @@ export const schemas = {
|
|||
}),
|
||||
};
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.on(
|
||||
meta.allowedMethods,
|
||||
meta.route,
|
||||
zValidator("param", schemas.param, handleZodError),
|
||||
zValidator("query", schemas.query, handleZodError),
|
||||
auth(meta.auth, meta.permissions),
|
||||
async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user } = context.get("auth");
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const {
|
||||
max_id,
|
||||
min_id,
|
||||
since_id,
|
||||
limit,
|
||||
exclude_reblogs,
|
||||
only_media,
|
||||
exclude_replies,
|
||||
pinned,
|
||||
} = context.req.valid("query");
|
||||
|
||||
const { objects, link } = await Timeline.getNoteTimeline(
|
||||
and(
|
||||
max_id ? lt(Notes.id, max_id) : undefined,
|
||||
since_id ? gte(Notes.id, since_id) : undefined,
|
||||
min_id ? gt(Notes.id, min_id) : undefined,
|
||||
eq(Notes.authorId, id),
|
||||
only_media
|
||||
? sql`EXISTS (SELECT 1 FROM "Attachments" WHERE "Attachments"."noteId" = ${Notes.id})`
|
||||
: undefined,
|
||||
pinned
|
||||
? sql`EXISTS (SELECT 1 FROM "UserToPinnedNotes" WHERE "UserToPinnedNotes"."noteId" = ${Notes.id} AND "UserToPinnedNotes"."userId" = ${otherUser.id})`
|
||||
: undefined,
|
||||
exclude_reblogs ? isNull(Notes.reblogId) : undefined,
|
||||
exclude_replies ? isNull(Notes.replyId) : undefined,
|
||||
),
|
||||
limit,
|
||||
context.req.url,
|
||||
user?.id,
|
||||
);
|
||||
|
||||
return context.json(
|
||||
await Promise.all(objects.map((note) => note.toApi(otherUser))),
|
||||
200,
|
||||
{
|
||||
link,
|
||||
const route = createRoute({
|
||||
method: "get",
|
||||
path: "/api/v1/accounts/{id}/statuses",
|
||||
summary: "Get account statuses",
|
||||
description: "Gets an paginated list of statuses by the specified account",
|
||||
middleware: [auth(meta.auth, meta.permissions)],
|
||||
request: {
|
||||
params: schemas.param,
|
||||
query: schemas.query,
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: "A list of statuses by the specified account",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.array(Note.schema),
|
||||
},
|
||||
);
|
||||
},
|
||||
headers: {
|
||||
Link: {
|
||||
description: "Links to the next and previous pages",
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
404: {
|
||||
description: "User not found",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.openapi(route, async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user } = context.get("auth");
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const {
|
||||
max_id,
|
||||
min_id,
|
||||
since_id,
|
||||
limit,
|
||||
exclude_reblogs,
|
||||
only_media,
|
||||
exclude_replies,
|
||||
pinned,
|
||||
} = context.req.valid("query");
|
||||
|
||||
const { objects, link } = await Timeline.getNoteTimeline(
|
||||
and(
|
||||
max_id ? lt(Notes.id, max_id) : undefined,
|
||||
since_id ? gte(Notes.id, since_id) : undefined,
|
||||
min_id ? gt(Notes.id, min_id) : undefined,
|
||||
eq(Notes.authorId, id),
|
||||
only_media
|
||||
? sql`EXISTS (SELECT 1 FROM "Attachments" WHERE "Attachments"."noteId" = ${Notes.id})`
|
||||
: undefined,
|
||||
pinned
|
||||
? sql`EXISTS (SELECT 1 FROM "UserToPinnedNotes" WHERE "UserToPinnedNotes"."noteId" = ${Notes.id} AND "UserToPinnedNotes"."userId" = ${otherUser.id})`
|
||||
: undefined,
|
||||
exclude_reblogs ? isNull(Notes.reblogId) : undefined,
|
||||
exclude_replies ? isNull(Notes.replyId) : undefined,
|
||||
),
|
||||
limit,
|
||||
context.req.url,
|
||||
user?.id,
|
||||
);
|
||||
|
||||
return context.json(
|
||||
await Promise.all(objects.map((note) => note.toApi(otherUser))),
|
||||
200,
|
||||
{
|
||||
link,
|
||||
},
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { apiRoute, applyConfig, auth, handleZodError } from "@/api";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import { apiRoute, applyConfig, auth } from "@/api";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { z } from "zod";
|
||||
import { RolePermissions } from "~/drizzle/schema";
|
||||
import { Relationship } from "~/packages/database-interface/relationship";
|
||||
import { User } from "~/packages/database-interface/user";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["POST"],
|
||||
|
|
@ -30,38 +31,69 @@ export const schemas = {
|
|||
}),
|
||||
};
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.on(
|
||||
meta.allowedMethods,
|
||||
meta.route,
|
||||
zValidator("param", schemas.param, handleZodError),
|
||||
auth(meta.auth, meta.permissions),
|
||||
async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user } = context.get("auth");
|
||||
|
||||
if (!user) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const foundRelationship = await Relationship.fromOwnerAndSubject(
|
||||
user,
|
||||
otherUser,
|
||||
);
|
||||
|
||||
if (foundRelationship.data.blocking) {
|
||||
await foundRelationship.update({
|
||||
blocking: false,
|
||||
});
|
||||
}
|
||||
|
||||
return context.json(foundRelationship.toApi());
|
||||
const route = createRoute({
|
||||
method: "post",
|
||||
path: "/api/v1/accounts/{id}/unblock",
|
||||
summary: "Unblock user",
|
||||
description: "Unblock a user",
|
||||
middleware: [auth(meta.auth, meta.permissions)],
|
||||
request: {
|
||||
params: schemas.param,
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: "Updated relationship",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: Relationship.schema,
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
401: {
|
||||
description: "Unauthorized",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
404: {
|
||||
description: "User not found",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.openapi(route, async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user } = context.get("auth");
|
||||
|
||||
if (!user) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const foundRelationship = await Relationship.fromOwnerAndSubject(
|
||||
user,
|
||||
otherUser,
|
||||
);
|
||||
|
||||
if (foundRelationship.data.blocking) {
|
||||
await foundRelationship.update({
|
||||
blocking: false,
|
||||
});
|
||||
}
|
||||
|
||||
return context.json(foundRelationship.toApi(), 200);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { apiRoute, applyConfig, auth, handleZodError } from "@/api";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import { apiRoute, applyConfig, auth } from "@/api";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { z } from "zod";
|
||||
import { RolePermissions } from "~/drizzle/schema";
|
||||
import { Relationship } from "~/packages/database-interface/relationship";
|
||||
import { User } from "~/packages/database-interface/user";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["POST"],
|
||||
|
|
@ -30,36 +31,75 @@ export const schemas = {
|
|||
}),
|
||||
};
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.on(
|
||||
meta.allowedMethods,
|
||||
meta.route,
|
||||
zValidator("param", schemas.param, handleZodError),
|
||||
auth(meta.auth, meta.permissions),
|
||||
async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user: self } = context.get("auth");
|
||||
|
||||
if (!self) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const foundRelationship = await Relationship.fromOwnerAndSubject(
|
||||
self,
|
||||
otherUser,
|
||||
);
|
||||
|
||||
if (!(await self.unfollow(otherUser, foundRelationship))) {
|
||||
return context.json({ error: "Failed to unfollow user" }, 500);
|
||||
}
|
||||
|
||||
return context.json(foundRelationship.toApi());
|
||||
const route = createRoute({
|
||||
method: "post",
|
||||
path: "/api/v1/accounts/{id}/unfollow",
|
||||
summary: "Unfollow user",
|
||||
description: "Unfollow a user",
|
||||
middleware: [auth(meta.auth, meta.permissions)],
|
||||
request: {
|
||||
params: schemas.param,
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: "Updated relationship",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: Relationship.schema,
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
401: {
|
||||
description: "Unauthorized",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
404: {
|
||||
description: "User not found",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
500: {
|
||||
description: "Failed to unfollow user during federation",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.openapi(route, async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user: self } = context.get("auth");
|
||||
|
||||
if (!self) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const foundRelationship = await Relationship.fromOwnerAndSubject(
|
||||
self,
|
||||
otherUser,
|
||||
);
|
||||
|
||||
if (!(await self.unfollow(otherUser, foundRelationship))) {
|
||||
return context.json({ error: "Failed to unfollow user" }, 500);
|
||||
}
|
||||
|
||||
return context.json(foundRelationship.toApi(), 200);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { apiRoute, applyConfig, auth, handleZodError } from "@/api";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import { apiRoute, applyConfig, auth } from "@/api";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { z } from "zod";
|
||||
import { RolePermissions } from "~/drizzle/schema";
|
||||
import { Relationship } from "~/packages/database-interface/relationship";
|
||||
import { User } from "~/packages/database-interface/user";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["POST"],
|
||||
|
|
@ -30,39 +31,70 @@ export const schemas = {
|
|||
}),
|
||||
};
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.on(
|
||||
meta.allowedMethods,
|
||||
meta.route,
|
||||
zValidator("param", schemas.param, handleZodError),
|
||||
auth(meta.auth, meta.permissions),
|
||||
async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user: self } = context.get("auth");
|
||||
|
||||
if (!self) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const user = await User.fromId(id);
|
||||
|
||||
if (!user) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const foundRelationship = await Relationship.fromOwnerAndSubject(
|
||||
self,
|
||||
user,
|
||||
);
|
||||
|
||||
if (foundRelationship.data.muting) {
|
||||
await foundRelationship.update({
|
||||
muting: false,
|
||||
mutingNotifications: false,
|
||||
});
|
||||
}
|
||||
|
||||
return context.json(foundRelationship.toApi());
|
||||
const route = createRoute({
|
||||
method: "post",
|
||||
path: "/api/v1/accounts/{id}/unmute",
|
||||
summary: "Unmute user",
|
||||
description: "Unmute a user",
|
||||
middleware: [auth(meta.auth, meta.permissions)],
|
||||
request: {
|
||||
params: schemas.param,
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: "Updated relationship",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: Relationship.schema,
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
401: {
|
||||
description: "Unauthorized",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
404: {
|
||||
description: "User not found",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.openapi(route, async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user: self } = context.get("auth");
|
||||
|
||||
if (!self) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const user = await User.fromId(id);
|
||||
|
||||
if (!user) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const foundRelationship = await Relationship.fromOwnerAndSubject(
|
||||
self,
|
||||
user,
|
||||
);
|
||||
|
||||
if (foundRelationship.data.muting) {
|
||||
await foundRelationship.update({
|
||||
muting: false,
|
||||
mutingNotifications: false,
|
||||
});
|
||||
}
|
||||
|
||||
return context.json(foundRelationship.toApi(), 200);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { apiRoute, applyConfig, auth, handleZodError } from "@/api";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import { apiRoute, applyConfig, auth } from "@/api";
|
||||
import { createRoute } from "@hono/zod-openapi";
|
||||
import { z } from "zod";
|
||||
import { RolePermissions } from "~/drizzle/schema";
|
||||
import { Relationship } from "~/packages/database-interface/relationship";
|
||||
import { User } from "~/packages/database-interface/user";
|
||||
import { ErrorSchema } from "~/types/api";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["POST"],
|
||||
|
|
@ -30,38 +31,69 @@ export const schemas = {
|
|||
}),
|
||||
};
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.on(
|
||||
meta.allowedMethods,
|
||||
meta.route,
|
||||
zValidator("param", schemas.param, handleZodError),
|
||||
auth(meta.auth, meta.permissions),
|
||||
async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user: self } = context.get("auth");
|
||||
|
||||
if (!self) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const foundRelationship = await Relationship.fromOwnerAndSubject(
|
||||
self,
|
||||
otherUser,
|
||||
);
|
||||
|
||||
if (foundRelationship.data.endorsed) {
|
||||
await foundRelationship.update({
|
||||
endorsed: false,
|
||||
});
|
||||
}
|
||||
|
||||
return context.json(foundRelationship.toApi());
|
||||
const route = createRoute({
|
||||
method: "post",
|
||||
path: "/api/v1/accounts/{id}/unpin",
|
||||
summary: "Unpin user",
|
||||
description: "Unpin a user from your profile",
|
||||
middleware: [auth(meta.auth, meta.permissions)],
|
||||
request: {
|
||||
params: schemas.param,
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: "Updated relationship",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: Relationship.schema,
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
401: {
|
||||
description: "Unauthorized",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
404: {
|
||||
description: "User not found",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: ErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.openapi(route, async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
const { user: self } = context.get("auth");
|
||||
|
||||
if (!self) {
|
||||
return context.json({ error: "Unauthorized" }, 401);
|
||||
}
|
||||
|
||||
const otherUser = await User.fromId(id);
|
||||
|
||||
if (!otherUser) {
|
||||
return context.json({ error: "User not found" }, 404);
|
||||
}
|
||||
|
||||
const foundRelationship = await Relationship.fromOwnerAndSubject(
|
||||
self,
|
||||
otherUser,
|
||||
);
|
||||
|
||||
if (foundRelationship.data.endorsed) {
|
||||
await foundRelationship.update({
|
||||
endorsed: false,
|
||||
});
|
||||
}
|
||||
|
||||
return context.json(foundRelationship.toApi(), 200);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
4
app.ts
4
app.ts
|
|
@ -2,6 +2,7 @@ import { sentry } from "@/sentry";
|
|||
import { cors } from "@hono/hono/cors";
|
||||
import { prettyJSON } from "@hono/hono/pretty-json";
|
||||
import { secureHeaders } from "@hono/hono/secure-headers";
|
||||
import { swaggerUI } from "@hono/swagger-ui";
|
||||
import { OpenAPIHono } from "@hono/zod-openapi";
|
||||
/* import { prometheus } from "@hono/prometheus";
|
||||
*/ import { getLogger } from "@logtape/logtape";
|
||||
|
|
@ -13,14 +14,15 @@ import { boundaryCheck } from "./middlewares/boundary-check";
|
|||
import { ipBans } from "./middlewares/ip-bans";
|
||||
import { logger } from "./middlewares/logger";
|
||||
import { routes } from "./routes";
|
||||
import { swaggerUI } from "@hono/swagger-ui";
|
||||
import type { ApiRouteExports, HonoEnv } from "./types/api";
|
||||
import { handleZodError } from "@/api";
|
||||
|
||||
export const appFactory = async () => {
|
||||
const serverLogger = getLogger("server");
|
||||
|
||||
const app = new OpenAPIHono<HonoEnv>({
|
||||
strict: false,
|
||||
defaultHook: handleZodError,
|
||||
});
|
||||
|
||||
/* const { printMetrics, registerMetrics } = prometheus({
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
eq,
|
||||
inArray,
|
||||
} from "drizzle-orm";
|
||||
import { z } from "zod";
|
||||
import { db } from "~/drizzle/db";
|
||||
import { Attachments } from "~/drizzle/schema";
|
||||
import { MediaBackendType } from "~/packages/config-manager/config.type";
|
||||
|
|
@ -21,6 +22,34 @@ import { BaseInterface } from "./base";
|
|||
export type AttachmentType = InferSelectModel<typeof Attachments>;
|
||||
|
||||
export class Attachment extends BaseInterface<typeof Attachments> {
|
||||
static schema: z.ZodType<ApiAttachment> = z.object({
|
||||
id: z.string().uuid(),
|
||||
type: z.enum(["unknown", "image", "gifv", "video", "audio"]),
|
||||
url: z.string().url(),
|
||||
remote_url: z.string().url().nullable(),
|
||||
preview_url: z.string().url().nullable(),
|
||||
text_url: z.string().url().nullable(),
|
||||
meta: z
|
||||
.object({
|
||||
width: z.number().optional(),
|
||||
height: z.number().optional(),
|
||||
fps: z.number().optional(),
|
||||
size: z.string().optional(),
|
||||
duration: z.number().optional(),
|
||||
length: z.string().optional(),
|
||||
aspect: z.number().optional(),
|
||||
original: z.object({
|
||||
width: z.number().optional(),
|
||||
height: z.number().optional(),
|
||||
size: z.string().optional(),
|
||||
aspect: z.number().optional(),
|
||||
}),
|
||||
})
|
||||
.nullable(),
|
||||
description: z.string().nullable(),
|
||||
blurhash: z.string().nullable(),
|
||||
});
|
||||
|
||||
async reload(): Promise<void> {
|
||||
const reloaded = await Attachment.fromId(this.data.id);
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import {
|
|||
} from "drizzle-orm";
|
||||
import { htmlToText } from "html-to-text";
|
||||
import { createRegExp, exactly, global } from "magic-regexp";
|
||||
import { z } from "zod";
|
||||
import {
|
||||
type Application,
|
||||
applicationToApi,
|
||||
|
|
@ -56,6 +57,96 @@ import { User } from "./user";
|
|||
* Gives helpers to fetch notes from database in a nice format
|
||||
*/
|
||||
export class Note extends BaseInterface<typeof Notes, StatusWithRelations> {
|
||||
static schema: z.ZodType<ApiStatus> = z.object({
|
||||
id: z.string().uuid(),
|
||||
uri: z.string().url(),
|
||||
url: z.string().url(),
|
||||
account: z.lazy(() => User.schema),
|
||||
in_reply_to_id: z.string().uuid().nullable(),
|
||||
in_reply_to_account_id: z.string().uuid().nullable(),
|
||||
reblog: z.lazy(() => Note.schema).nullable(),
|
||||
content: z.string(),
|
||||
plain_content: z.string().nullable(),
|
||||
created_at: z.string(),
|
||||
edited_at: z.string().nullable(),
|
||||
emojis: z.array(Emoji.schema),
|
||||
replies_count: z.number().int().nonnegative(),
|
||||
reblogs_count: z.number().int().nonnegative(),
|
||||
favourites_count: z.number().int().nonnegative(),
|
||||
reblogged: z.boolean().nullable(),
|
||||
favourited: z.boolean().nullable(),
|
||||
muted: z.boolean().nullable(),
|
||||
sensitive: z.boolean(),
|
||||
spoiler_text: z.string(),
|
||||
visibility: z.enum(["public", "unlisted", "private", "direct"]),
|
||||
media_attachments: z.array(Attachment.schema),
|
||||
mentions: z.array(
|
||||
z.object({
|
||||
id: z.string().uuid(),
|
||||
username: z.string(),
|
||||
acct: z.string(),
|
||||
url: z.string().url(),
|
||||
}),
|
||||
),
|
||||
tags: z.array(z.object({ name: z.string(), url: z.string().url() })),
|
||||
card: z
|
||||
.object({
|
||||
url: z.string().url(),
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
type: z.enum(["link", "photo", "video", "rich"]),
|
||||
image: z.string().url().nullable(),
|
||||
author_name: z.string().nullable(),
|
||||
author_url: z.string().url().nullable(),
|
||||
provider_name: z.string().nullable(),
|
||||
provider_url: z.string().url().nullable(),
|
||||
html: z.string().nullable(),
|
||||
width: z.number().int().nonnegative().nullable(),
|
||||
height: z.number().int().nonnegative().nullable(),
|
||||
embed_url: z.string().url().nullable(),
|
||||
blurhash: z.string().nullable(),
|
||||
})
|
||||
.nullable(),
|
||||
poll: z
|
||||
.object({
|
||||
id: z.string().uuid(),
|
||||
expires_at: z.string(),
|
||||
expired: z.boolean(),
|
||||
multiple: z.boolean(),
|
||||
votes_count: z.number().int().nonnegative(),
|
||||
voted: z.boolean(),
|
||||
options: z.array(
|
||||
z.object({
|
||||
title: z.string(),
|
||||
votes_count: z.number().int().nonnegative().nullable(),
|
||||
}),
|
||||
),
|
||||
})
|
||||
.nullable(),
|
||||
application: z
|
||||
.object({
|
||||
name: z.string(),
|
||||
website: z.string().url().nullable().optional(),
|
||||
vapid_key: z.string().nullable().optional(),
|
||||
})
|
||||
.nullable(),
|
||||
language: z.string().nullable(),
|
||||
pinned: z.boolean().nullable(),
|
||||
emoji_reactions: z.array(
|
||||
z.object({
|
||||
count: z.number().int().nonnegative(),
|
||||
me: z.boolean(),
|
||||
name: z.string(),
|
||||
url: z.string().url().optional(),
|
||||
static_url: z.string().url().optional(),
|
||||
accounts: z.array(z.lazy(() => User.schema)).optional(),
|
||||
account_ids: z.array(z.string().uuid()).optional(),
|
||||
}),
|
||||
),
|
||||
quote: z.lazy(() => Note.schema).nullable(),
|
||||
bookmarked: z.boolean(),
|
||||
});
|
||||
|
||||
save(): Promise<StatusWithRelations> {
|
||||
return this.update(this.data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ import { Role } from "./role";
|
|||
* Gives helpers to fetch users from database in a nice format
|
||||
*/
|
||||
export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
||||
static schema = z.object({
|
||||
static schema: z.ZodType<ApiAccount> = z.object({
|
||||
id: z.string(),
|
||||
username: z.string(),
|
||||
acct: z.string(),
|
||||
|
|
@ -92,12 +92,12 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
z.object({
|
||||
name: z.string(),
|
||||
value: z.string(),
|
||||
verified: z.boolean().nullable().optional(),
|
||||
verified: z.boolean().optional(),
|
||||
verified_at: z.string().nullable().optional(),
|
||||
}),
|
||||
),
|
||||
// FIXME: Use a proper type
|
||||
moved: z.any().nullable(),
|
||||
moved: z.lazy(() => User.schema).nullable(),
|
||||
bot: z.boolean().nullable(),
|
||||
source: z
|
||||
.object({
|
||||
|
|
@ -105,6 +105,12 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
sensitive: z.boolean().nullable(),
|
||||
language: z.string().nullable(),
|
||||
note: z.string(),
|
||||
fields: z.array(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
value: z.string(),
|
||||
}),
|
||||
),
|
||||
})
|
||||
.optional(),
|
||||
role: z
|
||||
|
|
|
|||
Loading…
Reference in a new issue