From 1b6c536b773b202af6d11bd53284bf64ce2e387a Mon Sep 17 00:00:00 2001 From: nihonium Date: Sat, 6 Dec 2025 07:49:26 +0300 Subject: [PATCH 1/4] fix: usertitle ftime logic --- modules/frontend/src/api/sdk.gen.ts | 17 +++++++++++- modules/frontend/src/api/types.gen.ts | 37 +++++++++++++++++++++++++++ sql/migrations/000001_init.up.sql | 3 ++- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/modules/frontend/src/api/sdk.gen.ts b/modules/frontend/src/api/sdk.gen.ts index 7d46120..24153db 100644 --- a/modules/frontend/src/api/sdk.gen.ts +++ b/modules/frontend/src/api/sdk.gen.ts @@ -2,7 +2,7 @@ import type { Client, Options as Options2, TDataShape } from './client'; import { client } from './client.gen'; -import type { AddUserTitleData, AddUserTitleErrors, AddUserTitleResponses, DeleteUserTitleData, DeleteUserTitleErrors, DeleteUserTitleResponses, GetTitleData, GetTitleErrors, GetTitleResponses, GetTitlesData, GetTitlesErrors, GetTitlesResponses, GetUsersData, GetUsersErrors, GetUsersIdData, GetUsersIdErrors, GetUsersIdResponses, GetUsersResponses, GetUserTitleData, GetUserTitleErrors, GetUserTitleResponses, GetUserTitlesData, GetUserTitlesErrors, GetUserTitlesResponses, UpdateUserData, UpdateUserErrors, UpdateUserResponses, UpdateUserTitleData, UpdateUserTitleErrors, UpdateUserTitleResponses } from './types.gen'; +import type { AddUserTitleData, AddUserTitleErrors, AddUserTitleResponses, DeleteUserTitleData, DeleteUserTitleErrors, DeleteUserTitleResponses, GetTitleData, GetTitleErrors, GetTitleResponses, GetTitlesData, GetTitlesErrors, GetTitlesResponses, GetUsersData, GetUsersErrors, GetUsersIdData, GetUsersIdErrors, GetUsersIdResponses, GetUsersResponses, GetUserTitleData, GetUserTitleErrors, GetUserTitleResponses, GetUserTitlesData, GetUserTitlesErrors, GetUserTitlesResponses, PostMediaUploadData, PostMediaUploadErrors, PostMediaUploadResponses, UpdateUserData, UpdateUserErrors, UpdateUserResponses, UpdateUserTitleData, UpdateUserTitleErrors, UpdateUserTitleResponses } from './types.gen'; export type Options = Options2 & { /** @@ -113,3 +113,18 @@ export const updateUserTitle = (options: O ...options.headers } }); + +/** + * Upload an image (PNG, JPEG, or WebP) + * + * Uploads a single image file. Supported formats: **PNG**, **JPEG/JPG**, **WebP**. + * + */ +export const postMediaUpload = (options: Options) => (options.client ?? client).post({ + url: '/media/upload', + ...options, + headers: { + 'Content-Type': 'encoding', + ...options.headers + } +}); diff --git a/modules/frontend/src/api/types.gen.ts b/modules/frontend/src/api/types.gen.ts index d4526a7..d0ca425 100644 --- a/modules/frontend/src/api/types.gen.ts +++ b/modules/frontend/src/api/types.gen.ts @@ -453,6 +453,7 @@ export type AddUserTitleData = { title_id: number; status: UserTitleStatus; rate?: number; + ftime?: string; }; path: { /** @@ -578,6 +579,7 @@ export type UpdateUserTitleData = { body: { status?: UserTitleStatus; rate?: number; + ftime?: string; }; path: { user_id: number; @@ -618,3 +620,38 @@ export type UpdateUserTitleResponses = { }; export type UpdateUserTitleResponse = UpdateUserTitleResponses[keyof UpdateUserTitleResponses]; + +export type PostMediaUploadData = { + body: unknown; + path?: never; + query?: never; + url: '/media/upload'; +}; + +export type PostMediaUploadErrors = { + /** + * Bad request — e.g., invalid/malformed image, empty file + */ + 400: string; + /** + * Unsupported Media Type — e.g., request `Content-Type` is not `multipart/form-data`, + * or the `image` part has an unsupported `Content-Type` (not image/png, image/jpeg, or image/webp) + * + */ + 415: unknown; + /** + * Internal server error + */ + 500: unknown; +}; + +export type PostMediaUploadError = PostMediaUploadErrors[keyof PostMediaUploadErrors]; + +export type PostMediaUploadResponses = { + /** + * Image uploaded successfully + */ + 200: Image; +}; + +export type PostMediaUploadResponse = PostMediaUploadResponses[keyof PostMediaUploadResponses]; diff --git a/sql/migrations/000001_init.up.sql b/sql/migrations/000001_init.up.sql index 369e455..415b9af 100644 --- a/sql/migrations/000001_init.up.sql +++ b/sql/migrations/000001_init.up.sql @@ -86,7 +86,8 @@ CREATE TABLE usertitles ( status usertitle_status_t NOT NULL, rate int CHECK (rate > 0 AND rate <= 10), review_id bigint REFERENCES reviews (id) ON DELETE SET NULL, - ctime timestamptz NOT NULL DEFAULT now() + ctime timestamptz NOT NULL DEFAULT now(), + ftime timestamptz NOT NULL DEFAULT now() -- // TODO: series status ); From fe1bf7ec1070bcbedac6fe64971b51832341e5e5 Mon Sep 17 00:00:00 2001 From: nihonium Date: Sat, 6 Dec 2025 08:38:34 +0300 Subject: [PATCH 2/4] fix(etl): sql enum for image storage --- modules/anime_etl/db/repository.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/anime_etl/db/repository.py b/modules/anime_etl/db/repository.py index 4c5caee..7c09329 100644 --- a/modules/anime_etl/db/repository.py +++ b/modules/anime_etl/db/repository.py @@ -80,7 +80,7 @@ async def get_or_create_image( VALUES (%s, %s) RETURNING id """, - ("image-service", rel_path), + ("local", rel_path), ) row = await cur.fetchone() return row["id"] From eef3696e5ee6bbd4e97dd50f7a0bbf1e5582a4f7 Mon Sep 17 00:00:00 2001 From: nihonium Date: Sat, 6 Dec 2025 09:17:06 +0300 Subject: [PATCH 3/4] fix(cicd): refact etl dockerfile --- Dockerfiles/Dockerfile_etl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Dockerfiles/Dockerfile_etl b/Dockerfiles/Dockerfile_etl index ddb0bb3..c721b51 100644 --- a/Dockerfiles/Dockerfile_etl +++ b/Dockerfiles/Dockerfile_etl @@ -2,11 +2,11 @@ FROM python:3.12-slim WORKDIR /app/modules/anime_etl -RUN apt-get update && apt-get install -y --no-install-recommends \ - build-essential \ - libpq-dev \ - ca-certificates \ - && rm -rf /var/lib/apt/lists/* +# RUN apt-get update && apt-get install -y --no-install-recommends \ +# build-essential \ +# libpq-dev \ +# ca-certificates \ +# && rm -rf /var/lib/apt/lists/* COPY modules/anime_etl/pyproject.toml modules/anime_etl/uv.lock ./ From 7787eb328f0590cdd102e6458e1b84c0ca06e2ab Mon Sep 17 00:00:00 2001 From: nihonium Date: Sat, 6 Dec 2025 09:17:45 +0300 Subject: [PATCH 4/4] feat: media routing --- modules/frontend/nginx-default.conf | 10 ++++++++++ modules/image_storage/app/main.py | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/modules/frontend/nginx-default.conf b/modules/frontend/nginx-default.conf index c3a851f..6075999 100644 --- a/modules/frontend/nginx-default.conf +++ b/modules/frontend/nginx-default.conf @@ -28,6 +28,16 @@ server { proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } + + location /media/ { + rewrite ^/media/(.*)$ /$1 break; + proxy_pass http://nyanimedb-images:8000/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } #error_page 404 /404.html; error_page 500 502 503 504 /50x.html; diff --git a/modules/image_storage/app/main.py b/modules/image_storage/app/main.py index ff59d36..2c915c3 100644 --- a/modules/image_storage/app/main.py +++ b/modules/image_storage/app/main.py @@ -99,7 +99,7 @@ async def download_by_url(payload: DownloadByUrlRequest): return {"path": rel} -@app.get("/media/{path:path}") +@app.get("/{path:path}") async def get_image(path: str): """ Отдаёт файл по относительному пути (например, posters/ab/cd/hash.jpg).