diff --git a/README.md b/README.md new file mode 100644 index 0000000..36dc674 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Genshin Impact DB + +--- + +### !! Supports 4.2 !! \ No newline at end of file diff --git a/main.py b/main.py index 7199e30..ee57529 100644 --- a/main.py +++ b/main.py @@ -1,12 +1,30 @@ +from json import loads + from fastapi import FastAPI from fastapi.openapi.utils import get_openapi from fastapi.responses import JSONResponse +from pydantic import ValidationError from src.errors import Response, NOT_FOUND from src.routes.achievements import achievements from src.routes.adventureranks import adventure_ranks -from src.routes.elements import elements +from src.routes.animals import animals +from src.routes.artifacts import artifacts from src.routes.characters import characters +from src.routes.crafts import crafts +from src.routes.domains import domains +from src.routes.elements import elements +from src.routes.enemies import enemies +from src.routes.foods import foods +from src.routes.geographies import geographies +from src.routes.glider import gliders +from src.routes.materials import materials +from src.routes.namecards import namecards +from src.routes.outfits import outfits +from src.routes.talentmaterialtypes import talent_material_types +from src.routes.tcg import tcg +from src.routes.weaponmaterialtypes import weapon_material_types +from src.routes.weapons import weapons app = FastAPI(title='Genshin Impact DB') @@ -19,10 +37,20 @@ async def not_found(r, e): ) -app.include_router(achievements) -app.include_router(adventure_ranks) -app.include_router(characters) -app.include_router(elements) +@app.exception_handler(ValidationError) +async def validation_error(_, e: ValidationError): + return JSONResponse( + status_code=412, + content=Response(error=True, response=loads(e.json())).model_dump() + ) + + +routers = [achievements, adventure_ranks, animals, artifacts, characters, crafts, domains, elements, enemies, foods, + geographies, materials, namecards, outfits, talent_material_types, weapon_material_types, weapons, gliders, + tcg] + +for router in routers: + app.include_router(router) def custom_openapi(): diff --git a/src/errors.py b/src/errors.py index d83ad0b..a0e2144 100644 --- a/src/errors.py +++ b/src/errors.py @@ -1,5 +1,3 @@ -from typing import Any, Optional - from pydantic import BaseModel @@ -15,3 +13,4 @@ class Response[T](BaseModel): # Constants NOT_FOUND = ErrorData(error_code=1, error_text='Not Found') +VALIDATION_ERROR = ErrorData(error_code=2, error_text='Validation Error') diff --git a/src/routes/achievements.py b/src/routes/achievements.py index d8434e1..29ae054 100644 --- a/src/routes/achievements.py +++ b/src/routes/achievements.py @@ -4,7 +4,7 @@ from fastapi import APIRouter from src.errors import Response from src.types.achievements import AchievementGroups, Achievement -from src.utils import parse_query_langs, load_index, load_file, parse_result_lang +from src.utils import parse_query_langs, load_index, load_category, parse_result_lang achievements = APIRouter(prefix='/achievements', tags=['Achievements']) @@ -33,7 +33,7 @@ async def get_achievement_group(name: str, query_languages: str = 'eng', result_ break else: raise HTTPException(404) - return Response[Achievement](response=load_file(result_lang, 'achievements', filename)) + return Response[Achievement](response=load_category(result_lang, 'achievements', filename)) @achievements.get('/groups') @@ -60,4 +60,4 @@ async def get_achievement_group(name: str, query_languages: str = 'eng', result_ break else: raise HTTPException(404) - return Response[AchievementGroups](response=load_file(result_lang, 'achievementgroups', filename)) + return Response[AchievementGroups](response=load_category(result_lang, 'achievementgroups', filename)) diff --git a/src/routes/adventureranks.py b/src/routes/adventureranks.py index 7743867..ca59b10 100644 --- a/src/routes/adventureranks.py +++ b/src/routes/adventureranks.py @@ -2,7 +2,7 @@ from fastapi import APIRouter, HTTPException from src.errors import Response from src.types.adventureranks import AdventureRank -from src.utils import parse_query_langs, load_index, parse_result_lang, load_file +from src.utils import parse_query_langs, load_index, parse_result_lang, load_category adventure_ranks = APIRouter(prefix='/adventure_ranks', tags=['Adventure Ranks']) @@ -31,4 +31,4 @@ async def query_character(query: str, query_languages: str = 'eng', result_langu break else: raise HTTPException(404) - return Response[AdventureRank](response=load_file(result_lang, 'adventureranks', filename)) + return Response[AdventureRank](response=load_category(result_lang, 'adventureranks', filename)) diff --git a/src/routes/animals.py b/src/routes/animals.py new file mode 100644 index 0000000..fe21691 --- /dev/null +++ b/src/routes/animals.py @@ -0,0 +1,26 @@ +from fastapi import APIRouter + +from src.errors import Response +from src.types.animals import Animal +from src.utils import load_index, parse_query_langs, parse_result_lang, load_category, get_file_name + +animals = APIRouter(prefix='/animals', tags=['Animals']) + + +@animals.get('/') +async def get_animals(query_field: str = 'names', query_languages: str = 'eng') -> Response: + query_langs = parse_query_langs(query_languages) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'animals') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@animals.get('/{query}') +async def get_animal(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[Animal]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'animals', query_langs) + print(filename) + return Response[Animal](response=load_category(result_lang, 'animals', filename)) diff --git a/src/routes/artifacts.py b/src/routes/artifacts.py new file mode 100644 index 0000000..9923d68 --- /dev/null +++ b/src/routes/artifacts.py @@ -0,0 +1,25 @@ +from fastapi import APIRouter + +from src.errors import Response +from src.types.artifacts import Artifact +from src.utils import load_index, parse_query_langs, parse_result_lang, load_category, get_file_name + +artifacts = APIRouter(prefix='/artifacts', tags=['Artifacts']) + + +@artifacts.get('/') +async def get_artifacts(query_field: str = 'names', query_languages: str = 'eng') -> Response: + query_langs = parse_query_langs(query_languages) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'artifacts') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@artifacts.get('/{query}') +async def get_artifact(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[Artifact]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'artifacts', query_langs) + return Response[Artifact](response=load_category(result_lang, 'artifacts', filename)) diff --git a/src/routes/characters.py b/src/routes/characters.py index f264cfd..b8c809f 100644 --- a/src/routes/characters.py +++ b/src/routes/characters.py @@ -1,14 +1,14 @@ from fastapi import APIRouter, HTTPException from src.errors import Response -from src.types.characters import Character -from src.utils import load_index, parse_query_langs, parse_result_lang, load_file +from src.types.characters import Character, Constellations, Talents +from src.utils import load_index, parse_query_langs, parse_result_lang, load_category, load_file, get_file_name characters = APIRouter(prefix='/characters', tags=['Characters']) @characters.get('/') -async def query_characters(query_field: str = 'names', query_languages: str = 'eng') -> Response: +async def get_characters(query_field: str = 'names', query_languages: str = 'eng') -> Response: query_langs = parse_query_langs(query_languages) response = [] for query_lang in query_langs: @@ -17,18 +17,46 @@ async def query_characters(query_field: str = 'names', query_languages: str = 'e return Response(error=False, response=response) -@characters.get('/{query}') -async def query_character(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[Character]: +@characters.get('/{name}') +async def get_character( + name: str, query_languages: str = 'eng', result_language: str = 'ru', + images: bool = False, stats: bool = False, url: bool = False +) -> Response[Character]: query_langs = parse_query_langs(query_languages) result_lang = parse_result_lang(result_language) + filename = get_file_name(name, 'characters', query_langs) - filename = '' - for lang in query_langs: - index: dict[str, str] = load_index(lang, 'characters')['names'] - for key, value in index.items(): - if key.lower().startswith(query): - filename = value - break - else: - raise HTTPException(404) - return Response[Character](response=load_file(result_lang, 'characters', filename)) + response = load_category(result_lang, 'characters', filename) + if images: + images_file = load_file('image', 'characters') + response.update({'images': images_file[filename]}) + if stats: + stats_file = load_file('stats', 'characters') + response.update({'stats': stats_file[filename]}) + if url: + url_file = load_file('url', 'characters') + if filename in url_file: + response.update({'url': url_file[filename]}) + + version_file = load_file('version', 'characters') + response.update({'version': version_file[filename]}) + + return Response[Character](response=response) + + +@characters.get('/{name}/constellations') +async def get_constellations( + name: str, query_languages: str = 'eng', result_language: str = 'ru', +) -> Response[Constellations]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(name, 'characters', query_langs) + return Response[Constellations](response=load_category(result_lang, 'constellations', filename)) + + +@characters.get('/{name}/talents') +async def get_talents(name: str, query_languages: str = 'eng', result_language: str = 'ru',) -> Response[Talents]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(name, 'characters', query_langs) + return Response[Talents](response=load_category(result_lang, 'talents', filename)) diff --git a/src/routes/crafts.py b/src/routes/crafts.py new file mode 100644 index 0000000..2d7e12c --- /dev/null +++ b/src/routes/crafts.py @@ -0,0 +1,25 @@ +from fastapi import APIRouter + +from src.errors import Response +from src.types.crafts import Craft +from src.utils import load_index, parse_query_langs, parse_result_lang, load_category, get_file_name + +crafts = APIRouter(prefix='/crafts', tags=['Crafts']) + + +@crafts.get('/') +async def get_crafts(query_field: str = 'names', query_languages: str = 'eng') -> Response: + query_langs = parse_query_langs(query_languages) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'crafts') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@crafts.get('/{query}') +async def get_craft(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[Craft]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'crafts', query_langs) + return Response[Craft](response=load_category(result_lang, 'crafts', filename)) diff --git a/src/routes/domains.py b/src/routes/domains.py new file mode 100644 index 0000000..dd553fe --- /dev/null +++ b/src/routes/domains.py @@ -0,0 +1,25 @@ +from fastapi import APIRouter + +from src.errors import Response +from src.types.domains import Domain +from src.utils import load_index, parse_query_langs, parse_result_lang, load_category, get_file_name + +domains = APIRouter(prefix='/domains', tags=['Domains']) + + +@domains.get('/') +async def get_domains(query_field: str = 'names', query_languages: str = 'eng') -> Response: + query_langs = parse_query_langs(query_languages) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'domains') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@domains.get('/{query}', response_model_exclude_none=True) +async def get_domain(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[Domain]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'domains', query_langs) + return Response[Domain](response=load_category(result_lang, 'domains', filename)) diff --git a/src/routes/elements.py b/src/routes/elements.py index 95afde5..541c924 100644 --- a/src/routes/elements.py +++ b/src/routes/elements.py @@ -1,19 +1,12 @@ -from fastapi import APIRouter, HTTPException -from pydantic import BaseModel +from fastapi import APIRouter -from src.constants import LANGUAGES from src.errors import Response -from src.types.characters import Character from src.types.elements import Element -from src.utils import load_index, parse_query_langs, parse_result_lang, load_file +from src.utils import load_index, parse_query_langs, parse_result_lang, load_category, get_file_name elements = APIRouter(prefix='/elements', tags=['Elements']) -class QueryCharacters(BaseModel): - res: dict[str, list[str]] - - @elements.get('/') async def query_elements(query_field: str = 'names', query_languages: str = 'eng') -> Response: query_langs = parse_query_langs(query_languages) @@ -28,14 +21,5 @@ async def query_elements(query_field: str = 'names', query_languages: str = 'eng async def query_element(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[Element]: query_langs = parse_query_langs(query_languages) result_lang = parse_result_lang(result_language) - - filename = '' - for lang in query_langs: - index: dict[str, str] = load_index(lang, 'elements')['names'] - for key, value in index.items(): - if key.lower().startswith(query): - filename = value - break - else: - raise HTTPException(404) - return Response[Element](response=load_file(result_lang, 'elements', filename)) + filename = get_file_name(query, 'elements', query_langs) + return Response[Element](response=load_category(result_lang, 'elements', filename)) diff --git a/src/routes/enemies.py b/src/routes/enemies.py new file mode 100644 index 0000000..db645d8 --- /dev/null +++ b/src/routes/enemies.py @@ -0,0 +1,25 @@ +from fastapi import APIRouter + +from src.errors import Response +from src.types.enemies import Enemy +from src.utils import load_index, parse_query_langs, parse_result_lang, load_category, get_file_name + +enemies = APIRouter(prefix='/enemies', tags=['Enemies']) + + +@enemies.get('/') +async def get_enemies(query_field: str = 'names', query_languages: str = 'eng') -> Response: + query_langs = parse_query_langs(query_languages) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'enemies') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@enemies.get('/{query}', response_model_exclude_none=True) +async def get_enemy(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[Enemy]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'enemies', query_langs) + return Response[Enemy](response=load_category(result_lang, 'enemies', filename)) diff --git a/src/routes/foods.py b/src/routes/foods.py new file mode 100644 index 0000000..da145b6 --- /dev/null +++ b/src/routes/foods.py @@ -0,0 +1,25 @@ +from fastapi import APIRouter + +from src.errors import Response +from src.types.foods import Food +from src.utils import load_index, parse_query_langs, parse_result_lang, load_category, get_file_name + +foods = APIRouter(prefix='/foods', tags=['Foods']) + + +@foods.get('/') +async def get_foods(query_field: str = 'names', query_languages: str = 'eng') -> Response: + query_langs = parse_query_langs(query_languages) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'foods') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@foods.get('/{query}', response_model_exclude_none=True) +async def get_food(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[Food]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'foods', query_langs) + return Response[Food](response=load_category(result_lang, 'foods', filename)) diff --git a/src/routes/geographies.py b/src/routes/geographies.py new file mode 100644 index 0000000..d82b503 --- /dev/null +++ b/src/routes/geographies.py @@ -0,0 +1,25 @@ +from fastapi import APIRouter + +from src.errors import Response +from src.types.geographies import Geography +from src.utils import load_index, parse_query_langs, parse_result_lang, load_category, get_file_name + +geographies = APIRouter(prefix='/geographies', tags=['Geographies']) + + +@geographies.get('/') +async def get_geographies(query_field: str = 'names', query_languages: str = 'eng') -> Response: + query_langs = parse_query_langs(query_languages) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'geographies') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@geographies.get('/{query}', response_model_exclude_none=True) +async def get_geography(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[Geography]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'geographies', query_langs) + return Response[Geography](response=load_category(result_lang, 'geographies', filename)) diff --git a/src/routes/glider.py b/src/routes/glider.py new file mode 100644 index 0000000..319c1a7 --- /dev/null +++ b/src/routes/glider.py @@ -0,0 +1,25 @@ +from fastapi import APIRouter + +from src.errors import Response +from src.types.gliders import Glider +from src.utils import load_index, parse_query_langs, parse_result_lang, load_category, get_file_name + +gliders = APIRouter(prefix='/gliders', tags=['Gliders']) + + +@gliders.get('/') +async def get_gliders(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'windgliders') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@gliders.get('/{query}', response_model_exclude_none=True) +async def get_glider(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[Glider]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'windgliders', query_langs) + return Response[Glider](response=load_category(result_lang, 'windgliders', filename)) diff --git a/src/routes/materials.py b/src/routes/materials.py new file mode 100644 index 0000000..f5a70b4 --- /dev/null +++ b/src/routes/materials.py @@ -0,0 +1,25 @@ +from fastapi import APIRouter + +from src.errors import Response +from src.types.materials import Material +from src.utils import load_index, parse_query_langs, parse_result_lang, load_category, get_file_name + +materials = APIRouter(prefix='/materials', tags=['Materials']) + + +@materials.get('/') +async def get_materials(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'materials') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@materials.get('/{query}', response_model_exclude_none=True) +async def get_material(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[Material]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'materials', query_langs) + return Response[Material](response=load_category(result_lang, 'materials', filename)) diff --git a/src/routes/namecards.py b/src/routes/namecards.py new file mode 100644 index 0000000..72ee27c --- /dev/null +++ b/src/routes/namecards.py @@ -0,0 +1,25 @@ +from fastapi import APIRouter + +from src.errors import Response +from src.types.namecards import NameCard +from src.utils import load_index, parse_query_langs, parse_result_lang, load_category, get_file_name + +namecards = APIRouter(prefix='/namecards', tags=['Namecards']) + + +@namecards.get('/') +async def get_namecards(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'namecards') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@namecards.get('/{query}', response_model_exclude_none=True) +async def get_namecard(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[NameCard]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'namecards', query_langs) + return Response[NameCard](response=load_category(result_lang, 'namecards', filename)) diff --git a/src/routes/outfits.py b/src/routes/outfits.py new file mode 100644 index 0000000..6f23ba6 --- /dev/null +++ b/src/routes/outfits.py @@ -0,0 +1,25 @@ +from fastapi import APIRouter + +from src.errors import Response +from src.types.outfits import Outfit +from src.utils import load_index, parse_query_langs, parse_result_lang, load_category, get_file_name + +outfits = APIRouter(prefix='/outfits', tags=['Outfits']) + + +@outfits.get('/') +async def get_outfits(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'outfits') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@outfits.get('/{query}', response_model_exclude_none=True) +async def get_outfit(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[Outfit]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'outfits', query_langs) + return Response[Outfit](response=load_category(result_lang, 'outfits', filename)) diff --git a/src/routes/talentmaterialtypes.py b/src/routes/talentmaterialtypes.py new file mode 100644 index 0000000..2e20164 --- /dev/null +++ b/src/routes/talentmaterialtypes.py @@ -0,0 +1,27 @@ +from fastapi import APIRouter + +from src.errors import Response +from src.types.talentmaterialtypes import TalentMaterialType +from src.utils import load_index, parse_query_langs, parse_result_lang, load_category, get_file_name + +talent_material_types = APIRouter(prefix='/talent_material_type', tags=['Talent Material']) + + +@talent_material_types.get('/') +async def get_talent_material_types(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'talentmaterialtypes') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@talent_material_types.get('/{query}', response_model_exclude_none=True) +async def get_talent_material_type( + query: str, query_languages: str = 'eng', result_language: str = 'ru' +) -> Response[TalentMaterialType]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'talentmaterialtypes', query_langs) + return Response[TalentMaterialType](response=load_category(result_lang, 'talentmaterialtypes', filename)) diff --git a/src/routes/tcg.py b/src/routes/tcg.py new file mode 100644 index 0000000..bc37571 --- /dev/null +++ b/src/routes/tcg.py @@ -0,0 +1,202 @@ +from fastapi import APIRouter + +from src.errors import Response +from src.types.tcg import ActionCard, CardBack, CardBox, CharacterCard, DetailedRule, EnemyCard, Keyword, LevelReward, \ + StatusEffect, Summon +from src.utils import get_file_name, parse_result_lang, parse_query_langs, load_category, load_index + +tcg = APIRouter(prefix='/tcg', tags=['TCG']) + + +@tcg.get('/action_cards') +async def get_action_cards(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'tcgactioncards') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@tcg.get('/action_cards/{query}', response_model_exclude_none=True) +async def get_action_card(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[ActionCard]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'tcgactioncards', query_langs) + return Response[ActionCard](response=load_category(result_lang, 'tcgactioncards', filename)) + + +@tcg.get('/card_backs') +async def get_card_backs(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'tcgcardbacks') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@tcg.get('/card_back/{query}', response_model_exclude_none=True) +async def get_card_back(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[CardBack]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'tcgcardbacks', query_langs) + return Response[CardBack](response=load_category(result_lang, 'tcgcardbacks', filename)) + + +@tcg.get('/card_boxes') +async def get_card_boxes(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'tcgcardboxes') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@tcg.get('/card_boxes/{query}', response_model_exclude_none=True) +async def get_card_box(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[CardBox]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'tcgcardboxes', query_langs) + return Response[CardBox](response=load_category(result_lang, 'tcgcardboxes', filename)) + + +@tcg.get('/character_cards') +async def get_character_cards(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'tcgcharactercards') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@tcg.get('/character_cards/{query}', response_model_exclude_none=True) +async def get_character_card( + query: str, query_languages: str = 'eng', result_language: str = 'ru' +) -> Response[CharacterCard]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'tcgcharactercards', query_langs) + return Response[CharacterCard](response=load_category(result_lang, 'tcgcharactercards', filename)) + + +@tcg.get('/enemy_cards') +async def get_enemy_cards(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'tcgenemycards') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@tcg.get('/enemy_cards/{query}', response_model_exclude_none=True) +async def get_enemy_card( + query: str, query_languages: str = 'eng', result_language: str = 'ru' +) -> Response[EnemyCard]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'tcgenemycards', query_langs) + return Response[EnemyCard](response=load_category(result_lang, 'tcgenemycards', filename)) + + +@tcg.get('/detailed_rules') +async def get_detailed_rules(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'tcgdetailedrules') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@tcg.get('/detailed_rules/{query}', response_model_exclude_none=True) +async def get_detailed_rule( + query: str, query_languages: str = 'eng', result_language: str = 'ru' +) -> Response[DetailedRule]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'tcgdetailedrules', query_langs) + return Response[DetailedRule](response=load_category(result_lang, 'tcgdetailedrules', filename)) + + +@tcg.get('/keywords') +async def get_keywords(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'tcgkeywords') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@tcg.get('/keywords/{query}', response_model_exclude_none=True) +async def get_keyword( + query: str, query_languages: str = 'eng', result_language: str = 'ru' +) -> Response[Keyword]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'tcgkeywords', query_langs) + return Response[Keyword](response=load_category(result_lang, 'tcgkeywords', filename)) + + +@tcg.get('/level_rewards') +async def get_level_rewards(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'tcglevelrewards') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@tcg.get('/level_rewards/{query}', response_model_exclude_none=True) +async def get_level_reward( + query: str, query_languages: str = 'eng', result_language: str = 'ru' +) -> Response[LevelReward]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'tcglevelrewards', query_langs) + return Response[LevelReward](response=load_category(result_lang, 'tcglevelrewards', filename)) + + +@tcg.get('/status_effects') +async def get_status_effects(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'tcgstatuseffects') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@tcg.get('/status_effects/{query}', response_model_exclude_none=True) +async def get_status_effect( + query: str, query_languages: str = 'eng', result_language: str = 'ru' +) -> Response[StatusEffect]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'tcgstatuseffects', query_langs) + return Response[StatusEffect](response=load_category(result_lang, 'tcgstatuseffects', filename)) + + +@tcg.get('/summons') +async def get_summons(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'tcgsummons') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@tcg.get('/summons/{query}', response_model_exclude_none=True) +async def get_summon( + query: str, query_languages: str = 'eng', result_language: str = 'ru' +) -> Response[Summon]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'tcgsummons', query_langs) + return Response[Summon](response=load_category(result_lang, 'tcgsummons', filename)) diff --git a/src/routes/weaponmaterialtypes.py b/src/routes/weaponmaterialtypes.py new file mode 100644 index 0000000..7da4390 --- /dev/null +++ b/src/routes/weaponmaterialtypes.py @@ -0,0 +1,27 @@ +from fastapi import APIRouter + +from src.errors import Response +from src.types.weaponmaterialtypes import WeaponMaterialType +from src.utils import load_index, parse_query_langs, parse_result_lang, load_category, get_file_name + +weapon_material_types = APIRouter(prefix='/weapon_material_type', tags=['Weapon Material']) + + +@weapon_material_types.get('/') +async def get_weapon_material_types(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'weaponmaterialtypes') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@weapon_material_types.get('/{query}', response_model_exclude_none=True) +async def get_weapon_material_type( + query: str, query_languages: str = 'eng', result_language: str = 'ru' +) -> Response[WeaponMaterialType]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'weaponmaterialtypes', query_langs) + return Response[WeaponMaterialType](response=load_category(result_lang, 'weaponmaterialtypes', filename)) diff --git a/src/routes/weapons.py b/src/routes/weapons.py new file mode 100644 index 0000000..899917c --- /dev/null +++ b/src/routes/weapons.py @@ -0,0 +1,25 @@ +from fastapi import APIRouter + +from src.errors import Response +from src.types.weapons import Weapon +from src.utils import load_index, parse_query_langs, parse_result_lang, load_category, get_file_name + +weapons = APIRouter(prefix='/weapons', tags=['Weapons']) + + +@weapons.get('/') +async def get_weapons(query_field: str = 'names', result_language: str = 'eng') -> Response: + query_langs = parse_query_langs(result_language) + response: list[dict[str, list[str]]] = [] + for query_lang in query_langs: + chars = load_index(query_lang, 'weapons') + response.append({query_lang: list(chars[query_field].keys())}) + return Response[list[dict[str, list[str]]]](error=False, response=response) + + +@weapons.get('/{query}', response_model_exclude_none=True) +async def get_weapon(query: str, query_languages: str = 'eng', result_language: str = 'ru') -> Response[Weapon]: + query_langs = parse_query_langs(query_languages) + result_lang = parse_result_lang(result_language) + filename = get_file_name(query, 'weapons', query_langs) + return Response[Weapon](response=load_category(result_lang, 'weapons', filename)) diff --git a/src/types/animals.py b/src/types/animals.py new file mode 100644 index 0000000..0002292 --- /dev/null +++ b/src/types/animals.py @@ -0,0 +1,9 @@ +from pydantic import BaseModel + + +class Animal(BaseModel): + name: str + description: str + category: str + counttype: str + sortorder: int diff --git a/src/types/artifacts.py b/src/types/artifacts.py new file mode 100644 index 0000000..fa4e7fb --- /dev/null +++ b/src/types/artifacts.py @@ -0,0 +1,22 @@ +from typing import List + +from pydantic import BaseModel, Field + + +class Piece(BaseModel): + name: str + relictype: str + description: str + story: str + + +class Artifact(BaseModel): + name: str + rarity: List[str] + field_2pc: str = Field(..., alias='2pc') + field_4pc: str = Field(..., alias='4pc') + flower: Piece + plume: Piece + sands: Piece + goblet: Piece + circlet: Piece diff --git a/src/types/characters.py b/src/types/characters.py index ecd3715..39042f2 100644 --- a/src/types/characters.py +++ b/src/types/characters.py @@ -1,5 +1,6 @@ -from pydantic import BaseModel -from typing import List +from typing import List, Optional + +from pydantic import BaseModel, Field class Cv(BaseModel): @@ -9,43 +10,66 @@ class Cv(BaseModel): korean: str -class Ascend1Item(BaseModel): - name: str - count: int - - -class Ascend2Item(BaseModel): - name: str - count: int - - -class Ascend3Item(BaseModel): - name: str - count: int - - -class Ascend4Item(BaseModel): - name: str - count: int - - -class Ascend5Item(BaseModel): - name: str - count: int - - -class Ascend6Item(BaseModel): +class AscendItem(BaseModel): name: str count: int class Costs(BaseModel): - ascend1: List[Ascend1Item] - ascend2: List[Ascend2Item] - ascend3: List[Ascend3Item] - ascend4: List[Ascend4Item] - ascend5: List[Ascend5Item] - ascend6: List[Ascend6Item] + ascend1: List[AscendItem] + ascend2: List[AscendItem] + ascend3: List[AscendItem] + ascend4: List[AscendItem] + ascend5: List[AscendItem] + ascend6: List[AscendItem] + + +class Images(BaseModel): + card: str + portrait: str + icon: str + sideicon: str + cover1: str + cover2: str + hoyolab_avatar: str = Field(..., alias='hoyolab-avatar') + nameicon: str + nameiconcard: str + namegachasplash: str + namegachaslice: str + namesideicon: str + + +class Base(BaseModel): + hp: float + attack: float + defense: float + critrate: float + critdmg: float + + +class Curve(BaseModel): + hp: str + attack: str + defense: str + + +class PromotionItem(BaseModel): + maxlevel: int + hp: float + attack: float + defense: float + specialized: float + + +class Stats(BaseModel): + base: Base + curve: Curve + specialized: str + promotion: List[PromotionItem] + + +class URL(BaseModel): + fandom: str class Character(BaseModel): @@ -66,4 +90,69 @@ class Character(BaseModel): birthday: str constellation: str cv: Cv - costs: Costs \ No newline at end of file + costs: Costs + images: Optional[Images] = None + stats: Optional[Stats] = None + url: Optional[URL] = None + version: str + + +# Constellations +class Constellation(BaseModel): + name: str + effect: str + + +class Constellations(BaseModel): + name: str + c1: Constellation + c2: Constellation + c3: Constellation + c4: Constellation + c5: Constellation + c6: Constellation + + +# Talents +class Attributes(BaseModel): + labels: List[str] + + +class Combat(BaseModel): + name: str + info: str + description: Optional[str] = None + attributes: Attributes + + +class Passive(BaseModel): + name: str + info: str + + +class LvlItem(BaseModel): + name: str + count: int + + +class TalentCosts(BaseModel): + lvl2: List[LvlItem] + lvl3: List[LvlItem] + lvl4: List[LvlItem] + lvl5: List[LvlItem] + lvl6: List[LvlItem] + lvl7: List[LvlItem] + lvl8: List[LvlItem] + lvl9: List[LvlItem] + lvl10: List[LvlItem] + + +class Talents(BaseModel): + name: str + combat1: Combat + combat2: Combat + combat3: Combat + passive1: Passive + passive2: Passive + passive3: Passive + costs: TalentCosts diff --git a/src/types/crafts.py b/src/types/crafts.py new file mode 100644 index 0000000..4f76acf --- /dev/null +++ b/src/types/crafts.py @@ -0,0 +1,18 @@ +from typing import List, Optional + +from pydantic import BaseModel + + +class RecipeItem(BaseModel): + name: str + count: int + + +class Craft(BaseModel): + name: str + filter: str + sortorder: int + unlockrank: int + resultcount: int + moracost: Optional[int] = 0 + recipe: List[RecipeItem] diff --git a/src/types/domains.py b/src/types/domains.py new file mode 100644 index 0000000..71194ec --- /dev/null +++ b/src/types/domains.py @@ -0,0 +1,23 @@ +from typing import List, Optional + +from pydantic import BaseModel + + +class RewardpreviewItem(BaseModel): + name: str + count: Optional[int] = None + rarity: Optional[str] = None + + +class Domain(BaseModel): + name: str + region: str + domainentrance: str + domaintype: str + description: str + recommendedlevel: int + recommendedelements: List[str] + unlockrank: int + rewardpreview: List[RewardpreviewItem] + disorder: List[str] + monsterlist: List[str] diff --git a/src/types/enemies.py b/src/types/enemies.py new file mode 100644 index 0000000..9161016 --- /dev/null +++ b/src/types/enemies.py @@ -0,0 +1,18 @@ +from typing import List, Optional + +from pydantic import BaseModel + + +class RewardpreviewItem(BaseModel): + name: str + count: Optional[float] = None + rarity: Optional[str] = None + + +class Enemy(BaseModel): + name: str + specialname: str + enemytype: str + category: str + description: str + rewardpreview: List[RewardpreviewItem] diff --git a/src/types/foods.py b/src/types/foods.py new file mode 100644 index 0000000..5dfbf7b --- /dev/null +++ b/src/types/foods.py @@ -0,0 +1,29 @@ +from typing import List, Optional + +from pydantic import BaseModel + + +class Quality(BaseModel): + effect: str + description: str + + +class Ingredient(BaseModel): + name: str + count: int + + +class Food(BaseModel): + name: str + rarity: str + foodtype: str + foodfilter: str + foodcategory: str + effect: str + description: str + basedish: Optional[str] = None + character: Optional[str] = None + suspicious: Optional[Quality] = None + normal: Optional[Quality] = None + delicious: Optional[Quality] = None + ingredients: List[Ingredient] diff --git a/src/types/geographies.py b/src/types/geographies.py new file mode 100644 index 0000000..744443e --- /dev/null +++ b/src/types/geographies.py @@ -0,0 +1,10 @@ +from pydantic import BaseModel + + +class Geography(BaseModel): + name: str + area: str + description: str + region: str + showonlyunlocked: bool = False + sortorder: int diff --git a/src/types/gliders.py b/src/types/gliders.py new file mode 100644 index 0000000..00129bf --- /dev/null +++ b/src/types/gliders.py @@ -0,0 +1,12 @@ +from typing import List + +from pydantic import BaseModel + + +class Glider(BaseModel): + name: str + description: str + rarity: str + story: str + sortorder: int + source: List[str] \ No newline at end of file diff --git a/src/types/materials.py b/src/types/materials.py new file mode 100644 index 0000000..b3ccf18 --- /dev/null +++ b/src/types/materials.py @@ -0,0 +1,13 @@ +from typing import List + +from pydantic import BaseModel + + +class Material(BaseModel): + name: str + description: str + sortorder: int + rarity: str + category: str + materialtype: str + source: List[str] diff --git a/src/types/namecards.py b/src/types/namecards.py new file mode 100644 index 0000000..2b25a59 --- /dev/null +++ b/src/types/namecards.py @@ -0,0 +1,10 @@ +from typing import List + +from pydantic import BaseModel + + +class NameCard(BaseModel): + name: str + description: str + sortorder: int + source: List[str] diff --git a/src/types/outfits.py b/src/types/outfits.py new file mode 100644 index 0000000..195d06d --- /dev/null +++ b/src/types/outfits.py @@ -0,0 +1,11 @@ +from typing import List, Optional + +from pydantic import BaseModel + + +class Outfit(BaseModel): + name: str + description: str + isdefault: bool + character: str + source: Optional[List[str]] = None diff --git a/src/types/talentmaterialtypes.py b/src/types/talentmaterialtypes.py new file mode 100644 index 0000000..da44596 --- /dev/null +++ b/src/types/talentmaterialtypes.py @@ -0,0 +1,14 @@ +from typing import List + +from pydantic import BaseModel, Field + + +class TalentMaterialType(BaseModel): + name: str + field_2starname: str = Field(..., alias='2starname') + field_3starname: str = Field(..., alias='3starname') + field_4starname: str = Field(..., alias='4starname') + day: List[str] + location: str + region: str + domainofmastery: str diff --git a/src/types/tcg.py b/src/types/tcg.py new file mode 100644 index 0000000..bff3caa --- /dev/null +++ b/src/types/tcg.py @@ -0,0 +1,152 @@ +from typing import List, Optional + +from pydantic import BaseModel + + +class Playcost(BaseModel): + costtype: str + count: int + + +# Action Cards +class ActionCard(BaseModel): + id: int + name: str + cardtype: str + cardtypetext: str + tags: List[str] + tagstext: List[str] + description: str + descriptionraw: str + descriptionreplaced: str + storytitle: str + storytext: str + source: str = None + playcost: List[Playcost] + + +# Card backs +class CardBack(BaseModel): + id: int + name: str + description: str + descriptionraw: str + source: str + rarity: int + + +class CardBox(BaseModel): + id: int + name: str + description: str + descriptionraw: str + source: str + rarity: int + + +# Character cards +class Skill(BaseModel): + id: int + name: str + descriptionraw: str + basedamage: Optional[int] = None + baseelement: Optional[str] = None + descriptionreplaced: str + description: str + typetag: str + type: str + playcost: List[Playcost] + + +class CharacterCard(BaseModel): + id: int + name: str + hp: int + maxenergy: int + tags: List[str] + tagstext: List[str] + storytitle: str + storytext: str + source: str + skills: List[Skill] + + +# Enemy card +class EnemyCard(BaseModel): + id: int + name: str + hp: int + maxenergy: int + tags: List[str] + tagstext: List[str] + skills: List[Skill] + + +# Detailed rules +class Rule(BaseModel): + title: str + titleraw: str + content: str + contentraw: str + filename_image: Optional[str] = None + + +class DetailedRule(BaseModel): + id: int + name: str + rules: List[Rule] + + +# Keywords +class Keyword(BaseModel): + id: int + name: str + nameraw: str + description: str + descriptionraw: str + + +# Level rewards +class Reward(BaseModel): + id: int + name: str + count: int + + +class LevelReward(BaseModel): + id: int + name: str + exp: int = None + icontype: str + unlockdescription: str + unlockdescriptionraw: str + rewards: List[Reward] + + +# Status effects +class StatusEffect(BaseModel): + id: int + name: str + statustypetext: str + cardtype: str + cardtypetext: str + tags: List[str] + description: str + descriptionraw: str + descriptionreplaced: str + + +# Summons +class Summon(BaseModel): + id: int + name: str + cardtypetext: str + tags: List + tagstext: List + description: str + descriptionraw: str + descriptionreplaced: str + countingtype: str + tokentype: str + hinttype: str + diff --git a/src/types/weaponmaterialtypes.py b/src/types/weaponmaterialtypes.py new file mode 100644 index 0000000..addeb65 --- /dev/null +++ b/src/types/weaponmaterialtypes.py @@ -0,0 +1,15 @@ +from typing import List + +from pydantic import BaseModel, Field + + +class WeaponMaterialType(BaseModel): + name: str + field_2starname: str = Field(..., alias='2starname') + field_3starname: str = Field(..., alias='3starname') + field_4starname: str = Field(..., alias='4starname') + field_5starname: str = Field(..., alias='5starname') + day: List[str] + location: str + region: str + domainofforgery: str diff --git a/src/types/weapons.py b/src/types/weapons.py new file mode 100644 index 0000000..e79ed75 --- /dev/null +++ b/src/types/weapons.py @@ -0,0 +1,37 @@ +from typing import List + +from pydantic import BaseModel + + +class AscendItem(BaseModel): + name: str + count: int + + +class Costs(BaseModel): + ascend1: List[AscendItem] + ascend2: List[AscendItem] + ascend3: List[AscendItem] + ascend4: List[AscendItem] + ascend5: List[AscendItem] + ascend6: List[AscendItem] + + +class Weapon(BaseModel): + name: str + description: str + weapontype: str + rarity: str + story: str + baseatk: int + substat: str + subvalue: str + effectname: str + effect: str + r1: List[str] + r2: List[str] + r3: List[str] + r4: List[str] + r5: List[str] + weaponmaterialtype: str + costs: Costs diff --git a/src/utils.py b/src/utils.py index 9f5a7e1..4575dc4 100644 --- a/src/utils.py +++ b/src/utils.py @@ -1,6 +1,8 @@ from json import load from os.path import join +from fastapi import HTTPException + from src.constants import LANGUAGES, DEFAULT_RESULT, DEFAULT_QUERY, DATA_FOLDER @@ -9,11 +11,27 @@ def load_index(language: str, category: str): return load(f) -def load_file(lang: str, category: str, name: str) -> dict: +def load_category(lang: str, category: str, name: str) -> dict: with open(join(DATA_FOLDER, lang, category, f'{name}.json'), 'r', encoding='utf-8') as f: return load(f) +def load_file(folder: str, name: str) -> dict: + with open(join(DATA_FOLDER, folder, f'{name}.json'), 'r', encoding='utf-8') as f: + return load(f) + + +def get_file_name(query, category, langs) -> str: + for lang in langs: + index: dict[str, str] = load_index(lang, category)['names'] + for key, value in index.items(): + for k in key.lower().split(' '): + if k.startswith(query.lower()): + return value + else: + raise HTTPException(404) + + def parse_query_langs(langs: str) -> list[str]: languages = langs.replace(' ', '').split(',') query = []