mirror of
				https://github.com/arcan1s/ffxivbis.git
				synced 2025-10-30 21:23:41 +00:00 
			
		
		
		
	complete swagger
This commit is contained in:
		
							
								
								
									
										104
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								README.md
									
									
									
									
									
								
							| @ -2,104 +2,30 @@ | ||||
|  | ||||
| Service which allows to manage savage loot distribution easy. | ||||
|  | ||||
| ## REST API | ||||
| ## Installation and usage | ||||
|  | ||||
| ### Party API | ||||
| This service requires python >= 3.7. For other dependencies see `setup.py`. | ||||
|  | ||||
| * `GET /api/v1/party` | ||||
| In general installation process looks like: | ||||
|  | ||||
|     Get party list. Parameters: | ||||
| ```bash | ||||
| python setup.py build | ||||
| python setup.py test  # if you want to run tests | ||||
| ``` | ||||
|  | ||||
|     * `nick`: player full nickname to filter, string, optional. | ||||
| Service can be run from `src` directory by using command: | ||||
|  | ||||
| * `POST /api/v1/party` | ||||
| ```bash | ||||
| python -m service.application.application | ||||
| ``` | ||||
|  | ||||
|     Add or remove party member. Parameters: | ||||
| To see all available options type `--help`. | ||||
|  | ||||
|     * `action`: action to do, string, required. One of `add`, `remove`. | ||||
|     * `job`: player job name, string, required. | ||||
|     * `nick`: player nickname, string, required. | ||||
|     * `link`: link to ariyala set to parse BiS, string, optional. | ||||
| ## Web service | ||||
|  | ||||
| ### BiS API | ||||
|  | ||||
| * `GET /api/v1/party/bis` | ||||
|  | ||||
|     Get party/player BiS. Parameters: | ||||
|      | ||||
|     * `nick`: player full nickname to filter, string, optional. | ||||
|      | ||||
| * `POST /api/v1/party/bis` | ||||
|  | ||||
|     Add or remove item to/from BiS. Parameters: | ||||
|      | ||||
|     * `action`: action to do, string, required. One of `add`, `remove`. | ||||
|     * `job`: player job name, string, required. | ||||
|     * `nick`: player nickname, string, required. | ||||
|     * `is_tome`: is item tome gear or not, bool, required. | ||||
|     * `piece`: item name, string, required. | ||||
|      | ||||
| * `PUT /api/v1/party/bis` | ||||
|  | ||||
|     Create BiS from ariyala link. Parameters: | ||||
|      | ||||
|     * `job`: player job name, string, required. | ||||
|     * `nick`: player nickname, string, required. | ||||
|     * `link`: link to ariyala set to parse BiS, string, required. | ||||
|      | ||||
| ### Loot API | ||||
|  | ||||
| * `GET /api/v1/party/loot` | ||||
|  | ||||
|     Get party/player loot. Parameters: | ||||
|      | ||||
|     * `nick`: player full nickname to filter, string, optional. | ||||
|      | ||||
| * `POST /api/v1/party/loot` | ||||
|  | ||||
|     Add or remove item to/from loot list. Parameters: | ||||
|      | ||||
|     * `action`: action to do, string, required. One of `add`, `remove`. | ||||
|     * `job`: player job name, string, required. | ||||
|     * `nick`: player nickname, string, required. | ||||
|     * `is_tome`: is item tome gear or not, bool, required. | ||||
|     * `piece`: item name, string, required. | ||||
|      | ||||
| * `PUT /api/v1/party/loot` | ||||
|  | ||||
|     Suggest players to get loot. Parameters: | ||||
|      | ||||
|     * `is_tome`: is item tome gear or not, bool, required. | ||||
|     * `piece`: item name, string, required. | ||||
|      | ||||
|      | ||||
| ### Users API | ||||
|  | ||||
| * `DELETE /api/v1/login/{username}` | ||||
|      | ||||
|     Delete user with specified username. Parameters: | ||||
|      | ||||
|     * `username`: username to remove, required. | ||||
|      | ||||
| * `POST /api/v1/login` | ||||
|         | ||||
|     Login with credentials. Parameters: | ||||
|      | ||||
|     * `username`: username to login, string, required. | ||||
|     * `password`: password to login, string, required. | ||||
|      | ||||
| * `PUT /api/v1/login` | ||||
|  | ||||
|     Create new user. Parameters: | ||||
|      | ||||
|     * `username`: username to login, string, required. | ||||
|     * `password`: password to login, string,  | ||||
|     * `permission`: user permission, one of `get`, `post`, optional, default `get`. | ||||
|      | ||||
| * `POST /api/v1/logout` | ||||
|  | ||||
|     Logout. | ||||
| REST API documentation is available at `http://0.0.0.0:8000/api-docs`. HTML representation is available at `http://0.0.0.0:8000`. | ||||
|  | ||||
| *Note*: host and port depend on configuration settings.  | ||||
|  | ||||
| ## Configuration | ||||
|  | ||||
|  | ||||
| @ -11,13 +11,15 @@ from apispec import APISpec | ||||
|  | ||||
| from service.core.version import __version__ | ||||
| from service.models.action import Action | ||||
| from service.models.bis import BiS | ||||
| from service.models.bis import BiS, BiSLink | ||||
| from service.models.error import Error | ||||
| from service.models.job import Job | ||||
| from service.models.loot import Loot | ||||
| from service.models.piece import Piece | ||||
| from service.models.player import Player, PlayerId | ||||
| from service.models.player import Player, PlayerId, PlayerIdWithCounters | ||||
| from service.models.player_edit import PlayerEdit | ||||
| from service.models.upgrade import Upgrade | ||||
| from service.models.user import User | ||||
|  | ||||
|  | ||||
| def get_spec(app: Application) -> APISpec: | ||||
| @ -45,13 +47,17 @@ def get_spec(app: Application) -> APISpec: | ||||
|     # components | ||||
|     spec.components.schema(Action.model_name(), Action.model_spec()) | ||||
|     spec.components.schema(BiS.model_name(), BiS.model_spec()) | ||||
|     spec.components.schema(BiSLink.model_name(), BiSLink.model_spec()) | ||||
|     spec.components.schema(Error.model_name(), Error.model_spec()) | ||||
|     spec.components.schema(Job.model_name(), Job.model_spec()) | ||||
|     spec.components.schema(Loot.model_name(), Loot.model_spec()) | ||||
|     spec.components.schema(Piece.model_name(), Piece.model_spec()) | ||||
|     spec.components.schema(Player.model_name(), Player.model_spec()) | ||||
|     spec.components.schema(PlayerEdit.model_name(), PlayerEdit.model_spec()) | ||||
|     spec.components.schema(PlayerId.model_name(), PlayerId.model_spec()) | ||||
|     spec.components.schema(PlayerIdWithCounters.model_name(), PlayerIdWithCounters.model_spec()) | ||||
|     spec.components.schema(Upgrade.model_name(), Upgrade.model_spec()) | ||||
|     spec.components.schema(User.model_name(), User.model_spec()) | ||||
|  | ||||
|     # default responses | ||||
|     spec.components.response('BadRequest', dict( | ||||
|  | ||||
| @ -7,6 +7,7 @@ | ||||
| # License: 3-clause BSD, see https://opensource.org/licenses/BSD-3-Clause | ||||
| # | ||||
| from aiohttp.web import Response | ||||
| from typing import Any, Dict, List, Optional, Type | ||||
|  | ||||
| from service.models.job import Job | ||||
| from service.models.piece import Piece | ||||
| @ -15,8 +16,92 @@ from service.models.player import PlayerId | ||||
| from service.api.utils import wrap_exception, wrap_invalid_param, wrap_json | ||||
| from service.api.views.common.bis_base import BiSBaseView | ||||
|  | ||||
| from .openapi import OpenApi | ||||
|  | ||||
| class BiSView(BiSBaseView): | ||||
|  | ||||
| class BiSView(BiSBaseView, OpenApi): | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_get_description(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'Get party players BiS items' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_get_parameters(cls: Type[OpenApi]) -> List[Dict[str, Any]]: | ||||
|         return [ | ||||
|             { | ||||
|                 'name': 'nick', | ||||
|                 'in': 'query', | ||||
|                 'description': 'player nick name to filter', | ||||
|                 'required': False, | ||||
|                 'type': 'string' | ||||
|             } | ||||
|         ] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_get_responses(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
|         return { | ||||
|             '200': {'content': {'application/json': { 'schema': { | ||||
|                 'type': 'array', | ||||
|                 'items': { | ||||
|                     'allOf': [{'$ref': cls.model_ref('Piece')}] | ||||
|                 }}}}} | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_get_summary(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'get party BiS items' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_get_tags(cls: Type[OpenApi]) -> List[str]: | ||||
|         return ['BiS'] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_description(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'Add new item to player BiS or remove existing' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_request_body(cls: Type[OpenApi], content_type: str) -> List[str]: | ||||
|         return ['Piece', 'PlayerEdit'] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_responses(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
|         return { | ||||
|             '200': {'content': {'application/json': {'schema':  {'$ref': cls.model_ref('Loot')}}}} | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_summary(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'edit BiS' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_tags(cls: Type[OpenApi]) -> List[str]: | ||||
|         return ['BiS'] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_consumes(cls: Type[OpenApi]) -> List[str]: | ||||
|         return ['application/json'] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_description(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'Generate new BiS set' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_request_body(cls: Type[OpenApi], content_type: str) -> List[str]: | ||||
|         return ['BiSLink'] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_responses(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
|         return { | ||||
|             '200': {'content': {'application/json': {'schema': {'$ref': cls.model_ref('BiS')}}}} | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_summary(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'update BiS' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_tags(cls: Type[OpenApi]) -> List[str]: | ||||
|         return ['BiS'] | ||||
|  | ||||
|     async def get(self) -> Response: | ||||
|         try: | ||||
| @ -34,7 +119,7 @@ class BiSView(BiSBaseView): | ||||
|         except Exception: | ||||
|             data = dict(await self.request.post()) | ||||
|  | ||||
|         required = ['action', 'is_tome', 'job', 'nick', 'piece'] | ||||
|         required = ['action', 'is_tome', 'job', 'name', 'nick'] | ||||
|         if any(param not in data for param in required): | ||||
|             return wrap_invalid_param(required, data) | ||||
|  | ||||
| @ -65,10 +150,10 @@ class BiSView(BiSBaseView): | ||||
|  | ||||
|         try: | ||||
|             player_id = PlayerId(Job[data['job']], data['nick']) | ||||
|             link = await self.bis_put(player_id, data['link']) | ||||
|             bis = await self.bis_put(player_id, data['link']) | ||||
|  | ||||
|         except Exception as e: | ||||
|             self.request.app.logger.exception('could not parse bis') | ||||
|             return wrap_exception(e, data) | ||||
|  | ||||
|         return wrap_json({'link': link}) | ||||
|         return wrap_json(bis) | ||||
| @ -7,12 +7,89 @@ | ||||
| # License: 3-clause BSD, see https://opensource.org/licenses/BSD-3-Clause | ||||
| # | ||||
| from aiohttp.web import Response | ||||
| from typing import Any, Dict, List, Optional, Type | ||||
|  | ||||
| from service.api.utils import wrap_exception, wrap_invalid_param, wrap_json | ||||
| from service.api.views.common.login_base import LoginBaseView | ||||
|  | ||||
| from .openapi import OpenApi | ||||
|  | ||||
| class LoginView(LoginBaseView): | ||||
|  | ||||
| class LoginView(LoginBaseView, OpenApi): | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_delete_description(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'Delete registered user' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_delete_parameters(cls: Type[OpenApi]) -> List[Dict[str, Any]]: | ||||
|         return [ | ||||
|             { | ||||
|                 'name': 'username', | ||||
|                 'in': 'path', | ||||
|                 'description': 'username to remove', | ||||
|                 'required': True, | ||||
|                 'type': 'string' | ||||
|             } | ||||
|         ] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_delete_responses(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
|         return { | ||||
|             '200': {'content': {'application/json': {'type': 'object'}}} | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_delete_summary(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'delete user' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_delete_tags(cls: Type[OpenApi]) -> List[str]: | ||||
|         return ['users'] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_description(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'Login as user' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_request_body(cls: Type[OpenApi], content_type: str) -> List[str]: | ||||
|         return ['User'] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_responses(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
|         return { | ||||
|             '200': {'content': {'application/json': {'type': 'object'}}} | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_summary(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'login' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_tags(cls: Type[OpenApi]) -> List[str]: | ||||
|         return ['users'] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_description(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'Create new user' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_request_body(cls: Type[OpenApi], content_type: str) -> List[str]: | ||||
|         return ['User'] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_responses(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
|         return { | ||||
|             '200': {'content': {'application/json': {'type': 'object'}}} | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_summary(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'create user' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_tags(cls: Type[OpenApi]) -> List[str]: | ||||
|         return ['users'] | ||||
|  | ||||
|     async def delete(self) -> Response: | ||||
|         username = self.request.match_info['username'] | ||||
|  | ||||
| @ -4,12 +4,37 @@ | ||||
| # License: 3-clause BSD, see https://opensource.org/licenses/BSD-3-Clause | ||||
| # | ||||
| from aiohttp.web import Response | ||||
| from typing import Any, Dict, List, Optional, Type | ||||
|  | ||||
| from service.api.utils import wrap_exception, wrap_json | ||||
| from service.api.views.common.login_base import LoginBaseView | ||||
|  | ||||
| from .openapi import OpenApi | ||||
|  | ||||
| class LogoutView(LoginBaseView): | ||||
|  | ||||
| class LogoutView(LoginBaseView, OpenApi): | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_description(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'Logout' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_request_body(cls: Type[OpenApi], content_type: str) -> List[str]: | ||||
|         return [] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_responses(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
|         return { | ||||
|             '200': {'content': {'application/json': {'type': 'object'}}} | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_summary(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'logout' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_tags(cls: Type[OpenApi]) -> List[str]: | ||||
|         return ['users'] | ||||
|  | ||||
|     async def post(self) -> Response: | ||||
|         try: | ||||
|  | ||||
| @ -7,6 +7,7 @@ | ||||
| # License: 3-clause BSD, see https://opensource.org/licenses/BSD-3-Clause | ||||
| # | ||||
| from aiohttp.web import Response | ||||
| from typing import Any, Dict, List, Optional, Type | ||||
|  | ||||
| from service.models.job import Job | ||||
| from service.models.piece import Piece | ||||
| @ -15,8 +16,92 @@ from service.models.player import PlayerId | ||||
| from service.api.utils import wrap_exception, wrap_invalid_param, wrap_json | ||||
| from service.api.views.common.loot_base import LootBaseView | ||||
|  | ||||
| from .openapi import OpenApi | ||||
|  | ||||
| class LootView(LootBaseView): | ||||
|  | ||||
| class LootView(LootBaseView, OpenApi): | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_get_description(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'Get party players loot' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_get_parameters(cls: Type[OpenApi]) -> List[Dict[str, Any]]: | ||||
|         return [ | ||||
|             { | ||||
|                 'name': 'nick', | ||||
|                 'in': 'query', | ||||
|                 'description': 'player nick name to filter', | ||||
|                 'required': False, | ||||
|                 'type': 'string' | ||||
|             } | ||||
|         ] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_get_responses(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
|         return { | ||||
|             '200': {'content': {'application/json': {'schema': { | ||||
|                 'type': 'array', | ||||
|                 'items': { | ||||
|                     'allOf': [{'$ref': cls.model_ref('Piece')}] | ||||
|                 }}}}} | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_get_summary(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'get party loot' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_get_tags(cls: Type[OpenApi]) -> List[str]: | ||||
|         return ['loot'] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_description(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'Add new loot item or remove existing' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_request_body(cls: Type[OpenApi], content_type: str) -> List[str]: | ||||
|         return ['Piece', 'PlayerEdit'] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_responses(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
|         return { | ||||
|             '200': {'content': {'application/json': {'schema': {'$ref': cls.model_ref('Loot')}}}} | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_summary(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'edit loot' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_tags(cls: Type[OpenApi]) -> List[str]: | ||||
|         return ['loot'] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_description(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'Suggest loot to party member' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_request_body(cls: Type[OpenApi], content_type: str) -> List[str]: | ||||
|         return ['Piece'] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_responses(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
|         return { | ||||
|             '200': {'content': {'application/json': {'schema': { | ||||
|                 'type': 'array', | ||||
|                 'items': { | ||||
|                     'allOf': [{'$ref': cls.model_ref('PlayerIdWithCounters')}] | ||||
|                 }}}}} | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_summary(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return 'suggest loot' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_tags(cls: Type[OpenApi]) -> List[str]: | ||||
|         return ['loot'] | ||||
|  | ||||
|     async def get(self) -> Response: | ||||
|         try: | ||||
| @ -34,7 +119,7 @@ class LootView(LootBaseView): | ||||
|         except Exception: | ||||
|             data = dict(await self.request.post()) | ||||
|  | ||||
|         required = ['action', 'is_tome', 'job', 'nick', 'piece'] | ||||
|         required = ['action', 'is_tome', 'job', 'name', 'nick'] | ||||
|         if any(param not in data for param in required): | ||||
|             return wrap_invalid_param(required, data) | ||||
|  | ||||
| @ -59,7 +144,7 @@ class LootView(LootBaseView): | ||||
|         except Exception: | ||||
|             data = dict(await self.request.post()) | ||||
|  | ||||
|         required = ['is_tome', 'piece'] | ||||
|         required = ['is_tome', 'name'] | ||||
|         if any(param not in data for param in required): | ||||
|             return wrap_invalid_param(required, data) | ||||
|  | ||||
|  | ||||
| @ -16,9 +16,38 @@ from service.models.serializable import Serializable | ||||
| class OpenApi(Serializable): | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_delete_spec(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
|     def endpoint_delete_description(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return None | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_delete_parameters(cls: Type[OpenApi]) -> List[Dict[str, Any]]: | ||||
|         return [] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_delete_responses(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
|         return {} | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_delete_summary(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return None | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_delete_tags(cls: Type[OpenApi]) -> List[str]: | ||||
|         return [] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_delete_spec(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
|         description = cls.endpoint_delete_description() | ||||
|         if description is None: | ||||
|             return {} | ||||
|         return { | ||||
|             'description': description, | ||||
|             'parameters': cls.endpoint_delete_parameters(), | ||||
|             'responses': cls.endpoint_with_default_responses(cls.endpoint_delete_responses()), | ||||
|             'summary': cls.endpoint_delete_summary(), | ||||
|             'tags': cls.endpoint_delete_tags() | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_get_description(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return None | ||||
| @ -61,8 +90,8 @@ class OpenApi(Serializable): | ||||
|         return None | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_request_body(cls: Type[OpenApi], content_type: str) -> str: | ||||
|         return '' | ||||
|     def endpoint_post_request_body(cls: Type[OpenApi], content_type: str) -> List[str]: | ||||
|         return [] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_responses(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
| @ -87,7 +116,10 @@ class OpenApi(Serializable): | ||||
|             'requestBody': { | ||||
|                 'content': { | ||||
|                     content_type: { | ||||
|                         'schema': {'$ref': cls.model_ref(cls.endpoint_post_request_body(content_type))} | ||||
|                         'schema': {'allOf': [ | ||||
|                             {'$ref': cls.model_ref(ref)} | ||||
|                             for ref in cls.endpoint_post_request_body(content_type) | ||||
|                         ]} | ||||
|                     } | ||||
|                     for content_type in cls.endpoint_post_consumes() | ||||
|                 } | ||||
| @ -97,6 +129,54 @@ class OpenApi(Serializable): | ||||
|             'tags': cls.endpoint_post_tags() | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_consumes(cls: Type[OpenApi]) -> List[str]: | ||||
|         return ['application/json'] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_description(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return None | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_request_body(cls: Type[OpenApi], content_type: str) -> List[str]: | ||||
|         return [] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_responses(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
|         return {} | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_summary(cls: Type[OpenApi]) -> Optional[str]: | ||||
|         return None | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_tags(cls: Type[OpenApi]) -> List[str]: | ||||
|         return [] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_put_spec(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
|         description = cls.endpoint_put_description() | ||||
|         if description is None: | ||||
|             return {} | ||||
|         return { | ||||
|             'consumes': cls.endpoint_put_consumes(), | ||||
|             'description': description, | ||||
|             'requestBody': { | ||||
|                 'content': { | ||||
|                     content_type: { | ||||
|                         'schema': {'allOf': [ | ||||
|                             {'$ref': cls.model_ref(ref)} | ||||
|                             for ref in cls.endpoint_put_request_body(content_type) | ||||
|                         ]} | ||||
|                     } | ||||
|                     for content_type in cls.endpoint_put_consumes() | ||||
|                 } | ||||
|             }, | ||||
|             'responses': cls.endpoint_with_default_responses(cls.endpoint_put_responses()), | ||||
|             'summary': cls.endpoint_put_summary(), | ||||
|             'tags': cls.endpoint_put_tags() | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_spec(cls: Type[OpenApi], operations: List[str]) -> Dict[str, Any]: | ||||
|         return { | ||||
|  | ||||
| @ -54,8 +54,8 @@ class PlayerView(PlayerBaseView, OpenApi): | ||||
|         return 'Create new party player or remove existing' | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_request_body(cls: Type[OpenApi], content_type: str) -> str: | ||||
|         return 'PlayerEdit' | ||||
|     def endpoint_post_request_body(cls: Type[OpenApi], content_type: str) -> List[str]: | ||||
|         return ['PlayerEdit'] | ||||
|  | ||||
|     @classmethod | ||||
|     def endpoint_post_responses(cls: Type[OpenApi]) -> Dict[str, Any]: | ||||
|  | ||||
| @ -10,6 +10,7 @@ from aiohttp.web import View | ||||
| from typing import List, Optional | ||||
|  | ||||
| from service.core.ariyala_parser import AriyalaParser | ||||
| from service.models.bis import BiS | ||||
| from service.models.piece import Piece | ||||
| from service.models.player import PlayerId | ||||
|  | ||||
| @ -35,13 +36,13 @@ class BiSBaseView(View): | ||||
|             return await self.bis_remove(player_id, piece) | ||||
|         return None | ||||
|  | ||||
|     async def bis_put(self, player_id: PlayerId, link: str) -> str: | ||||
|     async def bis_put(self, player_id: PlayerId, link: str) -> BiS: | ||||
|         parser = AriyalaParser(self.request.app['config']) | ||||
|         items = parser.get(link, player_id.job.name) | ||||
|         for piece in items: | ||||
|             await self.request.app['party'].set_item_bis(player_id, piece) | ||||
|         await self.request.app['party'].set_bis_link(player_id, link) | ||||
|         return link | ||||
|         return self.request.app['party'].players[player_id].bis | ||||
|  | ||||
|     async def bis_remove(self, player_id: PlayerId, piece: Piece) -> Piece: | ||||
|         await self.request.app['party'].remove_item_bis(player_id, piece) | ||||
|  | ||||
| @ -11,11 +11,42 @@ import itertools | ||||
| from dataclasses import dataclass | ||||
| from typing import Any, Dict, List, Optional, Type, Union | ||||
|  | ||||
| from .job import Job | ||||
| from .piece import Piece | ||||
| from .serializable import Serializable | ||||
| from .upgrade import Upgrade | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class BiSLink(Serializable): | ||||
|     nick: str | ||||
|     job: Job | ||||
|     link: str | ||||
|  | ||||
|     @classmethod | ||||
|     def model_properties(cls: Type[Serializable]) -> Dict[str, Any]: | ||||
|         return { | ||||
|             'job': { | ||||
|                 'description': 'player job name', | ||||
|                 '$ref': cls.model_ref('Job') | ||||
|             }, | ||||
|             'link': { | ||||
|                 'description': 'link to BiS set', | ||||
|                 'example': 'https://ffxiv.ariyala.com/19V5R', | ||||
|                 'type': 'string' | ||||
|             }, | ||||
|             'nick': { | ||||
|                 'description': 'player nick name', | ||||
|                 'example': 'Siuan Sanche', | ||||
|                 'type': 'string' | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def model_required(cls: Type[Serializable]) -> List[str]: | ||||
|         return ['job', 'link', 'nick'] | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class BiS(Serializable): | ||||
|     weapon: Optional[Piece] = None | ||||
|  | ||||
| @ -7,13 +7,31 @@ | ||||
| # License: 3-clause BSD, see https://opensource.org/licenses/BSD-3-Clause | ||||
| # | ||||
| from dataclasses import dataclass | ||||
| from typing import Union | ||||
| from typing import Any, Dict, List, Type, Union | ||||
|  | ||||
| from .piece import Piece | ||||
| from .serializable import Serializable | ||||
| from .upgrade import Upgrade | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class Loot: | ||||
| class Loot(Serializable): | ||||
|     player_id: int | ||||
|     piece: Union[Piece, Upgrade] | ||||
|  | ||||
|     @classmethod | ||||
|     def model_properties(cls: Type[Serializable]) -> Dict[str, Any]: | ||||
|         return { | ||||
|             'piece': { | ||||
|                 'description': 'player piece', | ||||
|                 '$ref': cls.model_ref('Piece') | ||||
|             }, | ||||
|             'player_id': { | ||||
|                 'description': 'player identifier', | ||||
|                 '$ref': cls.model_ref('PlayerId') | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def model_required(cls: Type[Serializable]) -> List[str]: | ||||
|         return ['piece', 'player_id'] | ||||
| @ -86,7 +86,6 @@ class Piece(Serializable): | ||||
|             }, | ||||
|             'name': { | ||||
|                 'description': 'piece name', | ||||
|                 'required': True, | ||||
|                 'type': 'string' | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @ -66,6 +66,48 @@ class PlayerIdWithCounters(PlayerId): | ||||
|     loot_count_total: int | ||||
|     bis_count_total: int | ||||
|  | ||||
|     @classmethod | ||||
|     def model_properties(cls: Type[Serializable]) -> Dict[str, Any]: | ||||
|         return { | ||||
|             'bis_count_total': { | ||||
|                 'description': 'total savage pieces in BiS', | ||||
|                 'type': 'integer' | ||||
|             }, | ||||
|             'is_required': { | ||||
|                 'description': 'is item required by BiS or not', | ||||
|                 'type': 'boolean' | ||||
|             }, | ||||
|             'job': { | ||||
|                 'description': 'player job name', | ||||
|                 '$ref': cls.model_ref('Job') | ||||
|             }, | ||||
|             'loot_count': { | ||||
|                 'description': 'count of this item which was already looted', | ||||
|                 'type': 'integer' | ||||
|             }, | ||||
|             'loot_count_bis': { | ||||
|                 'description': 'count of BiS items which were already looted', | ||||
|                 'type': 'integer' | ||||
|             }, | ||||
|             'loot_count_total': { | ||||
|                 'description': 'total count of items which were looted', | ||||
|                 'type': 'integer' | ||||
|             }, | ||||
|             'nick': { | ||||
|                 'description': 'player nick name', | ||||
|                 'type': 'string' | ||||
|             }, | ||||
|             'priority': { | ||||
|                 'description': 'player loot priority', | ||||
|                 'type': 'integer' | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def model_required(cls: Type[Serializable]) -> List[str]: | ||||
|         return ['bis_count_total', 'is_required', 'job', 'loot_count', | ||||
|                 'loot_count_bis', 'loot_count_total', 'nick', 'priority'] | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class Player(Serializable): | ||||
|  | ||||
| @ -7,10 +7,36 @@ | ||||
| # License: 3-clause BSD, see https://opensource.org/licenses/BSD-3-Clause | ||||
| # | ||||
| from dataclasses import dataclass | ||||
| from typing import Any, Dict, List, Type | ||||
|  | ||||
| from .serializable import Serializable | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class User: | ||||
| class User(Serializable): | ||||
|     username: str | ||||
|     password: str | ||||
|     permission: str | ||||
|  | ||||
|     @classmethod | ||||
|     def model_properties(cls: Type[Serializable]) -> Dict[str, Any]: | ||||
|         return { | ||||
|             'password': { | ||||
|                 'description': 'user password', | ||||
|                 'type': 'string' | ||||
|             }, | ||||
|             'permission': { | ||||
|                 'default': 'get', | ||||
|                 'description': 'user action permissions', | ||||
|                 'type': 'string', | ||||
|                 'enum': ['admin', 'get', 'post'] | ||||
|             }, | ||||
|             'username': { | ||||
|                 'description': 'user name', | ||||
|                 'type': 'string' | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     @classmethod | ||||
|     def model_required(cls: Type[Serializable]) -> List[str]: | ||||
|         return ['password', 'username'] | ||||
		Reference in New Issue
	
	Block a user