From aec1be61792be458f7cba4c7170f3948fb3fa144 Mon Sep 17 00:00:00 2001 From: Vadim Date: Sun, 22 Mar 2026 22:40:26 +0300 Subject: [PATCH] wip --- .gitignore | 1 + src/config.ts | 2 +- src/handles.ts | 16 ++++++++++++++++ src/index.ts | 22 +++++++++++++++++++--- src/s3-client/index.ts | 11 ----------- src/storage/index.ts | 30 ++++++++++++++++++++++++++++++ src/types/types.ts | 6 +++++- 7 files changed, 72 insertions(+), 16 deletions(-) delete mode 100644 src/s3-client/index.ts create mode 100644 src/storage/index.ts diff --git a/.gitignore b/.gitignore index 3d3bfb4..b5db3b5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules/ dist/ .idea/ .env +secrets.json \ No newline at end of file diff --git a/src/config.ts b/src/config.ts index c8c630a..dde2de7 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,4 +1,4 @@ -const EXPIRE = 30 * 60 // 30min +const EXPIRE = 300 * 60 // 300min export const config = { accessSecret: process.env.JWT_SECRET ?? 'JWTAccessSecret', diff --git a/src/handles.ts b/src/handles.ts index fd1b9ce..be538e8 100644 --- a/src/handles.ts +++ b/src/handles.ts @@ -4,6 +4,8 @@ import type { LoginDto, WebSocketCtx, WebSocketData } from './types/types.ts' import { createAccessToken, verifyAccessToken } from './utils/jwt.ts' import { config } from './config.ts' import { messageService } from './grpc/message.ts' +import { storage } from './storage' +import { randomUUIDv7 } from 'bun' export const handlers = { async getVersion(req: Request) { @@ -44,6 +46,20 @@ export const handlers = { return Response.json({ message: 'Login failed' }, { status: HttpStatusCodes.BAD_REQUEST }) } }, + async setAvatar(req: Request) { + const formdata = await req.formData() + const file = formdata.get('file') as File + if (!file) { + return Response.json({ message: 'Invalid image' }, { status: HttpStatusCodes.BAD_REQUEST }) + } + const uuid = randomUUIDv7() + await storage.upload(file,`${uuid}.${file.type.split('/')[1]}`) + }, + async getAvatar(req: Request) { + const url = storage.presign('avatar.jpg') + + return Response.json({ url }) + } } export async function upgrade(req: Request, server: Bun.Server) { diff --git a/src/index.ts b/src/index.ts index 3bf7568..54262a6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,6 +15,8 @@ const server = Bun.serve({ const method = req.method if (pathname === '/api/version' && method === 'GET') return handlers.getVersion(req) + if (pathname === '/api/avatar' && method === 'POST') return handlers.setAvatar(req) + if (pathname === '/api/avatar' && method === 'GET') return handlers.getAvatar(req) if (pathname === '/api/login' && method === 'POST') return handlers.login(req) if (pathname === '/ws') return upgrade(req, server) @@ -55,16 +57,30 @@ const server = Bun.serve({ const webSocketData = JSON.parse(message) as WebSocketData if (!webSocketData) return + if(webSocketData.type === 'GET_CHATS') { + const chatResponse = await messageService.listChat({ page: 0, userId: ws.data.userId }) + chatResponse.data.forEach((el) => ws.subscribe(el.id)) + ws.send(JSON.stringify({ type: 'CHATS', ...chatResponse })) + } + if (webSocketData.type === 'CREATE_CHAT') { - const chat = await messageService.createChat({ users: [{ userId: webSocketData.data.userId }, { userId: ws.data.userId }] }) - ws.send(JSON.stringify({ type: 'CHATS', ...chat })) + const chat = await messageService.createChat({ + users: [ + { userId: webSocketData.data.userId }, + { userId: ws.data.userId } + ] }) + if (chat?.data) { + ws.subscribe(chat.data.id) + ws.send(JSON.stringify({ type: 'CHATS', ...chat })) + } + } if (webSocketData.type === 'CREATE_MESSAGE') { const messageResponse = await messageService.createMessage({ chatId: webSocketData.data.chatId, - userId: ws.data.userId, message: webSocketData.data.message, + userId: ws.data.userId, }) server.publish(webSocketData.data.chatId, JSON.stringify({ type: 'MESSAGE', ...messageResponse })) } diff --git a/src/s3-client/index.ts b/src/s3-client/index.ts deleted file mode 100644 index 4424fce..0000000 --- a/src/s3-client/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { S3Client } from "@aws-sdk/client-s3"; - - -const rustfs_client = new S3Client({ - region: "cn-east-1", - credentials: { - accessKeyId: process.env.RUSTFS_ACCESS_KEY_ID!, - secretAccessKey: process.env.RUSTFS_SECRET_ACCESS_KEY!, - }, - endpoint: process.env.RUSTFS_ENDPOINT_URL!, -}); \ No newline at end of file diff --git a/src/storage/index.ts b/src/storage/index.ts new file mode 100644 index 0000000..6c0fe1a --- /dev/null +++ b/src/storage/index.ts @@ -0,0 +1,30 @@ +// import { ListBucketsCommand, PutObjectCommand, S3Client } from '@aws-sdk/client-s3' +import { S3Client, type S3File } from 'bun' + +class Storage { + client: S3Client + + constructor() { + this.client = new S3Client({ + region: 'cn-east-1', + accessKeyId: process.env.RUSTFS_ACCESS_KEY_ID!, + secretAccessKey: process.env.RUSTFS_SECRET_ACCESS_KEY!, + bucket: 'stor1', + endpoint: process.env.RUSTFS_ENDPOINT_URL!, + }) + } + + async upload(file: Blob, name: string): Promise { + const s3File: S3File = this.client.file(name) + const result = await s3File.write(file) + console.log({result}) + } + + presign(name: string) { + const s3File = this.client.file(name) + + return s3File.presign({method: 'GET'}) + } +} + +export const storage = new Storage() diff --git a/src/types/types.ts b/src/types/types.ts index 5b9491c..8062b7b 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -25,6 +25,10 @@ interface ListMessages { } } +interface ListChats { + type: 'GET_CHATS' +} + interface CreateMessage { type: 'CREATE_MESSAGE' data: { @@ -48,4 +52,4 @@ interface CreateChat { } } -export type WebSocketData = ListMessages | CreateMessage | ListUsers | CreateChat +export type WebSocketData = ListMessages | CreateMessage | ListUsers | CreateChat | ListChats