update lint: replace black and isort with ruff
This commit is contained in:
parent
a93d9668f7
commit
2a048a3719
151 changed files with 282 additions and 394 deletions
|
@ -25,21 +25,21 @@ repos:
|
|||
- id: mixed-line-ending
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.8.4
|
||||
rev: v0.9.1
|
||||
hooks:
|
||||
- id: ruff
|
||||
# - id: ruff-format
|
||||
- id: ruff-format
|
||||
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.13.2
|
||||
hooks:
|
||||
- id: isort
|
||||
args: ["--profile=black"]
|
||||
# - repo: https://github.com/pycqa/isort
|
||||
# rev: 5.13.2
|
||||
# hooks:
|
||||
# - id: isort
|
||||
# args: ["--profile=black"]
|
||||
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 24.4.2
|
||||
hooks:
|
||||
- id: black
|
||||
# - repo: https://github.com/psf/black
|
||||
# rev: 24.4.2
|
||||
# hooks:
|
||||
# - id: black
|
||||
|
||||
- repo: https://github.com/Riverside-Healthcare/djLint
|
||||
rev: v1.36.4
|
||||
|
|
|
@ -75,4 +75,4 @@ Please see [docs/install.md](docs/install.md)
|
|||
- To translate NeoDB to more languages, please join [our project on Weblate](https://hosted.weblate.org/projects/neodb/neodb/)
|
||||
|
||||
## Sponsor
|
||||
If you like this project, please consider donating to [NeoDB on ko-fi](https://ko-fi.com/neodb), or our friends at [NiceDB](https://patreon.com/tertius) without whom this project won't be possible.
|
||||
If you like this project, please consider donating to [NeoDB.social on ko-fi](https://ko-fi.com/neodb), or [Takahē](https://www.patreon.com/takahe) and [NiceDB](https://patreon.com/tertius) without whom this project won't be possible.
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from enum import Enum
|
||||
from typing import Any, Callable, List, Optional, Tuple, Type
|
||||
from typing import List
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.http import HttpResponse
|
||||
|
|
|
@ -7,12 +7,9 @@ class CatalogConfig(AppConfig):
|
|||
|
||||
def ready(self):
|
||||
# load key modules in proper order, make sure class inject and signal works as expected
|
||||
from catalog import api, models, sites
|
||||
from catalog.models import init_catalog_audit_log, init_catalog_search_models
|
||||
from journal import models as journal_models
|
||||
|
||||
# register cron jobs
|
||||
from catalog.jobs import DiscoverGenerator, PodcastUpdater # isort:skip
|
||||
|
||||
init_catalog_search_models()
|
||||
init_catalog_audit_log()
|
||||
|
|
|
@ -33,8 +33,6 @@ from catalog.common import (
|
|||
Item,
|
||||
ItemCategory,
|
||||
ItemInSchema,
|
||||
ItemSchema,
|
||||
ItemType,
|
||||
PrimaryLookupIdDescriptor,
|
||||
jsondata,
|
||||
)
|
||||
|
@ -286,7 +284,7 @@ class Edition(Item):
|
|||
logger.warning(f"Unable to find work for {work_res}")
|
||||
else:
|
||||
logger.warning(
|
||||
f'Unable to find resource for {w["id_type"]}:{w["id_value"]}'
|
||||
f"Unable to find resource for {w['id_type']}:{w['id_value']}"
|
||||
)
|
||||
work = Work.objects.filter(
|
||||
primary_lookup_id_type=w["id_type"],
|
||||
|
@ -431,7 +429,7 @@ class Work(Item):
|
|||
logger.warning(f"Unable to find edition for {edition_res}")
|
||||
else:
|
||||
logger.warning(
|
||||
f'Unable to find resource for {e["id_type"]}:{e["id_value"]}'
|
||||
f"Unable to find resource for {e['id_type']}:{e['id_value']}"
|
||||
)
|
||||
edition = Edition.objects.filter(
|
||||
primary_lookup_id_type=e["id_type"],
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import json
|
||||
import logging
|
||||
import re
|
||||
import time
|
||||
from io import BytesIO, StringIO
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
# pyright: reportIncompatibleMethodOverride=false
|
||||
import copy
|
||||
from base64 import b64decode, b64encode
|
||||
from base64 import b64encode
|
||||
from datetime import date, datetime
|
||||
from functools import partialmethod
|
||||
from hashlib import sha256
|
||||
from importlib import import_module
|
||||
|
||||
import django
|
||||
import loguru
|
||||
from cryptography.fernet import Fernet, MultiFernet
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import FieldError
|
||||
from django.db.models import DEFERRED, fields # type:ignore
|
||||
from django.utils import dateparse, timezone
|
||||
from django.utils.encoding import force_bytes
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_jsonform.forms.fields import JSONFormField as DJANGO_JSONFormField
|
||||
|
||||
# from django.db.models import JSONField as DJANGO_JSONField
|
||||
|
@ -22,7 +18,6 @@ from django_jsonform.forms.fields import JSONFormField as DJANGO_JSONFormField
|
|||
# from django.contrib.postgres.fields import ArrayField as DJANGO_ArrayField
|
||||
from django_jsonform.models.fields import ArrayField as DJANGO_ArrayField
|
||||
from django_jsonform.models.fields import JSONField as DJANGO_JSONField
|
||||
from loguru import logger
|
||||
|
||||
|
||||
class Patched_DJANGO_JSONField(DJANGO_JSONField):
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
import re
|
||||
import uuid
|
||||
from functools import cached_property
|
||||
from typing import TYPE_CHECKING, Any, Iterable, Self, Sequence, Type, cast
|
||||
from typing import TYPE_CHECKING, Any, Self
|
||||
|
||||
from auditlog.context import disable_auditlog
|
||||
from auditlog.models import AuditlogHistoryField, LogEntry
|
||||
from auditlog.models import LogEntry
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.core.signing import b62_decode, b62_encode
|
||||
from django.db import connection, models
|
||||
from django.db.models import QuerySet, Value
|
||||
from django.template.defaultfilters import default
|
||||
from django.db.models import QuerySet
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import get_language
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from loguru import logger
|
||||
from ninja import Field, Schema
|
||||
|
@ -72,36 +70,24 @@ class IdType(models.TextChoices):
|
|||
IMDB = "imdb", _("IMDb") # type:ignore[reportCallIssue]
|
||||
TMDB_TV = "tmdb_tv", _("TMDB TV Serie") # type:ignore[reportCallIssue]
|
||||
TMDB_TVSeason = "tmdb_tvseason", _("TMDB TV Season") # type:ignore[reportCallIssue]
|
||||
TMDB_TVEpisode = "tmdb_tvepisode", _(
|
||||
"TMDB TV Episode"
|
||||
) # type:ignore[reportCallIssue]
|
||||
TMDB_TVEpisode = "tmdb_tvepisode", _("TMDB TV Episode") # type:ignore[reportCallIssue]
|
||||
TMDB_Movie = "tmdb_movie", _("TMDB Movie") # type:ignore[reportCallIssue]
|
||||
Goodreads = "goodreads", _("Goodreads") # type:ignore[reportCallIssue]
|
||||
Goodreads_Work = "goodreads_work", _(
|
||||
"Goodreads Work"
|
||||
) # type:ignore[reportCallIssue]
|
||||
Goodreads_Work = "goodreads_work", _("Goodreads Work") # type:ignore[reportCallIssue]
|
||||
GoogleBooks = "googlebooks", _("Google Books") # type:ignore[reportCallIssue]
|
||||
DoubanBook = "doubanbook", _("Douban Book") # type:ignore[reportCallIssue]
|
||||
DoubanBook_Work = "doubanbook_work", _(
|
||||
"Douban Book Work"
|
||||
) # type:ignore[reportCallIssue]
|
||||
DoubanBook_Work = "doubanbook_work", _("Douban Book Work") # type:ignore[reportCallIssue]
|
||||
DoubanMovie = "doubanmovie", _("Douban Movie") # type:ignore[reportCallIssue]
|
||||
DoubanMusic = "doubanmusic", _("Douban Music") # type:ignore[reportCallIssue]
|
||||
DoubanGame = "doubangame", _("Douban Game") # type:ignore[reportCallIssue]
|
||||
DoubanDrama = "doubandrama", _("Douban Drama") # type:ignore[reportCallIssue]
|
||||
DoubanDramaVersion = "doubandrama_version", _(
|
||||
"Douban Drama Version"
|
||||
) # type:ignore[reportCallIssue]
|
||||
DoubanDramaVersion = "doubandrama_version", _("Douban Drama Version") # type:ignore[reportCallIssue]
|
||||
BooksTW = "bookstw", _("BooksTW Book") # type:ignore[reportCallIssue]
|
||||
Bandcamp = "bandcamp", _("Bandcamp") # type:ignore[reportCallIssue]
|
||||
Spotify_Album = "spotify_album", _("Spotify Album") # type:ignore[reportCallIssue]
|
||||
Spotify_Show = "spotify_show", _("Spotify Podcast") # type:ignore[reportCallIssue]
|
||||
Discogs_Release = "discogs_release", _(
|
||||
"Discogs Release"
|
||||
) # type:ignore[reportCallIssue]
|
||||
Discogs_Master = "discogs_master", _(
|
||||
"Discogs Master"
|
||||
) # type:ignore[reportCallIssue]
|
||||
Discogs_Release = "discogs_release", _("Discogs Release") # type:ignore[reportCallIssue]
|
||||
Discogs_Master = "discogs_master", _("Discogs Master") # type:ignore[reportCallIssue]
|
||||
MusicBrainz = "musicbrainz", _("MusicBrainz ID") # type:ignore[reportCallIssue]
|
||||
# DoubanBook_Author = "doubanbook_author", _("Douban Book Author") # type:ignore[reportCallIssue]
|
||||
# DoubanCelebrity = "doubanmovie_celebrity", _("Douban Movie Celebrity") # type:ignore[reportCallIssue]
|
||||
|
@ -142,13 +128,9 @@ class ItemType(models.TextChoices):
|
|||
Album = "music", _("Album") # type:ignore[reportCallIssue]
|
||||
Game = "game", _("Game") # type:ignore[reportCallIssue]
|
||||
Podcast = "podcast", _("Podcast Program") # type:ignore[reportCallIssue]
|
||||
PodcastEpisode = "podcastepisode", _(
|
||||
"Podcast Episode"
|
||||
) # type:ignore[reportCallIssue]
|
||||
PodcastEpisode = "podcastepisode", _("Podcast Episode") # type:ignore[reportCallIssue]
|
||||
Performance = "performance", _("Performance") # type:ignore[reportCallIssue]
|
||||
PerformanceProduction = "production", _(
|
||||
"Production"
|
||||
) # type:ignore[reportCallIssue]
|
||||
PerformanceProduction = "production", _("Production") # type:ignore[reportCallIssue]
|
||||
FanFic = "fanfic", _("Fanfic") # type:ignore[reportCallIssue]
|
||||
Exhibition = "exhibition", _("Exhibition") # type:ignore[reportCallIssue]
|
||||
Collection = "collection", _("Collection") # type:ignore[reportCallIssue]
|
||||
|
|
|
@ -10,7 +10,7 @@ ResourceContent persists as an ExternalResource which may link to an Item
|
|||
import json
|
||||
import re
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Callable, Type, TypeVar
|
||||
from typing import Type, TypeVar
|
||||
|
||||
import django_rq
|
||||
import requests
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
from django.test import TestCase
|
||||
|
||||
from common.models import (
|
||||
LANGUAGE_CHOICES,
|
||||
LOCALE_CHOICES,
|
||||
SCRIPT_CHOICES,
|
||||
SITE_DEFAULT_LANGUAGE,
|
||||
SITE_PREFERRED_LANGUAGES,
|
||||
SITE_PREFERRED_LOCALES,
|
||||
detect_language,
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
from datetime import date
|
||||
|
||||
from django.db import models
|
||||
from django.template.defaultfilters import default
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from catalog.common import (
|
||||
BaseSchema,
|
||||
ExternalResource,
|
||||
IdType,
|
||||
Item,
|
||||
ItemCategory,
|
||||
ItemInSchema,
|
||||
ItemSchema,
|
||||
ItemType,
|
||||
PrimaryLookupIdDescriptor,
|
||||
jsondata,
|
||||
|
|
|
@ -1,2 +1,7 @@
|
|||
from .discover import DiscoverGenerator
|
||||
from .podcast import PodcastUpdater
|
||||
|
||||
__all__ = [
|
||||
"DiscoverGenerator",
|
||||
"PodcastUpdater",
|
||||
]
|
||||
|
|
|
@ -7,7 +7,6 @@ from django.db.models import Count, F, Q
|
|||
from django.utils import timezone
|
||||
from loguru import logger
|
||||
|
||||
from boofilsic.settings import MIN_MARKS_FOR_DISCOVER
|
||||
from catalog.models import *
|
||||
from common.models import SITE_PREFERRED_LOCALES, BaseJob, JobManager
|
||||
from journal.models import (
|
||||
|
@ -19,7 +18,6 @@ from journal.models import (
|
|||
q_item_in_category,
|
||||
)
|
||||
from takahe.utils import Takahe
|
||||
from users.models import APIdentity
|
||||
|
||||
MAX_ITEMS_PER_PERIOD = 12
|
||||
MIN_MARKS = settings.MIN_MARKS_FOR_DISCOVER
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import pprint
|
||||
from datetime import timedelta
|
||||
from time import sleep
|
||||
|
||||
from loguru import logger
|
||||
|
||||
|
@ -30,6 +28,6 @@ class PodcastUpdater(BaseJob):
|
|||
site = RSS(p.feed_url)
|
||||
site.scrape_additional_data()
|
||||
c2 = p.episodes.count()
|
||||
logger.info(f"updated {p}, {c2-c} new episodes.")
|
||||
logger.info(f"updated {p}, {c2 - c} new episodes.")
|
||||
count += c2 - c
|
||||
logger.info(f"Podcasts update finished, {count} new episodes total.")
|
||||
|
|
|
@ -46,4 +46,4 @@ class Command(BaseCommand):
|
|||
resource = site.scrape()
|
||||
pprint.pp(resource.metadata)
|
||||
pprint.pp(resource.lookup_ids)
|
||||
self.stdout.write(self.style.SUCCESS(f"Done."))
|
||||
self.stdout.write(self.style.SUCCESS("Done."))
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
import pprint
|
||||
import re
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db.models import Count, F
|
||||
|
@ -9,7 +6,6 @@ from tqdm import tqdm
|
|||
from catalog.book.tests import uniq
|
||||
from catalog.models import *
|
||||
from common.models.lang import detect_language
|
||||
from journal.models import update_journal_for_merged_item
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
|
@ -49,7 +45,7 @@ class Command(BaseCommand):
|
|||
self.integrity()
|
||||
if options["localize"]:
|
||||
self.localize()
|
||||
self.stdout.write(self.style.SUCCESS(f"Done."))
|
||||
self.stdout.write(self.style.SUCCESS("Done."))
|
||||
|
||||
def localize(self):
|
||||
c = Item.objects.all().count()
|
||||
|
@ -94,14 +90,14 @@ class Command(BaseCommand):
|
|||
cls.objects.filter(is_deleted=True).delete()
|
||||
|
||||
def integrity(self):
|
||||
self.stdout.write(f"Checking circulated merge...")
|
||||
self.stdout.write("Checking circulated merge...")
|
||||
for i in Item.objects.filter(merged_to_item=F("id")):
|
||||
self.stdout.write(f"! {i} : {i.absolute_url}?skipcheck=1")
|
||||
if self.fix:
|
||||
i.merged_to_item = None
|
||||
i.save()
|
||||
|
||||
self.stdout.write(f"Checking chained merge...")
|
||||
self.stdout.write("Checking chained merge...")
|
||||
for i in (
|
||||
Item.objects.filter(merged_to_item__isnull=False)
|
||||
.annotate(n=Count("merged_from_items"))
|
||||
|
@ -113,14 +109,14 @@ class Command(BaseCommand):
|
|||
j.merged_to_item = i.merged_to_item
|
||||
j.save()
|
||||
|
||||
self.stdout.write(f"Checking deleted merge...")
|
||||
self.stdout.write("Checking deleted merge...")
|
||||
for i in Item.objects.filter(merged_to_item__isnull=False, is_deleted=True):
|
||||
self.stdout.write(f"! {i} : {i.absolute_url}?skipcheck=1")
|
||||
if self.fix:
|
||||
i.is_deleted = False
|
||||
i.save()
|
||||
|
||||
self.stdout.write(f"Checking deleted item with external resources...")
|
||||
self.stdout.write("Checking deleted item with external resources...")
|
||||
for i in (
|
||||
Item.objects.filter(is_deleted=True)
|
||||
.annotate(n=Count("external_resources"))
|
||||
|
@ -132,7 +128,7 @@ class Command(BaseCommand):
|
|||
r.item = None
|
||||
r.save()
|
||||
|
||||
self.stdout.write(f"Checking merged item with external resources...")
|
||||
self.stdout.write("Checking merged item with external resources...")
|
||||
for i in (
|
||||
Item.objects.filter(merged_to_item__isnull=False)
|
||||
.annotate(n=Count("external_resources"))
|
||||
|
@ -145,7 +141,7 @@ class Command(BaseCommand):
|
|||
r.save()
|
||||
|
||||
tvshow_ct_id = ContentType.objects.get_for_model(TVShow).id
|
||||
self.stdout.write(f"Checking TVShow merged to other class...")
|
||||
self.stdout.write("Checking TVShow merged to other class...")
|
||||
for i in (
|
||||
TVShow.objects.filter(merged_to_item__isnull=False)
|
||||
.filter(merged_to_item__isnull=False)
|
||||
|
@ -161,7 +157,7 @@ class Command(BaseCommand):
|
|||
if self.fix:
|
||||
i.recast_to(i.merged_to_item.__class__) # type:ignore
|
||||
|
||||
self.stdout.write(f"Checking TVSeason is child of other class...")
|
||||
self.stdout.write("Checking TVSeason is child of other class...")
|
||||
for i in TVSeason.objects.filter(show__isnull=False).exclude(
|
||||
show__polymorphic_ctype_id=tvshow_ct_id
|
||||
):
|
||||
|
@ -172,7 +168,7 @@ class Command(BaseCommand):
|
|||
i.show = None
|
||||
i.save()
|
||||
|
||||
self.stdout.write(f"Checking deleted item with child TV Season...")
|
||||
self.stdout.write("Checking deleted item with child TV Season...")
|
||||
for i in TVSeason.objects.filter(show__is_deleted=True):
|
||||
if not i.show:
|
||||
continue
|
||||
|
@ -181,7 +177,7 @@ class Command(BaseCommand):
|
|||
i.show.is_deleted = False
|
||||
i.show.save()
|
||||
|
||||
self.stdout.write(f"Checking merged item with child TV Season...")
|
||||
self.stdout.write("Checking merged item with child TV Season...")
|
||||
for i in TVSeason.objects.filter(show__merged_to_item__isnull=False):
|
||||
if not i.show:
|
||||
continue
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
import pprint
|
||||
from datetime import timedelta
|
||||
from time import sleep
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.core.paginator import Paginator
|
||||
from django.utils import timezone
|
||||
from tqdm import tqdm
|
||||
|
||||
from catalog.models import Item
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
import uuid
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
import catalog.common.utils
|
||||
|
|
|
@ -4,7 +4,6 @@ from django.db import migrations
|
|||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("catalog", "0010_alter_item_polymorphic_ctype"),
|
||||
]
|
||||
|
|
|
@ -6,7 +6,6 @@ import catalog.common.utils
|
|||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("catalog", "0011_alter_externalresource_id_type_and_more"),
|
||||
]
|
||||
|
|
|
@ -38,7 +38,7 @@ from .tv.models import (
|
|||
TVShowSchema,
|
||||
)
|
||||
|
||||
from .search.models import Indexer, ExternalSearchResultItem # isort:skip
|
||||
from .search.models import Indexer # isort:skip
|
||||
|
||||
|
||||
# class Exhibition(Item):
|
||||
|
|
|
@ -3,12 +3,10 @@ from django.utils.translation import gettext_lazy as _
|
|||
|
||||
from catalog.common import (
|
||||
BaseSchema,
|
||||
ExternalResource,
|
||||
IdType,
|
||||
Item,
|
||||
ItemCategory,
|
||||
ItemInSchema,
|
||||
ItemSchema,
|
||||
ItemType,
|
||||
PrimaryLookupIdDescriptor,
|
||||
jsondata,
|
||||
|
|
|
@ -6,12 +6,10 @@ from django.utils.translation import pgettext_lazy
|
|||
|
||||
from catalog.common import (
|
||||
BaseSchema,
|
||||
ExternalResource,
|
||||
IdType,
|
||||
Item,
|
||||
ItemCategory,
|
||||
ItemInSchema,
|
||||
ItemSchema,
|
||||
ItemType,
|
||||
PrimaryLookupIdDescriptor,
|
||||
jsondata,
|
||||
|
|
|
@ -391,7 +391,9 @@ class PerformanceProduction(Item):
|
|||
return (
|
||||
self.cover.url # type:ignore
|
||||
if self.cover and self.cover != settings.DEFAULT_ITEM_COVER
|
||||
else self.show.cover_image_url if self.show else None
|
||||
else self.show.cover_image_url
|
||||
if self.show
|
||||
else None
|
||||
)
|
||||
|
||||
def update_linked_items_from_external_resource(self, resource: ExternalResource):
|
||||
|
|
|
@ -6,14 +6,10 @@ from ninja import Field
|
|||
|
||||
from catalog.common import (
|
||||
BaseSchema,
|
||||
ExternalResource,
|
||||
IdType,
|
||||
Item,
|
||||
ItemCategory,
|
||||
ItemInSchema,
|
||||
ItemSchema,
|
||||
ItemType,
|
||||
PrimaryLookupIdDescriptor,
|
||||
jsondata,
|
||||
)
|
||||
from catalog.common.models import LIST_OF_ONE_PLUS_STR_SCHEMA, LanguageListField
|
||||
|
|
|
@ -62,7 +62,7 @@ class PodcastRSSFeedTestCase(TestCase):
|
|||
site = SiteManager.get_site_by_url(t_url)
|
||||
site.get_resource_ready()
|
||||
self.assertEqual(site.ready, True)
|
||||
metadata = site.resource.metadata
|
||||
# metadata = site.resource.metadata
|
||||
self.assertIsNotNone(site.get_item().cover.url)
|
||||
self.assertIsNotNone(site.get_item().recent_episodes[0].title)
|
||||
self.assertIsNotNone(site.get_item().recent_episodes[0].link)
|
||||
|
@ -74,7 +74,7 @@ class PodcastRSSFeedTestCase(TestCase):
|
|||
site = SiteManager.get_site_by_url(t_url)
|
||||
site.get_resource_ready()
|
||||
self.assertEqual(site.ready, True)
|
||||
metadata = site.resource.metadata
|
||||
# metadata = site.resource.metadata
|
||||
self.assertIsNotNone(site.get_item().recent_episodes[0].title)
|
||||
self.assertIsNotNone(site.get_item().recent_episodes[0].link)
|
||||
self.assertIsNotNone(site.get_item().recent_episodes[0].media_url)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import asyncio
|
||||
import logging
|
||||
import time
|
||||
from urllib.parse import quote_plus, urlparse
|
||||
|
||||
import httpx
|
||||
|
@ -90,7 +89,7 @@ class GoogleBooks:
|
|||
@classmethod
|
||||
def search(cls, q, page=1):
|
||||
results = []
|
||||
api_url = f"https://www.googleapis.com/books/v1/volumes?country=us&q={quote_plus(q)}&startIndex={SEARCH_PAGE_SIZE*(page-1)}&maxResults={SEARCH_PAGE_SIZE}&maxAllowedMaturityRating=MATURE"
|
||||
api_url = f"https://www.googleapis.com/books/v1/volumes?country=us&q={quote_plus(q)}&startIndex={SEARCH_PAGE_SIZE * (page - 1)}&maxResults={SEARCH_PAGE_SIZE}&maxAllowedMaturityRating=MATURE"
|
||||
try:
|
||||
j = requests.get(api_url, timeout=2).json()
|
||||
if "items" in j:
|
||||
|
@ -183,7 +182,7 @@ class Spotify:
|
|||
@classmethod
|
||||
def search(cls, q, page=1):
|
||||
results = []
|
||||
api_url = f"https://api.spotify.com/v1/search?q={q}&type=album&limit={SEARCH_PAGE_SIZE}&offset={page*SEARCH_PAGE_SIZE}"
|
||||
api_url = f"https://api.spotify.com/v1/search?q={q}&type=album&limit={SEARCH_PAGE_SIZE}&offset={page * SEARCH_PAGE_SIZE}"
|
||||
try:
|
||||
headers = {"Authorization": f"Bearer {get_spotify_token()}"}
|
||||
j = requests.get(api_url, headers=headers, timeout=2).json()
|
||||
|
@ -255,7 +254,7 @@ class ApplePodcast:
|
|||
@classmethod
|
||||
def search(cls, q, page=1):
|
||||
results = []
|
||||
search_url = f"https://itunes.apple.com/search?entity=podcast&limit={page*SEARCH_PAGE_SIZE}&term={quote_plus(q)}"
|
||||
search_url = f"https://itunes.apple.com/search?entity=podcast&limit={page * SEARCH_PAGE_SIZE}&term={quote_plus(q)}"
|
||||
try:
|
||||
r = requests.get(search_url, timeout=2).json()
|
||||
for p in r["results"][(page - 1) * SEARCH_PAGE_SIZE :]:
|
||||
|
@ -291,7 +290,7 @@ class IGDB:
|
|||
class Fediverse:
|
||||
@staticmethod
|
||||
async def search_task(host, q, category=None):
|
||||
api_url = f"https://{host}/api/catalog/search?query={quote_plus(q)}{'&category='+category if category else ''}"
|
||||
api_url = f"https://{host}/api/catalog/search?query={quote_plus(q)}{'&category=' + category if category else ''}"
|
||||
async with httpx.AsyncClient() as client:
|
||||
results = []
|
||||
try:
|
||||
|
|
|
@ -6,7 +6,6 @@ import django_rq
|
|||
from auditlog.context import set_actor
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from loguru import logger
|
||||
from rq.job import Job
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import types
|
||||
from datetime import timedelta
|
||||
from pprint import pprint
|
||||
from time import sleep
|
||||
|
||||
import django_rq
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import re
|
||||
from urllib.parse import quote
|
||||
|
||||
import django_rq
|
||||
from django.conf import settings
|
||||
|
@ -7,7 +6,6 @@ from django.contrib.auth.decorators import login_required
|
|||
from django.core.cache import cache
|
||||
from django.core.exceptions import BadRequest
|
||||
from django.shortcuts import redirect, render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from rq.job import Job
|
||||
|
@ -162,7 +160,7 @@ def external_search(request):
|
|||
keywords = request.GET.get("q", default="").strip()
|
||||
page_number = int_(request.GET.get("page"), 1)
|
||||
items = ExternalSources.search(category, keywords, page_number) if keywords else []
|
||||
cache_key = f"search_{category if category!='movietv' else 'movie,tv'}_{keywords}"
|
||||
cache_key = f"search_{category if category != 'movietv' else 'movie,tv'}_{keywords}"
|
||||
dedupe_urls = cache.get(cache_key, [])
|
||||
items = [i for i in items if i.source_url not in dedupe_urls]
|
||||
|
||||
|
|
|
@ -25,3 +25,33 @@ from .tmdb import TMDB_Movie
|
|||
from .ypshuo import Ypshuo
|
||||
|
||||
# from .apple_podcast import ApplePodcast
|
||||
|
||||
__all__ = [
|
||||
"SiteManager",
|
||||
"ArchiveOfOurOwn",
|
||||
"AppleMusic",
|
||||
"Bandcamp",
|
||||
"Bangumi",
|
||||
"BoardGameGeek",
|
||||
"BooksTW",
|
||||
"DiscogsMaster",
|
||||
"DiscogsRelease",
|
||||
"DoubanBook",
|
||||
"DoubanDrama",
|
||||
"DoubanGame",
|
||||
"DoubanMovie",
|
||||
"DoubanMusic",
|
||||
"FediverseInstance",
|
||||
"Goodreads",
|
||||
"GoogleBooks",
|
||||
"IGDB",
|
||||
"IMDB",
|
||||
"JJWXC",
|
||||
"Qidian",
|
||||
"RSS",
|
||||
"Spotify",
|
||||
"Steam",
|
||||
"TMDB_Movie",
|
||||
"Ypshuo",
|
||||
# "ApplePodcast",
|
||||
]
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import logging
|
||||
|
||||
from catalog.book.models import *
|
||||
from catalog.common import *
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ Scraping the website directly.
|
|||
|
||||
import json
|
||||
import logging
|
||||
from threading import local
|
||||
|
||||
import dateparser
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@ ref: https://boardgamegeek.com/wiki/page/BGG_XML_API2
|
|||
|
||||
import html
|
||||
|
||||
from langdetect import detect
|
||||
from loguru import logger
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.game.models import GameReleaseType
|
||||
|
|
|
@ -3,7 +3,6 @@ import logging
|
|||
from catalog.book.models import *
|
||||
from catalog.book.utils import *
|
||||
from catalog.common import *
|
||||
from common.models.lang import detect_language
|
||||
|
||||
from .douban import *
|
||||
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
Discogs.
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
||||
import requests
|
||||
from django.conf import settings
|
||||
|
||||
from catalog.common import *
|
||||
|
|
|
@ -37,12 +37,10 @@ class DoubanDownloader(ProxiedDownloader):
|
|||
class DoubanSearcher:
|
||||
@classmethod
|
||||
def search(cls, cat: ItemCategory, c: str, q: str, p: int = 1):
|
||||
url = f"https://search.douban.com/{c}/subject_search?search_text={q}&start={15*(p-1)}"
|
||||
url = f"https://search.douban.com/{c}/subject_search?search_text={q}&start={15 * (p - 1)}"
|
||||
content = DoubanDownloader(url).download().html()
|
||||
j = json.loads(
|
||||
content.xpath(
|
||||
"//script[text()[contains(.,'window.__DATA__')]]/text()"
|
||||
)[ # type:ignore
|
||||
content.xpath("//script[text()[contains(.,'window.__DATA__')]]/text()")[ # type:ignore
|
||||
0
|
||||
]
|
||||
.split("window.__DATA__ = ")[1] # type:ignore
|
||||
|
|
|
@ -7,7 +7,7 @@ from catalog.common import *
|
|||
from catalog.models import *
|
||||
from common.models.lang import detect_language
|
||||
|
||||
from .douban import DoubanDownloader, DoubanSearcher
|
||||
from .douban import DoubanDownloader
|
||||
|
||||
|
||||
def _cache_key(url):
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import logging
|
||||
|
||||
import dateparser
|
||||
|
||||
from catalog.common import *
|
||||
|
@ -7,7 +5,7 @@ from catalog.models import *
|
|||
from common.models.lang import detect_language
|
||||
from common.models.misc import uniq
|
||||
|
||||
from .douban import DoubanDownloader, DoubanSearcher
|
||||
from .douban import DoubanDownloader
|
||||
|
||||
|
||||
@SiteManager.register
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import json
|
||||
import logging
|
||||
import re
|
||||
|
||||
from loguru import logger
|
||||
|
||||
|
@ -10,7 +10,7 @@ from common.models.lang import detect_language
|
|||
from common.models.misc import int_
|
||||
|
||||
from .douban import DoubanDownloader, DoubanSearcher
|
||||
from .tmdb import TMDB_TV, TMDB_TVSeason, query_tmdb_tv_episode, search_tmdb_by_imdb_id
|
||||
from .tmdb import TMDB_TV, search_tmdb_by_imdb_id
|
||||
|
||||
|
||||
@SiteManager.register
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import logging
|
||||
|
||||
import dateparser
|
||||
|
||||
from catalog.common import *
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import re
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.validators import URLValidator
|
||||
from loguru import logger
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import json
|
||||
import logging
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
from django.utils.timezone import make_aware
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import json
|
||||
import logging
|
||||
|
||||
import re
|
||||
from catalog.common import *
|
||||
from catalog.movie.models import *
|
||||
from catalog.tv.models import *
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import logging
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import bleach
|
|||
import podcastparser
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import URLValidator
|
||||
from django.utils.timezone import make_aware
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
Spotify
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
import time
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import logging
|
||||
import re
|
||||
|
||||
import dateparser
|
||||
from django.conf import settings
|
||||
|
||||
from catalog.common import *
|
||||
|
|
|
@ -242,9 +242,9 @@ class TMDB_TV(AbstractSite):
|
|||
lambda s: {
|
||||
"model": "TVSeason",
|
||||
"id_type": IdType.TMDB_TVSeason,
|
||||
"id_value": f'{self.id_value}-{s["season_number"]}',
|
||||
"id_value": f"{self.id_value}-{s['season_number']}",
|
||||
"title": s["name"],
|
||||
"url": f'{self.url}/season/{s["season_number"]}',
|
||||
"url": f"{self.url}/season/{s['season_number']}",
|
||||
},
|
||||
res_data["seasons"],
|
||||
)
|
||||
|
@ -359,7 +359,7 @@ class TMDB_TVSeason(AbstractSite):
|
|||
pd.metadata["title"] = (
|
||||
pd.metadata["title"]
|
||||
if pd.metadata.get("title")
|
||||
else f'Season {d["season_number"]}'
|
||||
else f"Season {d['season_number']}"
|
||||
)
|
||||
pd.metadata["episode_number_list"] = list(
|
||||
map(lambda ep: ep["episode_number"], d["episodes"])
|
||||
|
@ -460,7 +460,7 @@ class TMDB_TVEpisode(AbstractSite):
|
|||
pd.metadata["title"] = (
|
||||
pd.metadata["title"]
|
||||
if pd.metadata["title"]
|
||||
else f'S{d["season_number"]} E{d["episode_number"]}'
|
||||
else f"S{d['season_number']} E{d['episode_number']}"
|
||||
)
|
||||
|
||||
if pd.lookup_ids.get(IdType.IMDB):
|
||||
|
|
|
@ -25,15 +25,12 @@ For now, we follow Douban convention, but keep an eye on it in case it breaks it
|
|||
|
||||
"""
|
||||
|
||||
import re
|
||||
from functools import cached_property
|
||||
from typing import TYPE_CHECKING, overload
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from auditlog.diff import ForeignKey
|
||||
from auditlog.models import QuerySet
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from typing_extensions import override
|
||||
|
||||
from catalog.common import (
|
||||
BaseSchema,
|
||||
|
|
|
@ -128,7 +128,7 @@ class DoubanMovieTVTestCase(TestCase):
|
|||
url = "https://movie.douban.com/subject/35597581/"
|
||||
item = SiteManager.get_site_by_url(url).get_resource_ready().item
|
||||
# disable this test to make douban data less disrupted
|
||||
# self.assertEqual(item.imdb, "tt21599650")
|
||||
self.assertEqual(item.imdb, "tt21599650")
|
||||
|
||||
|
||||
class MultiTVSitesTestCase(TestCase):
|
||||
|
@ -186,7 +186,7 @@ class MovieTVModelRecastTestCase(TestCase):
|
|||
|
||||
@use_local_response
|
||||
def test_recast(self):
|
||||
from catalog.models import Movie, TVShow
|
||||
from catalog.models import Movie
|
||||
|
||||
url2 = "https://www.imdb.com/title/tt0436992/"
|
||||
p2 = SiteManager.get_site_by_url(url2).get_resource_ready()
|
||||
|
@ -232,10 +232,10 @@ class IMDBTestCase(TestCase):
|
|||
|
||||
@use_local_response
|
||||
def test_get_episode_list(self):
|
||||
l = IMDB.get_episode_list("tt0436992", 4)
|
||||
self.assertEqual(len(l), 14)
|
||||
l = IMDB.get_episode_list("tt1205438", 4)
|
||||
self.assertEqual(len(l), 14)
|
||||
episodes = IMDB.get_episode_list("tt0436992", 4)
|
||||
self.assertEqual(len(episodes), 14)
|
||||
episodes = IMDB.get_episode_list("tt1205438", 4)
|
||||
self.assertEqual(len(episodes), 14)
|
||||
|
||||
@use_local_response
|
||||
def test_tvshow(self):
|
||||
|
|
|
@ -22,12 +22,10 @@ from journal.models import (
|
|||
Review,
|
||||
ShelfManager,
|
||||
ShelfMember,
|
||||
ShelfType,
|
||||
q_piece_in_home_feed_of_user,
|
||||
q_piece_visible_to_user,
|
||||
)
|
||||
from takahe.utils import Takahe
|
||||
from users.views import announcements
|
||||
|
||||
from .forms import *
|
||||
from .models import *
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Any, Callable, List, Optional, Tuple, Type
|
||||
from typing import Any, List
|
||||
|
||||
from django.conf import settings
|
||||
from django.db.models import QuerySet
|
||||
|
@ -91,7 +91,7 @@ class PageNumberPagination(NinjaPageNumberPagination):
|
|||
|
||||
api = NinjaAPI(
|
||||
auth=OAuthAccessTokenAuth(),
|
||||
title=f'{settings.SITE_INFO["site_name"]} API',
|
||||
title=f"{settings.SITE_INFO['site_name']} API",
|
||||
version="1.0.0",
|
||||
description=f"{settings.SITE_INFO['site_name']} API <hr/><a href='{settings.SITE_INFO['site_url']}'>Learn more</a>",
|
||||
)
|
||||
|
|
|
@ -1,12 +1,5 @@
|
|||
import json
|
||||
|
||||
import django.contrib.postgres.forms as postgres
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.forms import ModelForm
|
||||
from django.utils import formats
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from markdownx.fields import MarkdownxFormField
|
||||
|
||||
|
||||
class NeoModelForm(ModelForm):
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
import random
|
||||
from time import sleep
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from loguru import logger
|
||||
|
||||
from common.models import BaseJob, JobManager
|
||||
from common.models import JobManager
|
||||
|
||||
# @JobManager.register
|
||||
# class DummyJob(BaseJob):
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
import pprint
|
||||
|
||||
import django_rq
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand
|
||||
from redis import Redis
|
||||
from rq import Queue
|
||||
from rq.job import Job
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import re
|
||||
from functools import cached_property
|
||||
from time import sleep
|
||||
from typing import Iterable, Self, TypeVar
|
||||
from typing import Iterable, Self
|
||||
|
||||
import typesense
|
||||
from django.conf import settings
|
||||
from loguru import logger
|
||||
from ninja import Query
|
||||
from typesense.collection import Collection
|
||||
from typesense.exceptions import ObjectNotFound
|
||||
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
"""
|
||||
Language support utilities
|
||||
Language support utilities
|
||||
|
||||
get site wide preferences:
|
||||
SITE_DEFAULT_LANGUAGE
|
||||
SITE_PREFERRED_LANGUAGES
|
||||
SITE_PREFERRED_LOCALES
|
||||
get site wide preferences:
|
||||
SITE_DEFAULT_LANGUAGE
|
||||
SITE_PREFERRED_LANGUAGES
|
||||
SITE_PREFERRED_LOCALES
|
||||
|
||||
get available choices based on site wide preferences:
|
||||
LANGUAGE_CHOICES
|
||||
LOCALE_CHOICES
|
||||
SCRIPT_CHOICES
|
||||
get available choices based on site wide preferences:
|
||||
LANGUAGE_CHOICES
|
||||
LOCALE_CHOICES
|
||||
SCRIPT_CHOICES
|
||||
|
||||
based on user preferences:
|
||||
get_current_locales()
|
||||
based on user preferences:
|
||||
get_current_locales()
|
||||
|
||||
detect language based on text:
|
||||
detect_language()
|
||||
detect language based on text:
|
||||
detect_language()
|
||||
|
||||
refereneces:
|
||||
https://en.wikipedia.org/wiki/IETF_language_tag
|
||||
refereneces:
|
||||
https://en.wikipedia.org/wiki/IETF_language_tag
|
||||
"""
|
||||
|
||||
import re
|
||||
|
|
|
@ -9,9 +9,7 @@ from takahe.models import Config as TakaheConfig
|
|||
from takahe.models import Domain as TakaheDomain
|
||||
from takahe.models import Identity as TakaheIdentity
|
||||
from takahe.models import Relay as TakaheRelay
|
||||
from takahe.models import User as TakaheUser
|
||||
from takahe.utils import Takahe
|
||||
from users.models import User
|
||||
|
||||
|
||||
class Setup:
|
||||
|
|
|
@ -24,19 +24,26 @@
|
|||
{% if site_color == 'azure' %}
|
||||
<link rel="stylesheet"
|
||||
href="{{ cdn_url }}/npm/@picocss/pico@2/css/pico.min.css" />
|
||||
<style>
|
||||
{% else %}
|
||||
<link rel="stylesheet" href="{{ cdn_url }}/npm/@picocss/pico@2/css/pico.{{site_color}}.min.css" />
|
||||
<style>
|
||||
<link rel="stylesheet"
|
||||
href="{{ cdn_url }}/npm/@picocss/pico@2/css/pico.{{ site_color }}.min.css" />
|
||||
{% endif %}
|
||||
<style>
|
||||
:where(nav li)::before {
|
||||
float: none;
|
||||
content: " ";
|
||||
}
|
||||
</style>
|
||||
<link href="{% sass_src 'scss/neodb.scss' %}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ cdn_url }}/npm/@fortawesome/fontawesome-free@6.5.2/css/all.min.css" rel="stylesheet" type="text/css">
|
||||
<link rel="search" type="application/opensearchdescription+xml" title="{{ site_name }}" href="{% static 'opensearch.xml' %}">
|
||||
<link href="{% sass_src 'scss/neodb.scss' %}"
|
||||
rel="stylesheet"
|
||||
type="text/css" />
|
||||
<link href="{{ cdn_url }}/npm/@fortawesome/fontawesome-free@6.5.2/css/all.min.css"
|
||||
rel="stylesheet"
|
||||
type="text/css">
|
||||
<link rel="search"
|
||||
type="application/opensearchdescription+xml"
|
||||
title="{{ site_name }}"
|
||||
href="{% static 'opensearch.xml' %}">
|
||||
<script defer>
|
||||
(function(){
|
||||
const s = localStorage.getItem("user_style");
|
||||
|
@ -59,8 +66,8 @@
|
|||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-title" content="{{ site_name }}">
|
||||
{% if request.META.HTTP_HOST == site_domain %}
|
||||
<style type="text/css">.hide_unless_alter_domain{display:none;}</style>
|
||||
<style type="text/css">.hide_unless_alter_domain{display:none;}</style>
|
||||
{% else %}
|
||||
<meta name="robots" content="noindex">
|
||||
<meta name="robots" content="noindex">
|
||||
{% endif %}
|
||||
{{ site_head|safe }}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from datetime import date, datetime, timedelta, timezone
|
||||
from datetime import datetime
|
||||
|
||||
from django import template
|
||||
from django.conf import settings
|
||||
|
@ -48,16 +48,16 @@ def naturaldelta(v: datetime | None):
|
|||
if d < 60:
|
||||
return _("just now")
|
||||
if d < 3600:
|
||||
return f"{d//60}m"
|
||||
return f"{d // 60}m"
|
||||
if d < 86400:
|
||||
return f"{d//3600}h"
|
||||
return f"{d // 3600}h"
|
||||
if d < 86400 * 14:
|
||||
return f"{d//86400}d"
|
||||
return f"{d // 86400}d"
|
||||
if d < 86400 * 56:
|
||||
return f"{d//86400//7}w"
|
||||
return f"{d // 86400 // 7}w"
|
||||
if d < 86400 * 30 * 18:
|
||||
return f"{d//86400//30}mo"
|
||||
return f"{d//86400//365}yr"
|
||||
return f"{d // 86400 // 30}mo"
|
||||
return f"{d // 86400 // 365}yr"
|
||||
|
||||
|
||||
@register.filter(is_safe=True)
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import re
|
||||
|
||||
from django import template
|
||||
from django.template.defaultfilters import stringfilter
|
||||
from django.utils.safestring import mark_safe
|
||||
|
@ -31,7 +29,7 @@ def highlight(text, search):
|
|||
m = None
|
||||
for w in words:
|
||||
if otext[i : i + len(w)] == w:
|
||||
m = f"<mark>{text[i:i+len(w)]}</mark>"
|
||||
m = f"<mark>{text[i : i + len(w)]}</mark>"
|
||||
i += len(w)
|
||||
break
|
||||
if not m:
|
||||
|
|
|
@ -5,10 +5,9 @@ from typing import TYPE_CHECKING
|
|||
import django_rq
|
||||
from discord import SyncWebhook
|
||||
from django.conf import settings
|
||||
from django.conf.locale import LANG_INFO
|
||||
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
|
||||
from django.core.paginator import Paginator
|
||||
from django.core.signing import b62_decode, b62_encode
|
||||
from django.core.signing import b62_decode
|
||||
from django.http import Http404, HttpRequest, HttpResponseRedirect, QueryDict
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext as _
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
|
|
|
@ -14,7 +14,6 @@ from .models import (
|
|||
Review,
|
||||
ShelfType,
|
||||
Tag,
|
||||
TagManager,
|
||||
q_item_in_category,
|
||||
)
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ class JournalConfig(AppConfig):
|
|||
# load key modules in proper order, make sure class inject and signal works as expected
|
||||
from catalog.models import Indexer
|
||||
|
||||
from . import api
|
||||
from .models import Rating, Tag
|
||||
|
||||
Indexer.register_list_model(Tag)
|
||||
|
|
|
@ -35,7 +35,7 @@ def _fetch_remote_image(url):
|
|||
# logger.info(f'remote image saved as {local_url}')
|
||||
return local_url
|
||||
except Exception as e:
|
||||
logger.error(f"unable to fetch image", extra={"url": url, "exception": e})
|
||||
logger.error("unable to fetch image", extra={"url": url, "exception": e})
|
||||
return url
|
||||
|
||||
|
||||
|
@ -140,7 +140,7 @@ class DoubanImporter(Task):
|
|||
timestamp
|
||||
- (
|
||||
datetime.strptime(c[1], "%Y-%m-%d %H:%M:%S")
|
||||
if type(c[1]) == str
|
||||
if isinstance(c[1], str)
|
||||
else c[1]
|
||||
).replace(tzinfo=_tz_sh)
|
||||
)
|
||||
|
@ -161,7 +161,7 @@ class DoubanImporter(Task):
|
|||
self.import_review_sheet(self.review_data[name], name)
|
||||
self.message = f"豆瓣标记和评论导入完成,共处理{self.metadata['total']}篇,已存在{self.metadata['skipped']}篇,新增{self.metadata['imported']}篇。"
|
||||
if len(self.metadata["failed_urls"]) > 0:
|
||||
self.message += f'导入时未能处理{len(self.metadata["failed_urls"])}个网址。'
|
||||
self.message += f"导入时未能处理{len(self.metadata['failed_urls'])}个网址。"
|
||||
self.save()
|
||||
|
||||
def import_mark_sheet(self, worksheet, shelf_type, sheet_name):
|
||||
|
@ -188,7 +188,7 @@ class DoubanImporter(Task):
|
|||
comment = cells[7] if len(cells) >= 8 else None
|
||||
self.metadata["processed"] += 1
|
||||
try:
|
||||
if type(time) == str:
|
||||
if isinstance(time, str):
|
||||
time = datetime.strptime(time, "%Y-%m-%d %H:%M:%S")
|
||||
time = time.replace(tzinfo=_tz_sh)
|
||||
except Exception:
|
||||
|
@ -248,7 +248,7 @@ class DoubanImporter(Task):
|
|||
content = cells[6]
|
||||
self.metadata["processed"] += 1
|
||||
if time:
|
||||
if type(time) == str:
|
||||
if isinstance(time, str):
|
||||
time = datetime.strptime(time, "%Y-%m-%d %H:%M:%S")
|
||||
time = time.replace(tzinfo=_tz_sh)
|
||||
else:
|
||||
|
@ -271,7 +271,7 @@ class DoubanImporter(Task):
|
|||
def get_item_by_url(self, url):
|
||||
item = None
|
||||
if not url:
|
||||
logger.warning(f"URL empty")
|
||||
logger.warning("URL empty")
|
||||
return None
|
||||
try:
|
||||
site = SiteManager.get_site_by_url(url)
|
||||
|
|
|
@ -75,7 +75,7 @@ class GoodreadsImporter(Task):
|
|||
collection.append_item(book["book"], note=book["review"])
|
||||
total += 1
|
||||
collection.save()
|
||||
self.message = f'Imported {total} books from Goodreads as a Collection {shelf["title"]}.'
|
||||
self.message = f"Imported {total} books from Goodreads as a Collection {shelf['title']}."
|
||||
elif match_profile:
|
||||
uid = match_profile[1]
|
||||
shelves = {
|
||||
|
@ -103,7 +103,7 @@ class GoodreadsImporter(Task):
|
|||
)
|
||||
):
|
||||
print(
|
||||
f'Skip {shelf_type}/{book["book"]} bc it was marked {mark.shelf_type}'
|
||||
f"Skip {shelf_type}/{book['book']} bc it was marked {mark.shelf_type}"
|
||||
)
|
||||
else:
|
||||
mark.update(
|
||||
|
|
|
@ -28,13 +28,13 @@ class Command(BaseCommand):
|
|||
if options["export"]:
|
||||
self.process_export(options["export"])
|
||||
|
||||
self.stderr.write(self.style.SUCCESS(f"Done."))
|
||||
self.stderr.write(self.style.SUCCESS("Done."))
|
||||
|
||||
def process_export(self, collection_uuid):
|
||||
try:
|
||||
collection = Collection.objects.get(uid=get_uuid_or_404(collection_uuid))
|
||||
except Collection.DoesNotExist:
|
||||
self.stderr.write(self.style.ERROR(f"Collection not found."))
|
||||
self.stderr.write(self.style.ERROR("Collection not found."))
|
||||
return
|
||||
self.stderr.write(self.style.SUCCESS(f"Exporting {collection}"))
|
||||
data = {
|
||||
|
|
|
@ -99,12 +99,12 @@ class Command(BaseCommand):
|
|||
)
|
||||
|
||||
def integrity(self):
|
||||
self.stdout.write(f"Checking deleted items with remaining journals...")
|
||||
self.stdout.write("Checking deleted items with remaining journals...")
|
||||
for i in Item.objects.filter(is_deleted=True):
|
||||
if i.journal_exists():
|
||||
self.stdout.write(f"! {i} : {i.absolute_url}?skipcheck=1")
|
||||
|
||||
self.stdout.write(f"Checking merged items with remaining journals...")
|
||||
self.stdout.write("Checking merged items with remaining journals...")
|
||||
for i in Item.objects.filter(merged_to_item__isnull=False):
|
||||
if i.journal_exists():
|
||||
self.stdout.write(f"! {i} : {i.absolute_url}?skipcheck=1")
|
||||
|
@ -143,14 +143,14 @@ class Command(BaseCommand):
|
|||
match action:
|
||||
case "integrity":
|
||||
self.integrity()
|
||||
self.stdout.write(self.style.SUCCESS(f"Done."))
|
||||
self.stdout.write(self.style.SUCCESS("Done."))
|
||||
|
||||
case "purge":
|
||||
for pcls in [Content, ListMember]:
|
||||
for cls in pcls.__subclasses__():
|
||||
self.stdout.write(f"Cleaning up {cls}...")
|
||||
cls.objects.filter(visibility=99).delete()
|
||||
self.stdout.write(self.style.SUCCESS(f"Done."))
|
||||
self.stdout.write(self.style.SUCCESS("Done."))
|
||||
|
||||
case "idx-destroy":
|
||||
if yes or input(_CONFIRM).upper().startswith("Y"):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from auditlog.context import set_actor
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db.models import Count, F, Q
|
||||
from django.db.models import Count
|
||||
from django.utils.translation import gettext_lazy as t
|
||||
|
||||
from catalog.models import *
|
||||
|
|
|
@ -5,7 +5,6 @@ from django.db import migrations, models
|
|||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("takahe", "0001_initial"),
|
||||
("journal", "0015_use_identity_support_remote_piece"),
|
||||
|
|
|
@ -4,7 +4,6 @@ from django.db import migrations
|
|||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("journal", "0016_piecepost_piece_posts_piecepost_unique_piece_post"),
|
||||
]
|
||||
|
|
|
@ -5,7 +5,6 @@ from django.db import migrations, models
|
|||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("takahe", "0001_initial"),
|
||||
("journal", "0017_alter_piece_options_and_more"),
|
||||
|
|
|
@ -4,7 +4,6 @@ from django.db import migrations, models
|
|||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("journal", "0018_shelflogentrypost_shelflogentry_posts_and_more"),
|
||||
]
|
||||
|
|
|
@ -12,7 +12,6 @@ WHERE a.ctid < b.ctid
|
|||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("journal", "0019_alter_collection_edited_time_and_more"),
|
||||
]
|
||||
|
|
|
@ -4,7 +4,6 @@ from django.db import migrations
|
|||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("users", "0019_task"),
|
||||
("journal", "0021_pieceinteraction_pieceinteraction_unique_interaction"),
|
||||
|
|
|
@ -4,7 +4,6 @@ from django.db import migrations, models
|
|||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("journal", "0023_debris"),
|
||||
]
|
||||
|
|
|
@ -4,7 +4,6 @@ from django.db import migrations, models
|
|||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("journal", "0025_pin_tags"),
|
||||
]
|
||||
|
|
|
@ -33,6 +33,7 @@ from .utils import (
|
|||
__all__ = [
|
||||
"Collection",
|
||||
"CollectionMember",
|
||||
"Content",
|
||||
"FeaturedCollection",
|
||||
"Comment",
|
||||
"JournalIndex",
|
||||
|
|
|
@ -105,8 +105,6 @@ class Collection(List):
|
|||
)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
from takahe.utils import Takahe
|
||||
|
||||
if getattr(self, "catalog_item", None) is None:
|
||||
self.catalog_item = CatalogCollection()
|
||||
if (
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from functools import cached_property
|
||||
from typing import TYPE_CHECKING, Self
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import django.dispatch
|
||||
from django.db import models
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db import connection, models
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from users.models import APIdentity
|
||||
|
||||
|
|
|
@ -2,13 +2,10 @@ import re
|
|||
from functools import cached_property
|
||||
from typing import Any, override
|
||||
|
||||
from deepmerge import always_merger
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from loguru import logger
|
||||
|
||||
from catalog.models import Item
|
||||
from takahe.utils import Takahe
|
||||
|
||||
from .common import Content
|
||||
from .renderers import render_text
|
||||
|
|
|
@ -3,8 +3,7 @@ from typing import Any
|
|||
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
from django.db.models import Avg, Count, Q
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.db.models import Avg, Count
|
||||
|
||||
from catalog.models import Item
|
||||
from takahe.utils import Takahe
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from datetime import datetime
|
||||
from functools import cached_property
|
||||
from typing import TYPE_CHECKING, Any, override
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import connection, models
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
import re
|
||||
from datetime import timedelta
|
||||
from functools import cached_property
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
|
||||
from django.db import connection, models
|
||||
from django.db.models import Avg, Count, F, Q
|
||||
from django.core.validators import RegexValidator
|
||||
from django.db import models
|
||||
from django.db.models import Count, F
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from catalog.collection.models import Collection as CatalogCollection
|
||||
from catalog.models import Item
|
||||
from users.models import APIdentity
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
from auditlog.context import set_actor
|
||||
from django.db import transaction
|
||||
from django.db.utils import IntegrityError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from loguru import logger
|
||||
|
||||
from catalog.models import Item
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from django import template
|
||||
from django.template.defaultfilters import stringfilter
|
||||
from django.utils.translation import ngettext
|
||||
|
||||
from journal.models import Collection
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
from django import template
|
||||
from django.urls import reverse
|
||||
|
||||
from journal.models.mark import Mark
|
||||
from takahe.utils import Takahe
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
|
|
@ -32,3 +32,48 @@ from .review import ReviewFeed, review_edit, review_retrieve, user_review_list
|
|||
from .search import search
|
||||
from .tag import user_tag_edit, user_tag_list, user_tag_member_list
|
||||
from .wrapped import WrappedShareView, WrappedView
|
||||
|
||||
|
||||
__all__ = [
|
||||
"add_to_collection",
|
||||
"collection_add_featured",
|
||||
"collection_append_item",
|
||||
"collection_edit",
|
||||
"collection_move_item",
|
||||
"collection_remove_featured",
|
||||
"collection_remove_item",
|
||||
"collection_retrieve",
|
||||
"collection_retrieve_items",
|
||||
"collection_retrieve_redirect",
|
||||
"collection_share",
|
||||
"collection_update_item_note",
|
||||
"collection_update_member_order",
|
||||
"user_collection_list",
|
||||
"user_liked_collection_list",
|
||||
"piece_delete",
|
||||
"comment",
|
||||
"mark",
|
||||
"mark_log",
|
||||
"user_mark_list",
|
||||
"wish",
|
||||
"note_edit",
|
||||
"piece_replies",
|
||||
"post_boost",
|
||||
"post_delete",
|
||||
"post_like",
|
||||
"post_replies",
|
||||
"post_reply",
|
||||
"post_unlike",
|
||||
"profile",
|
||||
"user_calendar_data",
|
||||
"ReviewFeed",
|
||||
"review_edit",
|
||||
"review_retrieve",
|
||||
"user_review_list",
|
||||
"search",
|
||||
"user_tag_edit",
|
||||
"user_tag_list",
|
||||
"user_tag_member_list",
|
||||
"WrappedShareView",
|
||||
"WrappedView",
|
||||
]
|
||||
|
|
|
@ -2,7 +2,6 @@ import datetime
|
|||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.exceptions import BadRequest, PermissionDenied
|
||||
from django.core.paginator import Paginator
|
||||
from django.db.models import F, Min, OuterRef, Subquery
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
from datetime import datetime
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.exceptions import BadRequest, ObjectDoesNotExist, PermissionDenied
|
||||
from django.core.exceptions import BadRequest, PermissionDenied
|
||||
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.utils import timezone
|
||||
from django.utils.dateparse import parse_datetime
|
||||
from django.utils.translation import gettext as _
|
||||
|
@ -15,8 +14,8 @@ from loguru import logger
|
|||
from catalog.models import *
|
||||
from common.utils import AuthedHttpRequest, get_uuid_or_404
|
||||
|
||||
from ..models import Comment, Mark, ShelfManager, ShelfType, TagManager
|
||||
from .common import render_list, render_relogin, target_identity_required
|
||||
from ..models import Comment, Mark, ShelfManager, ShelfType
|
||||
from .common import render_list, render_relogin
|
||||
|
||||
PAGE_SIZE = 10
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from django import forms
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.exceptions import BadRequest, ObjectDoesNotExist, PermissionDenied
|
||||
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.core.exceptions import BadRequest
|
||||
from django.http import Http404, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.decorators.http import require_http_methods
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.exceptions import BadRequest, ObjectDoesNotExist, PermissionDenied
|
||||
from django.core.exceptions import BadRequest, PermissionDenied
|
||||
from django.http import Http404
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views.decorators.http import require_http_methods
|
||||
|
||||
from common.utils import AuthedHttpRequest, get_uuid_or_404, target_identity_required
|
||||
from common.utils import AuthedHttpRequest, get_uuid_or_404
|
||||
from takahe.utils import Takahe
|
||||
|
||||
from ..forms import *
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.http import Http404, HttpResponseRedirect
|
||||
from django.shortcuts import redirect, render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views.decorators.http import require_http_methods
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
from os import link
|
||||
|
||||
from django.db import models
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue