Skip to content

Commit

Permalink
Add new statistics and rating endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
AbstractUmbra committed Dec 27, 2021
1 parent 833f1a9 commit 49cb1f0
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 5 deletions.
3 changes: 3 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ Manga
.. autoclass:: MangaRelation
:members:

.. autoclass:: MangaStatistics
:members:

Query
~~~~~~~~
.. currentmodule:: hondana.query
Expand Down
9 changes: 9 additions & 0 deletions docs/types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,15 @@ Scanlator Group
.. autoclass:: GetMultiScanlationGroupResponse


Statistics
----------
.. autoclass:: StatisticsRatingResponse

.. autoclass:: StatisticsResponse

.. autoclass:: GetStatisticsResponse


Tags
----
.. autoclass:: TagResponse
Expand Down
68 changes: 67 additions & 1 deletion hondana/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
from .custom_list import CustomList
from .http import HTTPClient
from .legacy import LegacyItem
from .manga import Manga, MangaRelation
from .manga import Manga, MangaRelation, MangaStatistics
from .query import (
ArtistIncludes,
AuthorIncludes,
Expand Down Expand Up @@ -3095,3 +3095,69 @@ async def create_report(
The specified report UUID or object UUID does not exist.
"""
await self._http._create_report(report_category=report_category, reason=reason, object_id=object_id, details=details)

@require_authentication
async def set_manga_rating(self, manga_id: str, /, *, rating: int) -> None:
"""|coro|
This method will set your rating on the passed manga.
This method **overwrites** your previous set rating, if any.
Parameters
-----------
manga_id: :class:`str`
The manga you are setting the rating for.
rating: :class:`int`
The rating value, between 0 and 10.
Raises
-------
:exc:`Forbidden`
The request returned a response due to authentication failure.
:exc:`NotFound`
The specified manga UUID was not found or does not exist.
"""
await self._http._set_manga_rating(manga_id, rating=rating)

@require_authentication
async def delete_manga_rating(self, manga_id: str, /) -> None:
"""|coro|
This method will delete your set rating on the passed manga.
Parameters
-----------
manga_id: :class:`str`
The manga you wish to delete the rating for.
Raises
-------
:exc:`Forbidden`
The request returned a response due to authentication failure.
:exc:`NotFound`
The specified manga UUID was not found or does not exist.
"""
await self._http._delete_manga_rating(manga_id)

@require_authentication
async def get_manga_statistics(self, manga_ids: list[str], /) -> list[MangaStatistics]:
"""|coro|
This method will return the statistics for the passed manga.
Parameters
-----------
manga_ids: List[:class:`str`]
The list of manga ids to fetch the statistics for.
Returns
---------
List[:class:`~hondana.MangaStatistics`]
"""
data = await self._http._get_manga_statistics(manga_ids)

fmt: list[MangaStatistics] = []
for id_, stats in data["statistics"].items():
fmt.append(MangaStatistics(self._http, id_, stats))

return fmt
20 changes: 20 additions & 0 deletions hondana/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
manga,
report,
scanlator_group,
statistics,
user,
)
from .types.auth import CheckPayload
Expand Down Expand Up @@ -1957,3 +1958,22 @@ def _create_report(
query: dict[str, Any] = {"category": report_category, "reason": reason, "objectId": object_id, "details": details}

return self.request(route, json=query)

def _set_manga_rating(self, manga_id: str, /, *, rating: int) -> Response[Literal["ok", "error"]]:
route = Route("POST", "/rating/{manga_id}", manga_id=manga_id)

query: dict[str, Any] = {"rating": rating}

return self.request(route, json=query)

def _delete_manga_rating(self, manga_id: str, /) -> Response[Literal["ok", "error"]]:
route = Route("DELETE", "/rating/{manga_id}", manga_id=manga_id)

return self.request(route)

def _get_manga_statistics(self, manga_ids: list[str], /) -> Response[statistics.GetStatisticsResponse]:
route = Route("GET", "/statistics/manga")

query: dict[str, Any] = {"manga": manga_ids}

return self.request(route, params=query)
77 changes: 73 additions & 4 deletions hondana/manga.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,10 @@
from .types.author import AuthorResponse
from .types.common import ContentRating, LanguageCode, LocalisedString
from .types.relationship import RelationshipResponse
from .types.statistics import StatisticsResponse


__all__ = (
"Manga",
"MangaRelation",
)
__all__ = ("Manga", "MangaRelation", "MangaStatistics")


class Manga:
Expand Down Expand Up @@ -1206,6 +1204,42 @@ async def delete_relation(self, relation_id: str, /) -> None:
"""
await self._http._delete_manga_relation(self.id, relation_id)

@require_authentication
async def set_manga_rating(self, *, rating: int) -> None:
"""|coro|
This method will set your rating on the manga.
This method **overwrites** your previous set rating, if any.
Parameters
-----------
rating: :class:`int`
The rating value, between 0 and 10.
Raises
-------
:exc:`Forbidden`
The request returned a response due to authentication failure.
:exc:`NotFound`
The specified manga UUID was not found or does not exist.
"""
await self._http._set_manga_rating(self.id, rating=rating)

@require_authentication
async def delete_manga_rating(self) -> None:
"""|coro|
This method will delete your set rating on the manga.
Raises
-------
:exc:`Forbidden`
The request returned a response due to authentication failure.
:exc:`NotFound`
The specified manga UUID was not found or does not exist.
"""
await self._http._delete_manga_rating(self.id)


class MangaRelation:
"""A class representing a MangaRelation returned from the MangaDex API.
Expand Down Expand Up @@ -1251,3 +1285,38 @@ def __init__(self, http: HTTPClient, parent_id: str, payload: manga.MangaRelatio
self.id: str = self._data["id"]
self.version: int = self._attributes["version"]
self.relation_type: manga.MangaRelationType = self._attributes["relation"]


class MangaStatistics:
"""
A small object to house manga statistics.
Attributes
-----------
parent_id: :class:`str`
The manga these statistics belong to.
average: :class:`float`
The average mean score of the manga.
distribution: List[:class:`int`]
The scoring distribution of the manga.
"""

__slots__ = (
"_http",
"_data",
"_rating",
"parent_id",
"average",
"distribution",
)

def __init__(self, http: HTTPClient, parent_id: str, payload: StatisticsResponse) -> None:
self._http = http
self._data = payload
self._rating = payload["rating"]
self.parent_id: str = parent_id
self.average: float = self._rating["average"]
self.distribution: list[int] = self._rating["distribution"]

def __repr__(self) -> str:
return f"<MangaStatistics for={self.parent_id}>"
1 change: 1 addition & 0 deletions hondana/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from .relationship import *
from .report import *
from .scanlator_group import *
from .statistics import *
from .tags import *
from .token import *
from .user import *
64 changes: 64 additions & 0 deletions hondana/types/statistics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""
The MIT License (MIT)
Copyright (c) 2021-Present AbstractUmbra
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
"""

from __future__ import annotations

from typing import Literal, TypedDict


__all__ = (
"StatisticsRatingResponse",
"StatisticsResponse",
"GetStatisticsResponse",
)


class StatisticsRatingResponse(TypedDict):
"""
average: :class:`float`
distribution: List[:class:`int`]
"""

average: float
distribution: list[int]


class StatisticsResponse(TypedDict):
"""
rating: :class:`~hondana.types.StatisticsRatingResponse`
"""

rating: StatisticsRatingResponse


class GetStatisticsResponse(TypedDict):
"""
result: Literal[``"ok"``]
statistics: Dict[:class:`str`, :class:`~hondana.types.StatisticsResponse`]
"""

result: Literal["ok"]
statistics: dict[str, StatisticsResponse]

0 comments on commit 49cb1f0

Please sign in to comment.