|
@@ -1,15 +1,19 @@
|
|
|
|
|
+import logging
|
|
|
from collections import OrderedDict
|
|
from collections import OrderedDict
|
|
|
from dataclasses import dataclass
|
|
from dataclasses import dataclass
|
|
|
-import logging
|
|
|
|
|
from datetime import datetime
|
|
from datetime import datetime
|
|
|
from typing import Optional
|
|
from typing import Optional
|
|
|
from uuid import uuid4
|
|
from uuid import uuid4
|
|
|
|
|
|
|
|
import requests
|
|
import requests
|
|
|
|
|
+from books.constants import READCOMICSONLINE_URL
|
|
|
from books.openlibrary import (
|
|
from books.openlibrary import (
|
|
|
lookup_author_from_openlibrary,
|
|
lookup_author_from_openlibrary,
|
|
|
lookup_book_from_openlibrary,
|
|
lookup_book_from_openlibrary,
|
|
|
)
|
|
)
|
|
|
|
|
+from books.sources.google import lookup_book_from_google
|
|
|
|
|
+from books.sources.semantic import lookup_paper_from_semantic
|
|
|
|
|
+from books.utils import get_comic_issue_url
|
|
|
from django.conf import settings
|
|
from django.conf import settings
|
|
|
from django.contrib.auth import get_user_model
|
|
from django.contrib.auth import get_user_model
|
|
|
from django.core.files.base import ContentFile
|
|
from django.core.files.base import ContentFile
|
|
@@ -18,27 +22,25 @@ from django.urls import reverse
|
|
|
from django_extensions.db.models import TimeStampedModel
|
|
from django_extensions.db.models import TimeStampedModel
|
|
|
from imagekit.models import ImageSpecField
|
|
from imagekit.models import ImageSpecField
|
|
|
from imagekit.processors import ResizeToFit
|
|
from imagekit.processors import ResizeToFit
|
|
|
|
|
+from scrobbles.dataclasses import BaseLogData, LongPlayLogData
|
|
|
from scrobbles.mixins import (
|
|
from scrobbles.mixins import (
|
|
|
LongPlayScrobblableMixin,
|
|
LongPlayScrobblableMixin,
|
|
|
ObjectWithGenres,
|
|
ObjectWithGenres,
|
|
|
ScrobblableConstants,
|
|
ScrobblableConstants,
|
|
|
)
|
|
)
|
|
|
-from scrobbles.utils import get_scrobbles_for_media
|
|
|
|
|
|
|
+from scrobbles.utils import get_scrobbles_for_media, next_url_if_exists
|
|
|
from taggit.managers import TaggableManager
|
|
from taggit.managers import TaggableManager
|
|
|
from thefuzz import fuzz
|
|
from thefuzz import fuzz
|
|
|
-from vrobbler.apps.books.sources.comicvine import (
|
|
|
|
|
- ComicVineClient,
|
|
|
|
|
- lookup_comic_from_comicvine,
|
|
|
|
|
-)
|
|
|
|
|
|
|
|
|
|
from vrobbler.apps.books.locg import (
|
|
from vrobbler.apps.books.locg import (
|
|
|
lookup_comic_by_locg_slug,
|
|
lookup_comic_by_locg_slug,
|
|
|
lookup_comic_from_locg,
|
|
lookup_comic_from_locg,
|
|
|
lookup_comic_writer_by_locg_slug,
|
|
lookup_comic_writer_by_locg_slug,
|
|
|
)
|
|
)
|
|
|
-from books.sources.google import lookup_book_from_google
|
|
|
|
|
-from books.sources.semantic import lookup_paper_from_semantic
|
|
|
|
|
-from scrobbles.dataclasses import BaseLogData, LongPlayLogData
|
|
|
|
|
|
|
+from vrobbler.apps.books.sources.comicvine import (
|
|
|
|
|
+ ComicVineClient,
|
|
|
|
|
+ lookup_comic_from_comicvine,
|
|
|
|
|
+)
|
|
|
|
|
|
|
|
COMICVINE_API_KEY = getattr(settings, "COMICVINE_API_KEY", "")
|
|
COMICVINE_API_KEY = getattr(settings, "COMICVINE_API_KEY", "")
|
|
|
|
|
|
|
@@ -63,7 +65,6 @@ class BookLogData(BaseLogData, LongPlayLogData):
|
|
|
page_start: Optional[int] = None
|
|
page_start: Optional[int] = None
|
|
|
page_end: Optional[int] = None
|
|
page_end: Optional[int] = None
|
|
|
resume_url: Optional[str] = None
|
|
resume_url: Optional[str] = None
|
|
|
- restart_url: Optional[str] = None
|
|
|
|
|
|
|
|
|
|
_excluded_fields = {"koreader_hash", "page_data"}
|
|
_excluded_fields = {"koreader_hash", "page_data"}
|
|
|
|
|
|
|
@@ -150,6 +151,8 @@ class Book(LongPlayScrobblableMixin):
|
|
|
first_sentence = models.TextField(**BNULL)
|
|
first_sentence = models.TextField(**BNULL)
|
|
|
# ComicVine
|
|
# ComicVine
|
|
|
comicvine_id = models.CharField(max_length=255, **BNULL)
|
|
comicvine_id = models.CharField(max_length=255, **BNULL)
|
|
|
|
|
+ readcomics_url = models.CharField(max_length=255, **BNULL)
|
|
|
|
|
+ next_readcomics_url = models.CharField(max_length=255, **BNULL)
|
|
|
issue_number = models.IntegerField(max_length=5, **BNULL)
|
|
issue_number = models.IntegerField(max_length=5, **BNULL)
|
|
|
volume_number = models.IntegerField(max_length=5, **BNULL)
|
|
volume_number = models.IntegerField(max_length=5, **BNULL)
|
|
|
# OpenLibrary
|
|
# OpenLibrary
|
|
@@ -171,7 +174,11 @@ class Book(LongPlayScrobblableMixin):
|
|
|
|
|
|
|
|
genre = TaggableManager(through=ObjectWithGenres)
|
|
genre = TaggableManager(through=ObjectWithGenres)
|
|
|
|
|
|
|
|
- def __str__(self):
|
|
|
|
|
|
|
+ def __str__(self) -> str:
|
|
|
|
|
+ if self.issue_number and "Issue" not in str(self.title):
|
|
|
|
|
+ return f"{self.title} - Issue {self.issue_number}"
|
|
|
|
|
+ if self.volume_number and "Volume" not in str(self.title):
|
|
|
|
|
+ return f"{self.title} - Volume {self.volume_number}"
|
|
|
return f"{self.title}"
|
|
return f"{self.title}"
|
|
|
|
|
|
|
|
@property
|
|
@property
|
|
@@ -234,7 +241,7 @@ class Book(LongPlayScrobblableMixin):
|
|
|
|
|
|
|
|
@classmethod
|
|
@classmethod
|
|
|
def find_or_create(
|
|
def find_or_create(
|
|
|
- cls, title: str, enrich: bool = False, commit: bool = True
|
|
|
|
|
|
|
+ cls, title: str, url: str = "", enrich: bool = False, commit: bool = True
|
|
|
):
|
|
):
|
|
|
"""Given a title, get a Book instance.
|
|
"""Given a title, get a Book instance.
|
|
|
|
|
|
|
@@ -258,9 +265,17 @@ class Book(LongPlayScrobblableMixin):
|
|
|
)
|
|
)
|
|
|
return book
|
|
return book
|
|
|
|
|
|
|
|
- book_dict = lookup_book_from_google(title)
|
|
|
|
|
- if not book_dict or not book_dict.get("isbn_10"):
|
|
|
|
|
|
|
+ book_dict = None
|
|
|
|
|
+ if READCOMICSONLINE_URL in url:
|
|
|
book_dict = lookup_comic_from_comicvine(title)
|
|
book_dict = lookup_comic_from_comicvine(title)
|
|
|
|
|
+ book_dict["readcomics_url"] = get_comic_issue_url(url)
|
|
|
|
|
+ book_dict["next_readcomics_url"] = next_url_if_exists(book_dict["readcomics_url"])
|
|
|
|
|
+
|
|
|
|
|
+ if not book_dict:
|
|
|
|
|
+ book_dict = lookup_book_from_google(title)
|
|
|
|
|
+
|
|
|
|
|
+ if not book_dict:
|
|
|
|
|
+ logger.warning("No book found in any source, using data as is", extra={"title": title})
|
|
|
|
|
|
|
|
author_list = []
|
|
author_list = []
|
|
|
authors = book_dict.pop("authors", [])
|
|
authors = book_dict.pop("authors", [])
|