[books] Add papers as a data model

This commit is contained in:
2025-02-20 23:07:56 -05:00
parent e2b0decd83
commit 9e3f714c61
11 changed files with 944 additions and 548 deletions

View File

@ -36,6 +36,7 @@ from vrobbler.apps.books.locg import (
lookup_comic_writer_by_locg_slug,
)
from vrobbler.apps.books.sources.google import lookup_book_from_google
from vrobbler.apps.books.sources.semantic import lookup_paper_from_semantic
from vrobbler.apps.scrobbles.dataclasses import BookLogData
COMICVINE_API_KEY = getattr(settings, "COMICVINE_API_KEY", "")
@ -64,22 +65,27 @@ class Author(TimeStampedModel):
)
bio = models.TextField(**BNULL)
wikipedia_url = models.CharField(max_length=255, **BNULL)
isni = models.CharField(max_length=255, **BNULL)
locg_slug = models.CharField(max_length=255, **BNULL)
wikidata_id = models.CharField(max_length=255, **BNULL)
isni = models.CharField(max_length=255, **BNULL)
goodreads_id = models.CharField(max_length=255, **BNULL)
librarything_id = models.CharField(max_length=255, **BNULL)
comicvine_data = models.JSONField(**BNULL)
amazon_id = models.CharField(max_length=255, **BNULL)
semantic_id = models.CharField(max_length=50, **BNULL)
def __str__(self):
return f"{self.name}"
def fix_metadata(self, data_dict: dict = {}):
if not data_dict and self.openlibrary_id:
data_dict = lookup_author_from_openlibrary(self.openlibrary_id)
def enrich_from_semantic(self, overwrite=False):
...
def enrich_from_google_books(self, overwrite=False):
...
def enrich_from_openlibrary(self, overwrite=False):
data_dict = lookup_author_from_openlibrary(self.openlibrary_id)
if not data_dict or not data_dict.get("name"):
logger.warning("Could not find author on openlibrary")
return
headshot_url = data_dict.pop("author_headshot_url", "")
@ -160,26 +166,32 @@ class Book(LongPlayScrobblableMixin):
if not created and not overwrite:
return book
bdict, authors, cover, genres = lookup_book_from_google(
title
).as_dict_with_authors_cover_and_genres()
book_dict = lookup_book_from_google(title)
if created or overwrite:
author_list = []
authors = book_dict.pop("authors")
cover_url = book_dict.pop("cover_url")
genres = book_dict.pop("generes")
if authors:
for author_str in authors:
if author_str:
author_list.append(
Author.objects.get_or_create(name=author_str)[0]
author, a_created = Author.objects.get_or_create(
name=author_str
)
author_list.append(author)
if a_created:
# TODO enrich author
...
for k, v in bdict.items():
for k, v in book_dict.items():
setattr(book, k, v)
book.save()
book.save()
book.save_image_from_url(cover)
book.genre.add(*genres)
book.authors.add(*author_list)
book.save_image_from_url(cover_url)
book.genre.add(*genres)
book.authors.add(*author_list)
return book
def save_image_from_url(self, url: str, force_update: bool = False):
@ -474,3 +486,68 @@ class Page(TimeStampedModel):
seconds=self.duration_seconds
)
self.save(update_fields=["end_time"])
class Paper(LongPlayScrobblableMixin):
"""Keeps track of Academic Papers"""
COMPLETION_PERCENT = getattr(settings, "PAPER_COMPLETION_PERCENT", 60)
AVG_PAGE_READING_SECONDS = getattr(
settings, "AVERAGE_PAGE_READING_SECONDS", 60
)
title = models.CharField(max_length=255)
semantic_title = models.CharField(max_length=255, **BNULL)
authors = models.ManyToManyField(Author, blank=True)
koreader_data_by_hash = models.JSONField(**BNULL)
arxiv_id = models.CharField(max_length=50, **BNULL)
semantic_id = models.CharField(max_length=50, **BNULL)
arxiv_id = models.CharField(max_length=50, **BNULL)
corpus_id = models.CharField(max_length=50, **BNULL)
doi_id = models.CharField(max_length=50, **BNULL)
pages = models.IntegerField(**BNULL)
language = models.CharField(max_length=4, **BNULL)
first_publish_year = models.IntegerField(**BNULL)
publish_date = models.DateField(**BNULL)
journal = models.CharField(max_length=255, **BNULL)
journal_volume = models.CharField(max_length=50, **BNULL)
abstract = models.TextField(**BNULL)
tldr = models.CharField(max_length=255, **BNULL)
openaccess_pdf_url = models.CharField(max_length=255, **BNULL)
genre = TaggableManager(through=ObjectWithGenres)
@classmethod
def get_from_semantic(cls, title: str, overwrite: bool = False) -> "Paper":
paper, created = cls.objects.get_or_create(title=title)
if not created and not overwrite:
return paper
paper_dict = lookup_paper_from_semantic(title)
if created or overwrite:
author_list = []
author_dicts = paper_dict.pop("author_dicts")
if author_dicts:
for author_dict in author_dicts:
if author_dict.get("authorId"):
author, a_created = Author.objects.get_or_create(
semantic_id=author_dict.get("authorId")
)
author_list.append(author)
if a_created:
author.name = author_dict.get("name")
author.save()
# TODO enrich author?
...
for k, v in paper_dict.items():
setattr(paper, k, v)
paper.save()
if author_list:
paper.authors.add(*author_list)
genres = paper_dict.pop("genres", [])
if genres:
paper.genre.add(*genres)
return paper