From e02e05ea06a9c0e6443b875f891d2afd584e9fad Mon Sep 17 00:00:00 2001 From: Augusto Gunsch Date: Mon, 18 Oct 2021 17:42:26 -0300 Subject: [PATCH] Adicionar endpoint: GET /.../pokemon/{pokemonId} --- README.md | 2 +- api/routes/routes.py | 4 +++ api/views/helper.py | 55 +++++++++++++++++++++----------------- api/views/pokemon_owned.py | 15 +++++++++-- 4 files changed, 48 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 854f06d..9b931f8 100644 --- a/README.md +++ b/README.md @@ -22,5 +22,5 @@ Os endpoints que já estão funcionando marcados: - [X] GET /trainer/{trainerId} - [X] GET /trainer/{trainerId}/pokemon - [X] POST /trainer/{trainerId}/pokemon -- [ ] GET /trainer/{trainerId}/pokemon/{pokemonId} +- [X] GET /trainer/{trainerId}/pokemon/{pokemonId} - [ ] DELETE /trainer/{trainerId}/pokemon/{pokemonId} diff --git a/api/routes/routes.py b/api/routes/routes.py index 92c805f..781099b 100644 --- a/api/routes/routes.py +++ b/api/routes/routes.py @@ -29,3 +29,7 @@ def route_post_pokemons_owned(trainer, trainerId): if trainer.id != trainerId: return errors.ForbiddenError("Trainer id mismatch") return pokemon_owned.post_pokemon_owned(trainerId) + +@app.route("/trainer//pokemon/", methods=["GET"]) +def route_get_pokemon_owned(trainerId, pokemonId): + return pokemon_owned.get_pokemon_owned(trainerId, pokemonId) diff --git a/api/views/helper.py b/api/views/helper.py index 9321245..ac47f68 100644 --- a/api/views/helper.py +++ b/api/views/helper.py @@ -11,26 +11,26 @@ class HTTPError(Exception): def __init__(self, message): self.message = message -class TrainerNotFound(Exception): +class NotFound(Exception): pass -def get_trainer_fail(id): +def get_or_not_found(callback): try: - trainer = Trainer.query.get(id) - if trainer is None: - raise TrainerNotFound() - return trainer + resource = callback() + if resource is None: + raise NotFound() + return resource except: - raise TrainerNotFound() + raise NotFound() + +def get_trainer_fail(id): + return get_or_not_found(lambda : Trainer.query.get(id)) def get_trainer_by_nick_fail(nickname): - try: - trainer = Trainer.query.filter_by(nickname=nickname).one() - if trainer is None: - raise TrainerNotFound() - return trainer - except: - raise TrainerNotFound() + return get_or_not_found(lambda : Trainer.query.filter_by(nickname=nickname).one()) + +def get_pokemon_fail(trainer, id): + return get_or_not_found(lambda : trainer.pokemons_list.filter_by(id=id).one()) # authenticação do trainer (decorator) def token_required(f): @@ -38,13 +38,12 @@ def token_required(f): def decorated(*args, **kwargs): try: token = request.headers["authorization"] - print(token) - print(app.config["SECRET_KEY"]) data = jwt.decode(token, app.config["SECRET_KEY"], algorithms=["HS256"]) - print(data["username"]) trainer = get_trainer_by_nick_fail(data["username"]) except (TypeError, KeyError): return AuthenticationFailure("JWT token required") + except NotFound: + return AuthenticationFailure("Trainer not found") except: return AuthenticationFailure("JWT token is invalid or expired") @@ -53,13 +52,19 @@ def token_required(f): # seguintes funções puxam informações da pokeapi def set_pokemon_data(pokemon): - response = requests.get("https://pokeapi.co/api/v2/pokemon/{}".format(pokemon.pokemon_id)) - if response.status_code != 200: - raise HTTPError("Could not fetch pokemon with id {}".format(pokemon.pokemon_id)) - pokemon.pokemon_data = json.loads(response.text) + try: + response = requests.get("https://pokeapi.co/api/v2/pokemon/{}".format(pokemon.pokemon_id)) + if response.status_code != 200: + raise HTTPError("Could not fetch pokemon with id {}".format(pokemon.pokemon_id)) + pokemon.pokemon_data = json.loads(response.text) + except: + raise HTTPError("Could not fetch pokemon with id {}".format(pokemon.pokemon_id)) async def async_set_pokemon_data(session, pokemon): - response = await session.get("https://pokeapi.co/api/v2/pokemon/{}".format(pokemon.pokemon_id)) - if response.status != 200: - raise HTTPError("Could not fetch pokemon with id {}".format(pokemon.pokemon_id)) - pokemon.pokemon_data = json.loads(await response.text()) + try: + response = await session.get("https://pokeapi.co/api/v2/pokemon/{}".format(pokemon.pokemon_id)) + if response.status != 200: + raise HTTPError("Could not fetch pokemon with id {}".format(pokemon.pokemon_id)) + pokemon.pokemon_data = json.loads(await response.text()) + except: + raise HTTPError("Could not fetch pokemon with id {}".format(pokemon.pokemon_id)) diff --git a/api/views/pokemon_owned.py b/api/views/pokemon_owned.py index 8dbd8b1..58d4642 100644 --- a/api/views/pokemon_owned.py +++ b/api/views/pokemon_owned.py @@ -2,7 +2,7 @@ from api.models.pokemon_owned import pokemon_owned_schema, pokemon_owned_schemas from api.app import db from .parse_args import parse_limit, parse_offset, ParsingException, parse_json_obj from .errors import ParsingError, FetchError, ConflictingResources -from .helper import TrainerNotFound, HTTPError, get_trainer_fail, set_pokemon_data, async_set_pokemon_data +from .helper import * from aiohttp import ClientSession from asyncio import create_task, gather from sqlalchemy.exc import IntegrityError @@ -46,7 +46,7 @@ async def get_pokemons_owned(trainer_id): try: trainer = get_trainer_fail(trainer_id) - except TrainerNotFound: + except NotFound: return "", 404 pokemons = trainer.pokemons_list.limit(limit).offset(offset).all() @@ -62,3 +62,14 @@ async def get_pokemons_owned(trainer_id): return FetchError(e.message) return pokemon_owned_schemas.dumps(pokemons) + +def get_pokemon_owned(trainer_id, pokemon_id): + try: + trainer = get_trainer_fail(trainer_id) + pokemon = get_pokemon_fail(trainer, pokemon_id) + set_pokemon_data(pokemon) + return pokemon_owned_schema.dump(pokemon) + except NotFound: + return "", 404 + except HTTPError as e: + return FetchError(e.message)