Feat: メッセージの送受信 / New: ユーザーのiconプロパティ / New: logエンティティ・リポジトリ / Chg: コミュニティリポジトリのスキーマのiconをoptionalに / Del: 不要なimport / Fix: Vue起動前のindex.htmlの背景色をVueと同期 / Enhance: Service Workerを改善 / Fix: 最初に開いたページが動作しない問題 / Feat: 上部の通知モーダル / Feat: 閉じることができないエラーのモーダルに再読み込みボタンを追加 / Fix: はみ出す挙動などのCSSを修正

This commit is contained in:
2026-05-31 13:54:55 +09:00
parent beb0e25ad9
commit cbf18aec8f
37 changed files with 1174 additions and 83 deletions
@@ -1,7 +1,6 @@
import { DatabaseError, InputError } from "@/errors";
import Logger from "@/lib/logger";
import { CommunityEntity } from "@/modules/entities/Community";
import { UserEntity } from "@/modules/entities/User";
import type { FastifyInstance } from "fastify";
import z from "zod/v3";
+5
View File
@@ -5,6 +5,7 @@ import Me from "./me";
import ServerInfo from "./server-info";
import Community from "./community";
import Channel from "./channel";
import Message from "./message";
export default async function Routes(fastify: FastifyInstance) {
await fastify.register(Setup, {
@@ -30,4 +31,8 @@ export default async function Routes(fastify: FastifyInstance) {
await fastify.register(Channel, {
prefix: "/channel",
});
await fastify.register(Message, {
prefix: "/message",
});
}
@@ -0,0 +1,37 @@
import { DatabaseError, InputError } from "@/errors";
import Logger from "@/lib/logger";
import { MessageEntity } from "@/modules/entities/Message";
import type { FastifyInstance } from "fastify";
import z from "zod/v3";
export default async function MessageDelete(fastify: FastifyInstance) {
const logger = new Logger("Endpoint | message/delete");
fastify.post("/", async (req, res) => {
res.header("Content-Type", "application/json");
if ("error" in req.token)
return res.code(400).send(req.token);
const result = z.object({
id: z.string().length(10),
}).safeParse(req.body);
if (!result.success) {
return res.code(400).send(InputError(result.error.issues));
}
try {
const messageRepo = fastify.orm.em.getRepository(MessageEntity);
await messageRepo.deleteMessage(result.data.id);
return res.send({
success: true,
});
} catch (err) {
logger.error("Database Error:", err);
return res.code(500).send(DatabaseError());
}
});
}
@@ -0,0 +1,18 @@
import type { FastifyInstance } from "fastify";
import MessageList from "./list";
import MessageSend from "./send";
import MessageDelete from "./delete";
export default async function Message(fastify: FastifyInstance) {
await fastify.register(MessageList, {
prefix: "/list",
});
await fastify.register(MessageSend, {
prefix: "/send",
});
await fastify.register(MessageDelete, {
prefix: "/delete",
});
}
@@ -0,0 +1,55 @@
import { DatabaseError, InputError } from "@/errors";
import Logger from "@/lib/logger";
import { Pick } from "@/lib/object";
import { MessageEntity } from "@/modules/entities/Message";
import type { FastifyInstance } from "fastify";
import z from "zod/v3";
export default async function MessageList(fastify: FastifyInstance) {
const logger = new Logger("Endpoint | message/list");
fastify.post("/", async (req, res) => {
res.header("Content-Type", "application/json");
if ("error" in req.token)
return res.code(400).send(req.token);
const bodySchema = z.object({
limit: z.number().optional(),
until: z.string().optional(),
channel: z.string().length(10),
});
const result = bodySchema.safeParse(req.body);
if (!result.success) {
return res.code(400).send(InputError(result.error.issues));
}
try {
const messageRepo = fastify.orm.em.getRepository(MessageEntity);
const findResult = await messageRepo.listMessage(
result.data.channel,
result.data.limit,
result.data.until,
);
if ("error" in findResult) {
return res.code(400).send(findResult);
}
return res.send({
success: true,
messages: findResult.map(message => ({
...message,
createdBy: Pick(message.createdBy, ["id", "userid", "username", "icon"]),
})),
});
} catch (err) {
logger.error("Database Error:", err);
return res.code(500).send(DatabaseError());
}
});
}
@@ -0,0 +1,39 @@
import { DatabaseError, InputError } from "@/errors";
import Logger from "@/lib/logger";
import { MessageEntity } from "@/modules/entities/Message";
import { MessageRepository } from "@/modules/repositories/Message";
import type { FastifyInstance } from "fastify";
export default async function MessageSend(fastify: FastifyInstance) {
const logger = new Logger("Endpoint | message/send");
fastify.post("/", async (req, res) => {
res.header("Content-Type", "application/json");
res.header("Connection", "close");
if ("error" in req.token)
return res.code(400).send(req.token);
const result = MessageRepository.schema
.omit({ userid: true })
.safeParse(req.body);
if (!result.success) {
return res.code(400).send(InputError(result.error.issues));
}
try {
const messageRepo = fastify.orm.em.getRepository(MessageEntity);
const id = await messageRepo.sendMessage(result.data.message, result.data.channel, req.token.user.id);
return res.send({
success: true,
id,
});
} catch (err) {
logger.error("Database Error:", err);
return res.code(500).send(DatabaseError());
}
});
}