Merge branch 'dev' of ssh://meowgit.nekoea.red:22222/nihonium/nyanimedb into dev
All checks were successful
Build and Deploy Go App / build (push) Successful in 9m41s
Build and Deploy Go App / deploy (push) Successful in 1m8s

This commit is contained in:
Iron_Felix 2025-12-06 09:30:23 +03:00
commit 53011b67ae
7 changed files with 72 additions and 9 deletions

View file

@ -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 ./

View file

@ -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"]

View file

@ -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;

View file

@ -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<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = Options2<TData, ThrowOnError> & {
/**
@ -113,3 +113,18 @@ export const updateUserTitle = <ThrowOnError extends boolean = false>(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 = <ThrowOnError extends boolean = false>(options: Options<PostMediaUploadData, ThrowOnError>) => (options.client ?? client).post<PostMediaUploadResponses, PostMediaUploadErrors, ThrowOnError>({
url: '/media/upload',
...options,
headers: {
'Content-Type': 'encoding',
...options.headers
}
});

View file

@ -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];

View file

@ -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).

View file

@ -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
);