Skip to content

Commit

Permalink
fix: add none checking on mangadex chapter listing
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexandreSenpai committed Nov 11, 2024
1 parent d133358 commit f5906b4
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 17 deletions.
16 changes: 10 additions & 6 deletions enma/domain/entities/manga.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,23 @@ def add_page(self, page: Image) -> None:
self.pages_count += 1

@dataclass
class Tag:
name: Union[Literal["character"],
class Unit:
name: str

@dataclass
class Tag(Unit):
type: Union[Literal["character"],
Literal["related"],
Literal["category"]]
id: Union[int, str] = field(default=0)

@dataclass
class Author(Tag):
name: str
class Author(Unit):
id: Union[int, str] = field(default=0)

@dataclass
class Genre(Tag):
name: str
class Genre(Unit):
id: Union[int, str] = field(default=0)

class ILanguage(TypedDict):
ja: Literal['japanese']
Expand Down
6 changes: 3 additions & 3 deletions enma/infra/adapters/repositories/mangadex.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,13 +229,13 @@ def __list_chapters(self, manga_id: str) -> list[tuple[int, str]]:

data: IVolumesResponse = response.json()

chapters = []
for volume in data.get('volumes', []):
chapters = list()
for volume in data.get('volumes', dict()):
volume = data.get('volumes').get(volume)

if volume is None: continue

volume_chapters = volume.get('chapters')
volume_chapters = volume.get('chapters', dict())

for volume_key in volume_chapters:
current_vol = volume_chapters.get(volume_key)
Expand Down
60 changes: 52 additions & 8 deletions enma/infra/adapters/repositories/nhentai.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@
from datetime import datetime, timezone
from enum import Enum
import os
from typing import Any, Literal, Optional, Union, cast
from typing import Any, List, Literal, Optional, Union, cast
from urllib.parse import urljoin, urlparse
from pydantic import BaseModel, field_validator

import requests
from bs4 import BeautifulSoup, Tag

from enma.application.core.handlers.error import (ExceedRetryCount, Forbidden, InvalidConfig, InvalidRequest,
NhentaiSourceWithoutConfig, NotFound, Unknown)
NotFound, Unknown)
from enma.application.core.interfaces.manga_repository import IMangaRepository
from enma.application.core.utils.logger import logger
from enma.domain.entities.author_page import AuthorPage
from enma.domain.entities.manga import (MIME, Chapter, Genre, Author, Image, Manga, SymbolicLink,
Title)
Title, Tag as EnmaTag)
from enma.domain.entities.search_result import Pagination, SearchResult, Thumb
from enma.infra.core.interfaces.nhentai_response import NHentaiImage, NHentaiResponse
from enma.infra.core.interfaces.nhentai_response import NHentaiImage, NHentaiResponse, Tag as NHentaiResponseTag
from enma.infra.core.utils.cache import Cache
from enma._version import __version__

Expand All @@ -47,6 +47,14 @@ class Sort(__StrEnum):
ALL_TIME = 'popular'
RECENT = None

TagType = Union[Literal["language"],
Literal["parody"],
Literal["character"],
Literal["group"],
Literal["artist"],
Literal["tag"],
Literal["category"]]

class NHentai(IMangaRepository):
"""
Repository class for interacting with the nhentai API.
Expand Down Expand Up @@ -157,6 +165,11 @@ def __create_chapter(self,
width=page.get('w'),
height=page.get('h')))
return chapter

def __get_tag_by_type(self,
type: TagType,
tags: List[NHentaiResponseTag]) -> List[NHentaiResponseTag]:
return list(filter(lambda tag: tag.get('type') == type, tags))

@Cache(max_age_seconds=int(os.getenv('ENMA_CACHING_GET_TTL_IN_SECONDS', 300)),
max_size=20).cache
Expand All @@ -170,16 +183,46 @@ def get(self,
doujin: NHentaiResponse = response.json()
media_id = doujin.get('media_id')

nhentai_tags = doujin.get('tags')

chapter = self.__create_chapter(url=url,
with_symbolic_links=with_symbolic_links,
media_id=media_id,
pages=doujin.get('images').get('pages'))

language = [tag.get('name') for tag in doujin.get('tags') if tag.get('type') == 'language']
language = [tag.get('name')
for tag in self.__get_tag_by_type(type='language',
tags=nhentai_tags)]

authors = [Author(id=tag.get('id'),
name=tag.get('name')) for tag in doujin.get('tags') if tag.get('type') == 'artist']
genres = [Genre(id=genre.get('id'),
name=genre.get('name')) for genre in doujin.get('tags') if genre.get('type') == 'tag']
name=tag.get('name'))
for tag in self.__get_tag_by_type(type='artist',
tags=nhentai_tags)]

genres = [Genre(id=tag.get('id'),
name=tag.get('name'))
for tag in self.__get_tag_by_type(type='tag',
tags=nhentai_tags)]

characters = [EnmaTag(type='character',
name=tag.get('name'),
id=tag.get('id'))
for tag in self.__get_tag_by_type(type='character',
tags=nhentai_tags)]

related = [EnmaTag(type='related',
name=tag.get('name'),
id=tag.get('id'))
for tag in self.__get_tag_by_type(type='parody',
tags=nhentai_tags)]

category = [EnmaTag(type='category',
name=tag.get('name'),
id=tag.get('id'))
for tag in self.__get_tag_by_type(type='category',
tags=nhentai_tags)]

tags = [*characters, *related, *category]

thumbnail_mime = MIME[doujin.get("images").get("thumbnail").get("t").upper()]
thumbnail = Image(uri=self.__make_page_uri(type='thumbnail',
Expand Down Expand Up @@ -208,6 +251,7 @@ def get(self,
authors=authors,
genres=genres,
thumbnail=thumbnail,
tags=tags,
cover=cover,
chapters=[chapter])

Expand Down
32 changes: 32 additions & 0 deletions tests/test_nhentai_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,36 @@ def test_make_a_request_successfully(self, request_mock: MagicMock):
'add': 'header'},
params={'new': 'parameter'},
cookies={'cf_clearance': 'mocked'})

def test_should_filter_tags_correctly(self):
TAGS = [
{
"id": 33172,
"type": "category",
"name": "doujinshi",
"url": "/category/doujinshi/",
"count": 228729
},
{
"id": 29859,
"type": "tag",
"name": "b",
"url": "/tag/b/",
"count": 37321
},
{
"id": 1,
"type": "tag",
"name": "a",
"url": "/tag/a/",
"count": 1
}
]

characters = self.sut._NHentai__get_tag_by_type(type='category', tags=TAGS) # type: ignore
tags = self.sut._NHentai__get_tag_by_type(type='tag', tags=TAGS) # type: ignore
assert len(characters) == 1
assert len(tags) == 2

def test_making_page_uri(self):
page = self.sut._NHentai__make_page_uri(type='page', media_id='1234', mime=MIME.J, page_number=1) # type: ignore
Expand Down Expand Up @@ -130,6 +160,8 @@ def test_success_doujin_retrieve(self, sut_mock: MagicMock):

for chapter in res.chapters:
assert isinstance(chapter, Chapter)

assert len(res.tags) != 0

@patch('requests.get')
def test_must_return_other_titles_as_none_if_doesnt_exists(self, mock_method: MagicMock):
Expand Down

0 comments on commit f5906b4

Please sign in to comment.