Skip to content

Commit a636d6b

Browse files
authored
Merge branch 'main' into add-interests-api
2 parents 708ba5b + 23a2b70 commit a636d6b

File tree

38 files changed

+618
-205
lines changed

38 files changed

+618
-205
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ jobs:
8686
- uses: actions/setup-node@v3
8787
- uses: oven-sh/setup-bun@v2
8888
- run: make prepare-deploy-web
89-
- run: test `ls web/out | wc -l` != 0
89+
- run: test `ls web/.next | wc -l` != 0
9090

9191
deploy-test-server:
9292
name: Deploy Test (server)

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ setup-ci:
1616
make generate-sql
1717

1818
sync: sync-server sync-web sync-root sync-common
19-
lefthook install || true
19+
bunx lefthook install || true
2020
@echo '----------------------------------------------------------------------------------------------------------'
2121
@echo '| Most work is done. now running prisma-generate-sql (which might fail if .env.dev is not set configured)|'
2222
@echo '----------------------------------------------------------------------------------------------------------'

common/zod/schemas.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,15 @@ export const SendMessageSchema = z.object({
133133
content: z.string().min(1, { message: "Content must not be empty." }),
134134
});
135135

136+
export const MatchingStatusSchema = z.union([
137+
z.literal("myRequest"),
138+
z.literal("otherRequest"),
139+
z.literal("matched"),
140+
]);
141+
136142
export const DMOverviewSchema = z.object({
137143
isDM: z.literal(true),
144+
matchingStatus: MatchingStatusSchema,
138145
friendId: UserIDSchema,
139146
name: NameSchema,
140147
thumbnail: z.string(),
@@ -163,6 +170,7 @@ export const DMRoomSchema = z.object({
163170
export const PersonalizedDMRoomSchema = z.object({
164171
name: NameSchema,
165172
thumbnail: z.string(),
173+
matchingStatus: MatchingStatusSchema,
166174
});
167175

168176
export const SharedRoomSchema = z.object({

flake.nix

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,11 @@
2727
biome
2828
pkg-config
2929
openssl
30-
lefthook
3130
] ++ [
3231
rust-pkgs
3332
];
3433
shellHook = ''
3534
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.stdenv.cc.cc.lib}/lib
36-
lefthook install
3735
'' + prisma.shellHook;
3836
};
3937
});

server/src/database/chat.ts

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,35 @@ import type {
1414
} from "common/types";
1515
import { prisma } from "./client";
1616
import { getRelation } from "./matches";
17-
import { getMatchedUser } from "./requests";
17+
import {
18+
getMatchedUser,
19+
getPendingRequestsFromUser,
20+
getPendingRequestsToUser,
21+
} from "./requests";
1822

19-
// ユーザーの参加しているすべての Room の概要 (Overview) の取得
2023
export async function getOverview(
2124
user: UserID,
2225
): Promise<Result<RoomOverview[]>> {
2326
try {
2427
const matched = await getMatchedUser(user);
2528
if (!matched.ok) return Err(matched.error);
2629

27-
const dm = await Promise.all(
30+
const senders = await getPendingRequestsToUser(user);
31+
if (!senders.ok) return Err(senders.error);
32+
33+
const receivers = await getPendingRequestsFromUser(user);
34+
if (!receivers.ok) return Err(receivers.error);
35+
36+
//マッチングしている人のオーバービュー
37+
const matchingOverview = await Promise.all(
2838
matched.value.map(async (friend) => {
2939
const lastMessageResult = await getLastMessage(user, friend.id);
3040
const lastMessage = lastMessageResult.ok
3141
? lastMessageResult.value
3242
: undefined;
3343
const overview: DMOverview = {
3444
isDM: true,
45+
matchingStatus: "matched",
3546
friendId: friend.id,
3647
name: friend.name,
3748
thumbnail: friend.pictureUrl,
@@ -41,6 +52,44 @@ export async function getOverview(
4152
}),
4253
);
4354

55+
//自分にリクエストを送ってきた人のオーバービュー
56+
const senderOverview = await Promise.all(
57+
senders.value.map(async (sender) => {
58+
const lastMessageResult = await getLastMessage(user, sender.id);
59+
const lastMessage = lastMessageResult.ok
60+
? lastMessageResult.value
61+
: undefined;
62+
const overview: DMOverview = {
63+
isDM: true,
64+
matchingStatus: "otherRequest",
65+
friendId: sender.id,
66+
name: sender.name,
67+
thumbnail: sender.pictureUrl,
68+
lastMsg: lastMessage,
69+
};
70+
return overview;
71+
}),
72+
);
73+
74+
//自分がリクエストを送った人のオーバービュー
75+
const receiverOverview = await Promise.all(
76+
receivers.value.map(async (receiver) => {
77+
const lastMessageResult = await getLastMessage(user, receiver.id);
78+
const lastMessage = lastMessageResult.ok
79+
? lastMessageResult.value
80+
: undefined;
81+
const overview: DMOverview = {
82+
isDM: true,
83+
matchingStatus: "myRequest",
84+
friendId: receiver.id,
85+
name: receiver.name,
86+
thumbnail: receiver.pictureUrl,
87+
lastMsg: lastMessage,
88+
};
89+
return overview;
90+
}),
91+
);
92+
4493
const sharedRooms: {
4594
id: number;
4695
name: string;
@@ -61,7 +110,21 @@ export async function getOverview(
61110
};
62111
return overview;
63112
});
64-
return Ok([...shared, ...dm]);
113+
114+
const overview = [
115+
...matchingOverview,
116+
...senderOverview,
117+
...receiverOverview,
118+
...shared,
119+
];
120+
121+
const sortedOverviewByTime = overview.sort((a, b) => {
122+
const dateA = a.lastMsg?.createdAt ? a.lastMsg.createdAt.getTime() : 0;
123+
const dateB = b.lastMsg?.createdAt ? b.lastMsg.createdAt.getTime() : 0;
124+
return dateB - dateA;
125+
});
126+
127+
return Ok([...sortedOverviewByTime]);
65128
} catch (e) {
66129
return Err(e);
67130
}

server/src/database/requests.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,3 +276,19 @@ export async function getMatchedUser(
276276
return Err(e);
277277
}
278278
}
279+
280+
export async function matchWithMemo(userId: UserID) {
281+
try {
282+
const result = await prisma.relationship.create({
283+
data: {
284+
status: "MATCHED",
285+
sendingUserId: userId,
286+
receivingUserId: 0, //KeepメモのUserId
287+
},
288+
});
289+
290+
return result;
291+
} catch (error) {
292+
return Err(error);
293+
}
294+
}

server/src/functions/chat.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@ export async function sendDM(
4242
send: SendMessage,
4343
): Promise<http.Response<Message>> {
4444
const rel = await getRelation(from, to);
45-
if (!rel.ok || rel.value.status !== "MATCHED")
46-
return http.forbidden("cannot send to non-friend");
45+
if (!rel.ok || rel.value.status === "REJECTED")
46+
return http.forbidden(
47+
"You cannot send a message because the friendship request was rejected.",
48+
);
4749

4850
// they are now MATCHED
4951
const msg: Omit<Message, "id"> = {
@@ -59,21 +61,28 @@ export async function sendDM(
5961
}
6062

6163
export async function getDM(
62-
requester: UserID,
63-
_with: UserID,
64+
user: UserID,
65+
friend: UserID,
6466
): Promise<http.Response<PersonalizedDMRoom & DMRoom>> {
65-
if (!areMatched(requester, _with))
66-
return http.forbidden("cannot DM with a non-friend");
67+
const rel = await getRelation(user, friend);
68+
if (!rel.ok || rel.value.status === "REJECTED")
69+
return http.forbidden("cannot send to rejected-friend");
6770

68-
const room = await db.getDMbetween(requester, _with);
71+
const room = await db.getDMbetween(user, friend);
6972
if (!room.ok) return http.internalError();
7073

71-
const friendData = await getUserByID(_with);
74+
const friendData = await getUserByID(friend);
7275
if (!friendData.ok) return http.notFound("friend not found");
7376

7477
const personalized: PersonalizedDMRoom & DMRoom = {
7578
name: friendData.value.name,
7679
thumbnail: friendData.value.pictureUrl,
80+
matchingStatus:
81+
rel.value.status === "MATCHED"
82+
? "matched"
83+
: rel.value.sendingUserId === user //どっちが送ったリクエストなのかを判定
84+
? "myRequest"
85+
: "otherRequest",
7786
...room.value,
7887
};
7988

server/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const app = express();
1717
// https://expressjs.com/ja/api.html#app.settings.table の query parser を参照。
1818
app.set("query parser", "simple");
1919

20-
const port = 3000;
20+
const port = process.env.PORT || 3000;
2121
const allowedOrigins = (
2222
process.env.CORS_ALLOW_ORIGINS || panic("env CORS_ALLOW_ORIGINS is missing")
2323
)

server/src/router/chat.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ router.get("/overview", async (req, res) => {
2323
res.status(result.code).send(result.body);
2424
});
2525

26-
// send DM to userid.
26+
// send DM to userId.
2727
router.post("/dm/to/:userid", async (req, res) => {
2828
const user = await safeGetUserId(req);
2929
if (!user.ok) return res.status(401).send("auth error");
3030
const friend = safeParseInt(req.params.userid);
31-
if (!friend.ok) return res.status(400).send("bad param encoding: `userid`");
31+
if (!friend.ok) return res.status(400).send("bad param encoding: `userId`");
3232

3333
const send = SendMessageSchema.safeParse(req.body);
3434
if (!send.success) {
@@ -42,14 +42,14 @@ router.post("/dm/to/:userid", async (req, res) => {
4242
res.status(result.code).send(result.body);
4343
});
4444

45-
// GET a DM Room with userid, CREATE one if not found.
45+
// GET a DM Room with userId, CREATE one if not found.
4646
router.get("/dm/with/:userid", async (req, res) => {
4747
const user = await safeGetUserId(req);
4848
if (!user.ok) return res.status(401).send("auth error");
4949

5050
const friend = safeParseInt(req.params.userid);
5151
if (!friend.ok)
52-
return res.status(400).send("invalid param `userid` formatting");
52+
return res.status(400).send("invalid param `userId` formatting");
5353

5454
const result = await core.getDM(user.value, friend.value);
5555

server/src/router/users.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import express, { type Request, type Response } from "express";
1313
import {
1414
getPendingRequestsFromUser,
1515
getPendingRequestsToUser,
16+
matchWithMemo,
1617
} from "../database/requests";
1718
import {
1819
createUser,
@@ -128,10 +129,20 @@ router.get("/id/:id", async (req: Request, res: Response) => {
128129
// INSERT INTO "User" VALUES (body...)
129130
router.post("/", async (req: Request, res: Response) => {
130131
const partialUser = InitUserSchema.safeParse(req.body);
131-
if (!partialUser.success) return res.status(400).send("invalid format");
132+
if (!partialUser.success)
133+
return res.status(400).send({
134+
error: "Invalid input format",
135+
details: partialUser.error.errors,
136+
});
132137

133138
const user = await createUser(partialUser.data);
134-
if (!user.ok) return res.status(500).send();
139+
if (!user.ok) return res.status(500).send({ error: "Failed to create user" });
140+
141+
//ユーザー作成と同時にメモとマッチング
142+
const result = await matchWithMemo(user.value.id);
143+
if ("ok" in result && !result.ok) {
144+
return res.status(500).send({ error: "Failed to match user with memo" });
145+
}
135146
res.status(201).json(user.value);
136147
});
137148

0 commit comments

Comments
 (0)