Small fixes

This commit is contained in:
2024-05-10 16:44:46 +04:00
parent a45c2dfee2
commit fd5b19e6a9
12 changed files with 94 additions and 61 deletions

View File

@@ -6,6 +6,7 @@ import database
cli = typer.Typer() cli = typer.Typer()
@cli.command(name="create") @cli.command(name="create")
def create_database(): aiorun(database.create_all()) def create_database(): aiorun(database.create_all())
@cli.command(name="drop") @cli.command(name="drop")

View File

@@ -1,4 +1,7 @@
from .crud import * from .crud import *
from .schemas import * from .schemas import *
from .database import get_session, drop_all, create_all, recreate_all from .database import get_session as get_session, \
drop_all as drop_all, \
create_all as create_all, \
recreate_all as recreate_all
from .crud import * from .crud import *

View File

@@ -5,14 +5,17 @@ from .. import models as mdl
from .. import schemas as sch from .. import schemas as sch
from ..database import add_transaction from ..database import add_transaction
async def add_game(db: AsyncSession, async def add_game(db: AsyncSession,
game_info: sch.GameCreate, game_info: sch.GameCreate,
user_id: int): user_id: int):
game = mdl.Game(**game_info.model_dump(), owner_id=user_id) game = mdl.Game(**game_info.model_dump(), owner_id=user_id)
return await add_transaction(db, game) return await add_transaction(db, game)
async def get_games(db: AsyncSession): async def get_games(db: AsyncSession):
return (await db.execute(select(mdl.Game))).scalars().all() return (await db.execute(select(mdl.Game))).scalars().all()
async def get_game(db: AsyncSession, game_id: int): async def get_game(db: AsyncSession, game_id: int):
return await db.get(mdl.Game, game_id) return await db.get(mdl.Game, game_id)

View File

@@ -1,7 +1,6 @@
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.asyncio import create_async_engine from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
DATABASE_URL = "sqlite+aiosqlite:///./dev_database.db" DATABASE_URL = "sqlite+aiosqlite:///./dev_database.db"
# DATABASE_URL = "postgresql://user:password@postgresserver/db" # DATABASE_URL = "postgresql://user:password@postgresserver/db"
@@ -9,27 +8,31 @@ DATABASE_URL = "sqlite+aiosqlite:///./dev_database.db"
engine = create_async_engine( engine = create_async_engine(
DATABASE_URL, connect_args={"check_same_thread": False}, echo=True DATABASE_URL, connect_args={"check_same_thread": False}, echo=True
) )
async_session = sessionmaker( async_session = sessionmaker( # type: ignore
engine, class_=AsyncSession, expire_on_commit=False) engine, class_=AsyncSession, expire_on_commit=False) # type: ignore
Base = declarative_base() Base = declarative_base()
async def get_session() -> AsyncSession: # type: ignore async def get_session() -> AsyncSession: # type: ignore
# Dependency
async with async_session() as session: # type: ignore async with async_session() as session: # type: ignore
yield session yield session
async def drop_all(): async def drop_all():
async with engine.begin() as conn: async with engine.begin() as conn:
await conn.run_sync(Base.metadata.drop_all) await conn.run_sync(Base.metadata.drop_all)
async def create_all(): async def create_all():
async with engine.begin() as conn: async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all) await conn.run_sync(Base.metadata.create_all)
async def recreate_all(): async def recreate_all():
await drop_all() await drop_all()
await create_all() await create_all()
async def add_transaction[T](db: AsyncSession, entity: T) -> T: async def add_transaction[T](db: AsyncSession, entity: T) -> T:
try: try:
db.add(entity) db.add(entity)

View File

@@ -7,36 +7,51 @@ import aiofiles
from fastapi import UploadFile from fastapi import UploadFile
from PIL import Image from PIL import Image
def create_hash_name(filename: str): def create_hash_name(filename: str):
return str(hashlib.sha1(filename.encode()).hexdigest()) return str(hashlib.sha1(filename.encode()).hexdigest())
async def save_torrent_file(torrent: UploadFile): async def save_torrent_file(torrent: UploadFile):
if(torrent.filename is None): raise ValueError("Filename not found")
hash_filename = create_hash_name(torrent.filename)+".torrent" hash_filename = create_hash_name(torrent.filename)+".torrent"
async with aiofiles.open(Path() / "content" / "torrent" async with aiofiles.open(Path() / "content" / "torrent"
/ hash_filename, 'wb') as file: / hash_filename, 'wb') as file:
await file.write(await torrent.read()) torrent_data = await torrent.read()
if (isinstance(torrent_data, str)):
raise ValueError("Invalid torrent file")
await file.write(torrent_data)
return hash_filename return hash_filename
async def save_image(cover: UploadFile, type: Literal["cover", "screenshot"]): async def save_image(cover: UploadFile, type: Literal["cover", "screenshot"]):
hash_filename = create_hash_name(cover.filename) \ if(cover.filename is None): raise ValueError("Filename not found")
+ mimetypes.guess_extension(cover.content_type) if(cover.content_type is None): raise ValueError("File content type unknown")
hash_filename = create_hash_name(cover.filename)
file_extension = mimetypes.guess_extension(cover.content_type)
if (file_extension is None): raise NameError("File extension not found")
else: hash_filename += file_extension
async with aiofiles.open(Path() / "content" / "images" / type / "full_size" async with aiofiles.open(Path() / "content" / "images" / type / "full_size"
/ hash_filename, 'wb') as full_size_file, \ / hash_filename, 'wb') as full_size_file, \
aiofiles.open(Path() / "content" / "images" / type / aiofiles.open(Path() / "content" / "images" / type /
"preview" / hash_filename, 'wb') as preview_file: "preview" / hash_filename, 'wb') as preview_file:
cover_data = await cover.read() cover_data = await cover.read()
if (isinstance(cover_data, str)):
raise ValueError("Invalid image file")
await full_size_file.write(cover_data) await full_size_file.write(cover_data)
image = Image.open(BytesIO(cover_data)) image = Image.open(BytesIO(cover_data))
compressed_coefficient = (image.size[0] * image.size[1]) / (1280*720/4) compressed_coefficient = (image.size[0] * image.size[1]) / (1280*720/4)
if(compressed_coefficient < 1): compressed_coefficient = 1 if (compressed_coefficient < 1):
compressed_coefficient = 1
compressed_image = image.resize( compressed_image = image.resize(
( int(image.size[0] / compressed_coefficient), (int(image.size[0] / compressed_coefficient),
int(image.size[1] / compressed_coefficient) ) int(image.size[1] / compressed_coefficient))
) )
buf = BytesIO() buf = BytesIO()
compressed_image.save(buf, format= compressed_image.save(
cover.content_type.upper().replace("IMAGE/", "")) buf, format=cover.content_type.upper().replace("IMAGE/", ""))
await preview_file.write(buf.getbuffer()) await preview_file.write(buf.getbuffer())
return hash_filename return hash_filename

View File

@@ -1,5 +1,4 @@
from fastapi import Depends, FastAPI, HTTPException from fastapi import FastAPI
from sqlalchemy.ext.asyncio import AsyncSession
import typer import typer
import cli_commands import cli_commands
@@ -13,4 +12,5 @@ app.include_router(files_router)
cli = typer.Typer() cli = typer.Typer()
cli.add_typer(cli_commands.cli, name="database") cli.add_typer(cli_commands.cli, name="database")
if(__name__ == "__main__"): cli() if (__name__ == "__main__"):
cli()

View File

@@ -4,3 +4,4 @@ SQLAlchemy==2.0.30
aiosqlite==0.20.0 aiosqlite==0.20.0
typer==0.12.3 typer==0.12.3
aiofiles==23.2.1 aiofiles==23.2.1
Pillow==10.3.0

View File

@@ -1,3 +1,3 @@
from .games import router as games_router from .games import games_router as games_router
from .files import router as files_router from .files import files_router as files_router
from .startup import router as startup_router from .startup import startup_router as startup_router

View File

@@ -1,20 +1,24 @@
from fastapi import APIRouter, Depends, HTTPException, UploadFile from fastapi import APIRouter, HTTPException, UploadFile
from database import * from database import *
from file_handler import * from file_handler import *
router = APIRouter(prefix="/files", tags=["Files"]) files_router = APIRouter(prefix="/files", tags=["Files"])
@router.post("/torrent", response_model=str)
@files_router.post("/torrent", response_model=str)
async def upload_torrent(torrent: UploadFile): async def upload_torrent(torrent: UploadFile):
try: return await save_torrent_file(torrent) try:
return await save_torrent_file(torrent)
except Exception as ex: except Exception as ex:
print(ex) print(ex)
raise HTTPException(500) raise HTTPException(500)
@router.post("/cover", response_model=str)
@files_router.post("/cover", response_model=str)
async def upload_cover(cover: UploadFile): async def upload_cover(cover: UploadFile):
try: return await save_image(cover, "cover") try:
return await save_image(cover, "cover")
except Exception as ex: except Exception as ex:
print(ex) print(ex)
raise HTTPException(500) raise HTTPException(500)

View File

@@ -1,27 +1,29 @@
from fastapi import APIRouter, Depends, HTTPException, UploadFile from fastapi import APIRouter, Depends, HTTPException
from database import * from database import *
from file_handler import * from file_handler import *
router = APIRouter(prefix="/games", tags=["Games"]) games_router = APIRouter(prefix="/games", tags=["Games"])
@router.get("/", response_model=list[Game])
@games_router.get("/", response_model=list[Game])
async def get_games(db: AsyncSession = Depends(get_session)): async def get_games(db: AsyncSession = Depends(get_session)):
try: return await crud.get_games(db) try:
except Exception as ex: raise HTTPException(500) return await crud.get_games(db)
except Exception:
raise HTTPException(500)
@router.get("/{game_id}", response_model=Game)
@games_router.get("/{game_id}", response_model=Game)
async def get_game(game_id: int, db: AsyncSession = Depends(get_session)): async def get_game(game_id: int, db: AsyncSession = Depends(get_session)):
return await crud.get_game(db, game_id) return await crud.get_game(db, game_id)
@router.post("/", response_model=Game)
@games_router.post("/", response_model=Game)
async def add_game(game: GameCreate, async def add_game(game: GameCreate,
user_id: int, user_id: int,
db:AsyncSession = Depends(get_session)): db: AsyncSession = Depends(get_session)):
try: try:
torrent_filename = save_torrent_file(torrent, game.title)
cover_filename = save_image(cover, game.title, "cover")
return await crud.add_game(db, game, user_id) return await crud.add_game(db, game, user_id)
except Exception as ex: except Exception:
raise HTTPException(500) raise HTTPException(500)

View File

@@ -1,9 +1,10 @@
from fastapi import APIRouter from fastapi import APIRouter
from pathlib import Path from pathlib import Path
router = APIRouter() startup_router = APIRouter()
@router.on_event("startup")
@startup_router.on_event("startup")
def startup(): def startup():
need_paths = [ need_paths = [
Path() / "content" / "images" / "cover" / "full_size", Path() / "content" / "images" / "cover" / "full_size",