fix unicode site name; add isort; split journal and users models

This commit is contained in:
Your Name 2023-08-10 11:27:31 -04:00 committed by Henri Dickson
parent 4e7583d6f1
commit 22640a74ab
163 changed files with 2318 additions and 1918 deletions

View file

@ -12,8 +12,13 @@ repos:
language_version: python3.11 language_version: python3.11
repos: repos:
- repo: https://github.com/Riverside-Healthcare/djLint - repo: https://github.com/Riverside-Healthcare/djLint
rev: v1.30.2 rev: v1.32.1
hooks: hooks:
- id: djlint-reformat-django - id: djlint-reformat-django
- id: djlint-django - id: djlint-django
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
args: ["--profile=black"]

View file

@ -1,5 +1,7 @@
import os import os
NEODB_VERSION = "0.8"
PROJECT_ROOT = os.path.abspath(os.path.dirname(__name__)) PROJECT_ROOT = os.path.abspath(os.path.dirname(__name__))
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)

View file

@ -13,13 +13,14 @@ Including another URLconf
1. Import the include() function: from django.urls import include, path 1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
""" """
from django.contrib import admin
from django.urls import path, include
from django.conf import settings from django.conf import settings
from users.views import login from django.contrib import admin
from common.api import api from django.urls import include, path
from django.views.generic import RedirectView from django.views.generic import RedirectView
from common.api import api
from users.views import login
urlpatterns = [ urlpatterns = [
path("api/", api.urls), # type: ignore path("api/", api.urls), # type: ignore
path("login/", login), path("login/", login),

View file

@ -1,12 +1,13 @@
from django.http import Http404, HttpResponse
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.http import HttpResponse
from django.http import Http404
from ninja import Schema from ninja import Schema
from common.api import * from common.api import *
from .models import *
from .common import * from .common import *
from .models import *
from .search.models import enqueue_fetch, get_fetch_lock, query_index
from .sites import * from .sites import *
from .search.models import enqueue_fetch, query_index, get_fetch_lock
class SearchResult(Schema): class SearchResult(Schema):

View file

@ -7,11 +7,9 @@ class CatalogConfig(AppConfig):
def ready(self): def ready(self):
# load key modules in proper order, make sure class inject and signal works as expected # load key modules in proper order, make sure class inject and signal works as expected
from catalog import models from catalog import api, models, sites
from catalog import sites from catalog.models import init_catalog_audit_log, init_catalog_search_models
from journal import models as journal_models from journal import models as journal_models
from catalog.models import init_catalog_search_models, init_catalog_audit_log
from catalog import api
init_catalog_search_models() init_catalog_search_models()
init_catalog_audit_log() init_catalog_audit_log()

View file

@ -20,7 +20,9 @@ work data seems asymmetric (a book links to a work, but may not listed in that w
from django.core.validators import MaxValueValidator, MinValueValidator from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from catalog.common.models import * from catalog.common.models import *
from .utils import * from .utils import *

View file

@ -1,4 +1,5 @@
from django.test import TestCase from django.test import TestCase
from catalog.book.models import * from catalog.book.models import *
from catalog.book.utils import * from catalog.book.utils import *
from catalog.common import * from catalog.common import *

View file

@ -1,4 +1,5 @@
import re import re
from .models import IdType from .models import IdType

View file

@ -1,9 +1,8 @@
from .models import *
from .sites import *
from .downloaders import *
from .scrapers import *
from . import jsondata from . import jsondata
from .downloaders import *
from .models import *
from .scrapers import *
from .sites import *
__all__ = ( __all__ = (
"IdType", "IdType",

View file

@ -1,18 +1,18 @@
import requests
import filetype
from PIL import Image
from io import BytesIO
from requests.exceptions import RequestException
from django.conf import settings
from pathlib import Path
import json import json
from io import StringIO import logging
import re import re
import time import time
import logging from io import BytesIO, StringIO
from lxml import html from pathlib import Path
from urllib.parse import quote from urllib.parse import quote
import filetype
import requests
from django.conf import settings
from lxml import html
from PIL import Image
from requests.exceptions import RequestException
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,22 +1,20 @@
import copy import copy
from datetime import date, datetime from datetime import date, datetime
from importlib import import_module
from functools import partialmethod from functools import partialmethod
from django.utils.translation import gettext_lazy as _ from importlib import import_module
import django import django
from django.core.exceptions import FieldError from django.core.exceptions import FieldError
from django.db.models import fields from django.db.models import fields
from django.utils import dateparse, timezone from django.utils import dateparse, timezone
from django.utils.translation import gettext_lazy as _
# from django.contrib.postgres.fields import ArrayField as DJANGO_ArrayField
from django_jsonform.models.fields import ArrayField as DJANGO_ArrayField
# from django.db.models import JSONField as DJANGO_JSONField # from django.db.models import JSONField as DJANGO_JSONField
# from jsoneditor.fields.django3_jsonfield import JSONField as DJANGO_JSONField # from jsoneditor.fields.django3_jsonfield import JSONField as DJANGO_JSONField
# 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 django_jsonform.models.fields import JSONField as DJANGO_JSONField
__all__ = ( __all__ = (
"BooleanField", "BooleanField",
"CharField", "CharField",

View file

@ -1,29 +1,32 @@
from functools import cached_property
from polymorphic.models import PolymorphicModel
from django.db import models
import logging import logging
import re import re
from catalog.common import jsondata
from django.utils.translation import gettext_lazy as _
from django.utils import timezone
from django.core.files.uploadedfile import SimpleUploadedFile
from django.contrib.contenttypes.models import ContentType
from django.utils.baseconv import base62
import uuid import uuid
from functools import cached_property
from typing import cast from typing import cast
from .utils import DEFAULT_ITEM_COVER, item_cover_path, resource_cover_path
from .mixins import SoftDeleteMixin
from django.conf import settings
from users.models import User
from django.db import connection
from ninja import Schema
from auditlog.context import disable_auditlog from auditlog.context import disable_auditlog
from auditlog.models import LogEntry, AuditlogHistoryField from auditlog.models import AuditlogHistoryField, LogEntry
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.core.files.uploadedfile import SimpleUploadedFile
from django.db import connection, models
from django.utils import timezone
from django.utils.baseconv import base62
from django.utils.translation import gettext_lazy as _
from ninja import Schema
from polymorphic.models import PolymorphicModel
from catalog.common import jsondata
from users.models import User
from .mixins import SoftDeleteMixin
from .utils import DEFAULT_ITEM_COVER, item_cover_path, resource_cover_path
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class SiteName(models.TextChoices): class SiteName(models.TextChoices):
Unknown = "unknown", _("未知站点")
Douban = "douban", _("豆瓣") Douban = "douban", _("豆瓣")
Goodreads = "goodreads", _("Goodreads") Goodreads = "goodreads", _("Goodreads")
GoogleBooks = "googlebooks", _("谷歌图书") GoogleBooks = "googlebooks", _("谷歌图书")
@ -482,6 +485,35 @@ class Item(SoftDeleteMixin, PolymorphicModel):
def editable(self): def editable(self):
return not self.is_deleted and self.merged_to_item is None return not self.is_deleted and self.merged_to_item is None
@property
def rating(self):
from journal.models import Rating
return Rating.get_rating_for_item(self)
@property
def rating_count(self):
from journal.models import Rating
return Rating.get_rating_count_for_item(self)
@property
def rating_dist(self):
from journal.models import Rating
return Rating.get_rating_distribution_for_item(self)
@property
def tags(self):
from journal.models import TagManager
return TagManager.indexable_tags_for_item(self)
def journal_exists(self):
from journal.models import journal_exists_for_item
return journal_exists_for_item(self)
class ItemLookupId(models.Model): class ItemLookupId(models.Model):
item = models.ForeignKey( item = models.ForeignKey(
@ -542,12 +574,17 @@ class ExternalResource(models.Model):
self.save() self.save()
def get_site(self): def get_site(self):
"""place holder only, this will be injected from SiteManager""" from .sites import SiteManager
pass
return SiteManager.get_site_cls_by_id_type(self.id_type)
@property @property
def site_name(self): def site_name(self):
return getattr(self.get_site(), "SITE_NAME") try:
return self.get_site().SITE_NAME
except:
_logger.warning(f"Unknown site for {self}")
return SiteName.Unknown
def update_content(self, resource_content): def update_content(self, resource_content):
self.other_lookup_ids = resource_content.lookup_ids self.other_lookup_ids = resource_content.lookup_ids

View file

@ -6,14 +6,15 @@ a Site should map to a unique set of url patterns.
a Site may scrape a url and store result in ResourceContent a Site may scrape a url and store result in ResourceContent
ResourceContent persists as an ExternalResource which may link to an Item ResourceContent persists as an ExternalResource which may link to an Item
""" """
from typing import Callable
import re
from .models import ExternalResource, IdType, IdealIdTypes, Item
from dataclasses import dataclass, field
import logging
import json import json
import logging
import re
from dataclasses import dataclass, field
from typing import Callable
import django_rq import django_rq
from .models import ExternalResource, IdealIdTypes, IdType, Item
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@ -297,11 +298,6 @@ class SiteManager:
return SiteManager.register.values() return SiteManager.register.values()
ExternalResource.get_site = lambda resource: SiteManager.get_site_cls_by_id_type(
resource.id_type
) # type: ignore
def crawl_related_resources_task(resource_pk): def crawl_related_resources_task(resource_pk):
resource = ExternalResource.objects.filter(pk=resource_pk).first() resource = ExternalResource.objects.filter(pk=resource_pk).first()
if not resource: if not resource:

View file

@ -1,7 +1,7 @@
import logging import logging
from django.utils import timezone
import uuid import uuid
from django.utils import timezone
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,9 +1,9 @@
from django import forms from django import forms
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from catalog.models import * from catalog.models import *
from common.forms import PreviewImageInput from common.forms import PreviewImageInput
CatalogForms = {} CatalogForms = {}

View file

@ -1,7 +1,9 @@
from datetime import date from datetime import date
from catalog.common.models import *
from django.utils.translation import gettext_lazy as _
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _
from catalog.common.models import *
class GameInSchema(ItemInSchema): class GameInSchema(ItemInSchema):

View file

@ -1,4 +1,5 @@
from django.test import TestCase from django.test import TestCase
from catalog.common import * from catalog.common import *
from catalog.models import * from catalog.models import *

View file

@ -1,5 +1,7 @@
from django.core.management.base import BaseCommand
import pprint import pprint
from django.core.management.base import BaseCommand
from catalog.common import SiteManager from catalog.common import SiteManager
from catalog.sites import * from catalog.sites import *

View file

@ -1,6 +1,8 @@
import pprint
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.db.models import Count, F from django.db.models import Count, F
import pprint
from catalog.models import * from catalog.models import *
from journal.models import update_journal_for_merged_item from journal.models import update_journal_for_merged_item

View file

@ -1,9 +1,11 @@
from django.core.management.base import BaseCommand
from catalog.common import *
import re import re
from urllib.parse import urljoin from urllib.parse import urljoin
from django.core.management.base import BaseCommand
from loguru import logger from loguru import logger
from catalog.common import *
class Command(BaseCommand): class Command(BaseCommand):
help = "Crawl content" help = "Crawl content"

View file

@ -1,12 +1,14 @@
from django.core.management.base import BaseCommand
from django.core.cache import cache
from catalog.models import *
from journal.models import ShelfMember, query_item_category, ItemCategory, Comment
from datetime import timedelta from datetime import timedelta
from django.utils import timezone
from django.core.cache import cache
from django.core.management.base import BaseCommand
from django.db.models import Count, F from django.db.models import Count, F
from django.utils import timezone
from loguru import logger from loguru import logger
from catalog.models import *
from journal.models import Comment, ItemCategory, ShelfMember, query_item_category
MAX_ITEMS_PER_PERIOD = 12 MAX_ITEMS_PER_PERIOD = 12
MIN_MARKS = 2 MIN_MARKS = 2
MAX_DAYS_FOR_PERIOD = 96 MAX_DAYS_FOR_PERIOD = 96

View file

@ -1,12 +1,14 @@
from django.core.management.base import BaseCommand
from django.conf import settings
from catalog.models import *
import pprint import pprint
from django.core.paginator import Paginator
from tqdm import tqdm
from time import sleep
from datetime import timedelta from datetime import timedelta
from time import sleep
from django.conf import settings
from django.core.management.base import BaseCommand
from django.core.paginator import Paginator
from django.utils import timezone from django.utils import timezone
from tqdm import tqdm
from catalog.models import *
BATCH_SIZE = 1000 BATCH_SIZE = 1000

View file

@ -1,15 +1,17 @@
from django.core.management.base import BaseCommand import pprint
from datetime import timedelta
from time import sleep
from django.conf import settings from django.conf import settings
from django.core.management.base import BaseCommand
from django.core.paginator import Paginator
from django.utils import timezone
from loguru import logger
from tqdm import tqdm
from catalog.common.models import IdType from catalog.common.models import IdType
from catalog.models import * from catalog.models import *
from catalog.sites import RSS from catalog.sites import RSS
import pprint
from django.core.paginator import Paginator
from tqdm import tqdm
from time import sleep
from datetime import timedelta
from django.utils import timezone
from loguru import logger
class Command(BaseCommand): class Command(BaseCommand):

View file

@ -1,11 +1,13 @@
# Generated by Django 3.2.16 on 2023-01-12 01:32 # Generated by Django 3.2.16 on 2023-01-12 01:32
import uuid
import django.db.models.deletion
import simple_history.models
from django.db import migrations, models
import catalog.common.mixins import catalog.common.mixins
import catalog.common.utils import catalog.common.utils
from django.db import migrations, models
import django.db.models.deletion
import simple_history.models
import uuid
class Migration(migrations.Migration): class Migration(migrations.Migration):

View file

@ -1,8 +1,8 @@
# Generated by Django 3.2.16 on 2023-01-12 01:32 # Generated by Django 3.2.16 on 2023-01-12 01:32
import django.db.models.deletion
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):

View file

@ -1,7 +1,7 @@
# Generated by Django 3.2.16 on 2023-02-02 03:47 # Generated by Django 3.2.16 on 2023-02-02 03:47
from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):

View file

@ -1,7 +1,7 @@
# Generated by Django 3.2.16 on 2023-02-03 21:58 # Generated by Django 3.2.16 on 2023-02-03 21:58
from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):

View file

@ -1,7 +1,7 @@
# Generated by Django 3.2.19 on 2023-06-05 02:31 # Generated by Django 3.2.19 on 2023-06-05 02:31
from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):

View file

@ -1,7 +1,7 @@
# Generated by Django 4.2.3 on 2023-07-06 22:53 # Generated by Django 4.2.3 on 2023-07-06 22:53
from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):

View file

@ -1,37 +1,41 @@
import logging
from auditlog.registry import auditlog
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from .book.models import Edition, EditionInSchema, EditionSchema, Series, Work
from .collection.models import Collection as CatalogCollection
from .common.models import ( from .common.models import (
ExternalResource, ExternalResource,
Item, Item,
ItemCategory,
ItemSchema, ItemSchema,
item_content_types,
item_categories, item_categories,
item_content_types,
) )
from .book.models import Edition, Work, Series, EditionSchema, EditionInSchema from .game.models import Game, GameInSchema, GameSchema
from .movie.models import Movie, MovieSchema, MovieInSchema from .movie.models import Movie, MovieInSchema, MovieSchema
from .tv.models import ( from .music.models import Album, AlbumInSchema, AlbumSchema
TVShow,
TVSeason,
TVEpisode,
TVShowSchema,
TVShowInSchema,
TVSeasonSchema,
TVSeasonInSchema,
TVEpisodeSchema,
)
from .music.models import Album, AlbumSchema, AlbumInSchema
from .game.models import Game, GameSchema, GameInSchema
from .podcast.models import Podcast, PodcastSchema, PodcastInSchema, PodcastEpisode
from .performance.models import ( from .performance.models import (
Performance, Performance,
PerformanceProduction, PerformanceProduction,
PerformanceSchema,
PerformanceProductionSchema, PerformanceProductionSchema,
PerformanceSchema,
) )
from .collection.models import Collection as CatalogCollection from .podcast.models import Podcast, PodcastEpisode, PodcastInSchema, PodcastSchema
from .search.models import Indexer from .tv.models import (
from django.contrib.contenttypes.models import ContentType TVEpisode,
from django.conf import settings TVEpisodeSchema,
import logging TVSeason,
from auditlog.registry import auditlog TVSeasonInSchema,
TVSeasonSchema,
TVShow,
TVShowInSchema,
TVShowSchema,
)
from .search.models import Indexer # isort:skip
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,6 +1,7 @@
from catalog.common.models import *
from django.utils.translation import gettext_lazy as _
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _
from catalog.common.models import *
class MovieInSchema(ItemInSchema): class MovieInSchema(ItemInSchema):

View file

@ -1,4 +1,5 @@
from django.test import TestCase from django.test import TestCase
from catalog.common import * from catalog.common import *

View file

@ -1,7 +1,9 @@
from datetime import date from datetime import date
from catalog.common.models import *
from django.utils.translation import gettext_lazy as _
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _
from catalog.common.models import *
class AlbumInSchema(ItemInSchema): class AlbumInSchema(ItemInSchema):

View file

@ -1,4 +1,5 @@
from django.test import TestCase from django.test import TestCase
from catalog.common import * from catalog.common import *
from catalog.models import * from catalog.models import *
from catalog.music.utils import * from catalog.music.utils import *

View file

@ -1,10 +1,12 @@
from functools import cached_property from functools import cached_property
from django.utils.translation import gettext_lazy as _
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _
from ninja import Schema
from catalog.common import * from catalog.common import *
from catalog.common.models import ItemSchema from catalog.common.models import ItemSchema
from catalog.common.utils import DEFAULT_ITEM_COVER from catalog.common.utils import DEFAULT_ITEM_COVER
from ninja import Schema
class CrewMemberSchema(Schema): class CrewMemberSchema(Schema):

View file

@ -1,7 +1,8 @@
from catalog.common.models import *
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from catalog.common.models import *
class PodcastInSchema(ItemInSchema): class PodcastInSchema(ItemInSchema):
genre: list[str] genre: list[str]

View file

@ -1,7 +1,7 @@
from django.test import TestCase from django.test import TestCase
from catalog.podcast.models import *
from catalog.common import *
from catalog.common import *
from catalog.podcast.models import *
# class ApplePodcastTestCase(TestCase): # class ApplePodcastTestCase(TestCase):
# def setUp(self): # def setUp(self):

View file

@ -1,11 +1,13 @@
import logging
from urllib.parse import quote_plus from urllib.parse import quote_plus
import requests
from django.conf import settings from django.conf import settings
from lxml import html
from catalog.common import * from catalog.common import *
from catalog.models import * from catalog.models import *
from catalog.sites.spotify import get_spotify_token from catalog.sites.spotify import get_spotify_token
import requests
from lxml import html
import logging
SEARCH_PAGE_SIZE = 5 # not all apis support page size SEARCH_PAGE_SIZE = 5 # not all apis support page size
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View file

@ -1,15 +1,17 @@
import logging
from django.utils.translation import gettext_lazy as _
from catalog.common.sites import SiteManager
from ..models import TVSeason, Item
from django.conf import settings
import django_rq
from rq.job import Job
from django.core.cache import cache
import hashlib import hashlib
from .typesense import Indexer as TypeSenseIndexer import logging
import django_rq
from auditlog.context import set_actor from auditlog.context import set_actor
from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
from django.utils.translation import gettext_lazy as _
from rq.job import Job
from catalog.common.sites import SiteManager
from ..models import Item, TVSeason
from .typesense import Indexer as TypeSenseIndexer
# from .meilisearch import Indexer as MeiliSearchIndexer # from .meilisearch import Indexer as MeiliSearchIndexer

View file

@ -1,16 +1,18 @@
from datetime import timedelta
import types
import logging import logging
import typesense import types
from typesense.exceptions import ObjectNotFound from datetime import timedelta
from typesense.collection import Collection
from django.conf import settings
from django.db.models.signals import post_save, post_delete
from catalog.models import Item
from pprint import pprint from pprint import pprint
import django_rq import django_rq
from rq.job import Job import typesense
from django.conf import settings
from django.db.models.signals import post_delete, post_save
from django_redis import get_redis_connection from django_redis import get_redis_connection
from rq.job import Job
from typesense.collection import Collection
from typesense.exceptions import ObjectNotFound
from catalog.models import Item
INDEX_NAME = "catalog" INDEX_NAME = "catalog"
SEARCHABLE_ATTRIBUTES = [ SEARCHABLE_ATTRIBUTES = [

View file

@ -1,22 +1,21 @@
from ..common.sites import SiteManager from ..common.sites import SiteManager
from .apple_music import AppleMusic
from .bandcamp import Bandcamp
from .bangumi import Bangumi
from .bookstw import BooksTW
from .discogs import DiscogsMaster, DiscogsRelease
from .douban_book import DoubanBook
from .douban_drama import DoubanDrama
from .douban_game import DoubanGame
from .douban_movie import DoubanMovie
from .douban_music import DoubanMusic
from .goodreads import Goodreads
from .google_books import GoogleBooks
from .igdb import IGDB
from .imdb import IMDB
# from .apple_podcast import ApplePodcast # from .apple_podcast import ApplePodcast
from .rss import RSS from .rss import RSS
from .douban_book import DoubanBook
from .douban_movie import DoubanMovie
from .douban_music import DoubanMusic
from .douban_game import DoubanGame
from .douban_drama import DoubanDrama
from .goodreads import Goodreads
from .google_books import GoogleBooks
from .tmdb import TMDB_Movie
from .imdb import IMDB
from .spotify import Spotify from .spotify import Spotify
from .igdb import IGDB
from .steam import Steam from .steam import Steam
from .bandcamp import Bandcamp from .tmdb import TMDB_Movie
from .bangumi import Bangumi
from .discogs import DiscogsRelease
from .discogs import DiscogsMaster
from .bookstw import BooksTW
from .apple_music import AppleMusic

View file

@ -1,6 +1,8 @@
import logging
from catalog.common import * from catalog.common import *
from catalog.models import * from catalog.models import *
import logging
from .rss import RSS from .rss import RSS
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,11 +1,12 @@
import json
import logging
import re
import urllib.parse
import dateparser
from catalog.common import * from catalog.common import *
from catalog.models import * from catalog.models import *
import logging
import urllib.parse
import dateparser
import re
import json
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,7 +1,7 @@
from catalog.common import *
from catalog.models import *
import logging import logging
from catalog.common import *
from catalog.models import *
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,9 +1,10 @@
from catalog.common import *
from catalog.book.models import *
from catalog.book.utils import *
from .douban import *
import logging import logging
from catalog.book.models import *
from catalog.book.utils import *
from catalog.common import *
from .douban import *
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,15 +1,17 @@
""" """
Discogs. Discogs.
""" """
import json
import logging
import requests
from django.conf import settings from django.conf import settings
from catalog.common import * from catalog.common import *
from catalog.models import * from catalog.models import *
from catalog.music.utils import upc_to_gtin_13 from catalog.music.utils import upc_to_gtin_13
from .douban import *
import json
import logging
import requests
from .douban import *
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,6 +1,6 @@
import re import re
from catalog.common import *
from catalog.common import *
RE_NUMBERS = re.compile(r"\d+\d*") RE_NUMBERS = re.compile(r"\d+\d*")
RE_WHITESPACES = re.compile(r"\s+") RE_WHITESPACES = re.compile(r"\s+")

View file

@ -1,12 +1,13 @@
from django.utils.timezone import make_aware
from datetime import datetime
from catalog.book.models import Edition, Work
from catalog.common import *
from catalog.book.utils import detect_isbn_asin
from lxml import html
import json import json
import logging import logging
from datetime import datetime
from django.utils.timezone import make_aware
from lxml import html
from catalog.book.models import Edition, Work
from catalog.book.utils import detect_isbn_asin
from catalog.common import *
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,8 +1,8 @@
import logging
import re
from catalog.common import * from catalog.common import *
from catalog.models import * from catalog.models import *
import re
import logging
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -4,15 +4,16 @@ IGDB
use (e.g. "portal-2") as id, which is different from real id in IGDB API use (e.g. "portal-2") as id, which is different from real id in IGDB API
""" """
from catalog.common import *
from catalog.models import *
from django.conf import settings
from igdb.wrapper import IGDBWrapper
import requests
import datetime import datetime
import json import json
import logging import logging
import requests
from django.conf import settings
from igdb.wrapper import IGDBWrapper
from catalog.common import *
from catalog.models import *
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,10 +1,11 @@
import json import json
from catalog.common import *
from .tmdb import search_tmdb_by_imdb_id
from catalog.movie.models import *
from catalog.tv.models import *
import logging import logging
from catalog.common import *
from catalog.movie.models import *
from catalog.tv.models import *
from .tmdb import search_tmdb_by_imdb_id
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,21 +1,23 @@
from catalog.common import *
from catalog.models import *
import logging import logging
import podcastparser import pickle
import urllib.request import urllib.request
from django.core.cache import cache
from catalog.podcast.models import PodcastEpisode
from datetime import datetime from datetime import datetime
from django.utils.timezone import make_aware
import bleach import bleach
from django.core.validators import URLValidator import podcastparser
from django.core.cache import cache
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import URLValidator
from django.utils.timezone import make_aware
from catalog.common import *
from catalog.common.downloaders import ( from catalog.common.downloaders import (
_local_response_path,
get_mock_file, get_mock_file,
get_mock_mode, get_mock_mode,
_local_response_path,
) )
import pickle from catalog.models import *
from catalog.podcast.models import PodcastEpisode
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,17 +1,19 @@
""" """
Spotify Spotify
""" """
import datetime
import logging
import time
import dateparser
import requests
from django.conf import settings from django.conf import settings
from catalog.common import * from catalog.common import *
from catalog.models import * from catalog.models import *
from catalog.music.utils import upc_to_gtin_13 from catalog.music.utils import upc_to_gtin_13
from .douban import *
import time
import datetime
import requests
import dateparser
import logging
from .douban import *
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,9 +1,11 @@
from catalog.common import *
from catalog.models import *
from .igdb import search_igdb_by_3p_url
import dateparser
import logging import logging
import dateparser
from catalog.common import *
from catalog.models import *
from .igdb import search_igdb_by_3p_url
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -2,14 +2,16 @@
The Movie Database The Movie Database
""" """
import logging
import re import re
from django.conf import settings from django.conf import settings
from catalog.common import * from catalog.common import *
from .douban import *
from catalog.movie.models import * from catalog.movie.models import *
from catalog.tv.models import * from catalog.tv.models import *
import logging
from .douban import *
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,10 +1,11 @@
from django.test import TestCase from django.test import TestCase
from catalog.book.tests import * from catalog.book.tests import *
from catalog.movie.tests import *
from catalog.tv.tests import *
from catalog.music.tests import *
from catalog.game.tests import * from catalog.game.tests import *
from catalog.podcast.tests import * from catalog.movie.tests import *
from catalog.music.tests import *
from catalog.performance.tests import * from catalog.performance.tests import *
from catalog.podcast.tests import *
from catalog.tv.tests import *
# imported tests with same name might be ignored silently # imported tests with same name might be ignored silently

View file

@ -25,10 +25,12 @@ For now, we follow Douban convention, but keep an eye on it in case it breaks it
""" """
from functools import cached_property from functools import cached_property
from catalog.common.models import *
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from catalog.common.models import *
class TVShowInSchema(ItemInSchema): class TVShowInSchema(ItemInSchema):
season_count: int | None = None season_count: int | None = None

View file

@ -1,7 +1,8 @@
from django.test import TestCase from django.test import TestCase
from catalog.common import * from catalog.common import *
from catalog.tv.models import *
from catalog.sites.imdb import IMDB from catalog.sites.imdb import IMDB
from catalog.tv.models import *
class JSONFieldTestCase(TestCase): class JSONFieldTestCase(TestCase):

View file

@ -1,6 +1,7 @@
from django.urls import path, re_path from django.urls import path, re_path
from .views import *
from .models import * from .models import *
from .views import *
app_name = "catalog" app_name = "catalog"

View file

@ -1,24 +1,32 @@
import logging import logging
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.decorators import login_required, permission_required
from django.utils.translation import gettext_lazy as _
from django.core.exceptions import BadRequest, PermissionDenied, ObjectDoesNotExist
from django.db.models import Count
from django.core.paginator import Paginator
from .models import *
from django.views.decorators.clickjacking import xframe_options_exempt
from journal.models import Mark, ShelfMember, Review, Comment, query_item_category
from journal.models import (
query_visible,
query_following,
)
from common.utils import PageLinksGenerator, get_uuid_or_404
from common.config import PAGE_LINK_NUMBER
from journal.models import ShelfTypeNames, ShelfType, ItemCategory
from .forms import *
from .search.views import *
from django.http import Http404
from django.core.cache import cache from django.core.cache import cache
from django.core.exceptions import BadRequest, ObjectDoesNotExist, PermissionDenied
from django.core.paginator import Paginator
from django.db.models import Count
from django.http import Http404
from django.shortcuts import get_object_or_404, redirect, render
from django.utils.translation import gettext_lazy as _
from django.views.decorators.clickjacking import xframe_options_exempt
from common.config import PAGE_LINK_NUMBER
from common.utils import PageLinksGenerator, get_uuid_or_404
from journal.models import (
Comment,
Mark,
Review,
ShelfMember,
ShelfType,
ShelfTypeNames,
query_following,
query_item_category,
query_visible,
)
from .forms import *
from .models import *
from .search.views import *
from .views_edit import * from .views_edit import *
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@ -205,7 +213,8 @@ def comments_by_episode(request, item_path, item_uuid):
raise Http404() raise Http404()
episode_uuid = request.GET.get("episode_uuid") episode_uuid = request.GET.get("episode_uuid")
if episode_uuid: if episode_uuid:
ids = [TVEpisode.get_by_url(episode_uuid).id] episode = TVEpisode.get_by_url(episode_uuid)
ids = [episode.pk] if episode else []
else: else:
ids = item.child_item_ids ids = item.child_item_ids
queryset = Comment.objects.filter(item_id__in=ids).order_by("-created_time") queryset = Comment.objects.filter(item_id__in=ids).order_by("-created_time")
@ -250,7 +259,7 @@ def discover(request):
raise BadRequest() raise BadRequest()
user = request.user user = request.user
if user.is_authenticated: if user.is_authenticated:
layout = user.get_preference().discover_layout layout = user.preference.discover_layout
else: else:
layout = [] layout = []

View file

@ -1,19 +1,22 @@
import logging import logging
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required, permission_required
from django.utils.translation import gettext_lazy as _
from django.http import HttpResponseRedirect
from django.core.exceptions import BadRequest, PermissionDenied, ObjectDoesNotExist
from django.utils import timezone
from django.contrib import messages
from .common.models import ExternalResource, IdType, IdealIdTypes
from .sites.imdb import IMDB
from .models import *
from .forms import *
from .search.views import *
from journal.models import update_journal_for_merged_item
from common.utils import get_uuid_or_404
from auditlog.context import set_actor from auditlog.context import set_actor
from django.contrib import messages
from django.contrib.auth.decorators import login_required, permission_required
from django.core.exceptions import BadRequest, ObjectDoesNotExist, PermissionDenied
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect, render
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from common.utils import get_uuid_or_404
from journal.models import update_journal_for_merged_item
from .common.models import ExternalResource, IdealIdTypes, IdType
from .forms import *
from .models import *
from .search.views import *
from .sites.imdb import IMDB
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,13 +1,14 @@
from ninja import NinjaAPI, Schema import logging
from django.conf import settings
from typing import Any, Callable, List, Optional, Tuple, Type from typing import Any, Callable, List, Optional, Tuple, Type
from ninja.pagination import PageNumberPagination as NinjaPageNumberPagination
from django.conf import settings
from django.db.models import QuerySet from django.db.models import QuerySet
from ninja import NinjaAPI, Schema
from ninja.pagination import PageNumberPagination as NinjaPageNumberPagination
from ninja.security import HttpBearer from ninja.security import HttpBearer
from oauthlib.oauth2 import Server
from oauth2_provider.oauth2_backends import OAuthLibCore from oauth2_provider.oauth2_backends import OAuthLibCore
from oauth2_provider.oauth2_validators import OAuth2Validator from oauth2_provider.oauth2_validators import OAuth2Validator
import logging from oauthlib.oauth2 import Server
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,11 +1,12 @@
from django import forms
from markdownx.fields import MarkdownxFormField
import django.contrib.postgres.forms as postgres
from django.utils import formats
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
import json import json
import django.contrib.postgres.forms as postgres
from django import forms
from django.core.exceptions import ValidationError
from django.utils import formats
from django.utils.translation import gettext_lazy as _
from markdownx.fields import MarkdownxFormField
class PreviewImageInput(forms.FileInput): class PreviewImageInput(forms.FileInput):
template_name = "widgets/image.html" template_name = "widgets/image.html"

View file

@ -1,8 +1,9 @@
from django.core.management.base import BaseCommand
import pprint import pprint
from django.core.management.base import BaseCommand
from redis import Redis from redis import Redis
from rq.job import Job
from rq import Queue from rq import Queue
from rq.job import Job
class Command(BaseCommand): class Command(BaseCommand):

View file

@ -1,8 +1,9 @@
from django.core.management.base import BaseCommand
import pprint import pprint
from django.core.management.base import BaseCommand
from redis import Redis from redis import Redis
from rq.job import Job
from rq import Queue from rq import Queue
from rq.job import Job
class Command(BaseCommand): class Command(BaseCommand):

View file

@ -2,7 +2,6 @@ from django import template
from django.conf import settings from django.conf import settings
from django.utils.html import format_html from django.utils.html import format_html
register = template.Library() register = template.Library()

View file

@ -1,7 +1,8 @@
from django import template from django import template
from django.template.defaultfilters import stringfilter from django.template.defaultfilters import stringfilter
from django.utils.text import Truncator
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.text import Truncator
from catalog.common.models import ItemCategory, item_categories from catalog.common.models import ItemCategory, item_categories
from catalog.search.views import visible_categories as _visible_categories from catalog.search.views import visible_categories as _visible_categories

View file

@ -1,9 +1,10 @@
from django import template
from django.utils.safestring import mark_safe
from django.template.defaultfilters import stringfilter
from opencc import OpenCC
import re import re
from django import template
from django.template.defaultfilters import stringfilter
from django.utils.safestring import mark_safe
from opencc import OpenCC
cc = OpenCC("t2s") cc = OpenCC("t2s")
register = template.Library() register = template.Library()

View file

@ -3,7 +3,6 @@ from django.conf import settings
from django.template.defaultfilters import stringfilter from django.template.defaultfilters import stringfilter
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
register = template.Library() register = template.Library()

View file

@ -1,7 +1,6 @@
from django import template from django import template
from django.utils import timezone from django.utils import timezone
register = template.Library() register = template.Library()

View file

@ -2,7 +2,6 @@ from django import template
from django.template.defaultfilters import stringfilter from django.template.defaultfilters import stringfilter
from django.utils.text import Truncator from django.utils.text import Truncator
register = template.Library() register = template.Library()

View file

@ -1,4 +1,5 @@
from django.urls import path from django.urls import path
from .views import * from .views import *
app_name = "common" app_name = "common"

View file

@ -1,4 +1,5 @@
import uuid import uuid
from django.http import Http404 from django.http import Http404
from django.utils import timezone from django.utils import timezone
from django.utils.baseconv import base62 from django.utils.baseconv import base62

View file

@ -1,7 +1,7 @@
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect, render from django.shortcuts import redirect, render
from django.urls import reverse from django.urls import reverse
from django.contrib.auth.decorators import login_required
@login_required @login_required
@ -11,7 +11,7 @@ def me(request):
def home(request): def home(request):
if request.user.is_authenticated: if request.user.is_authenticated:
home = request.user.get_preference().classic_homepage home = request.user.preference.classic_homepage
if home == 1: if home == 1:
return redirect(request.user.url) return redirect(request.user.url)
elif home == 2: elif home == 2:

View file

@ -1,12 +1,12 @@
# Generated by Django 3.2.19 on 2023-06-28 05:09 # Generated by Django 3.2.19 on 2023-06-28 05:09
from django.conf import settings
import django.core.validators import django.core.validators
from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
import markdownx.models import markdownx.models
import oauth2_provider.generators import oauth2_provider.generators
import oauth2_provider.models import oauth2_provider.models
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):

View file

@ -1,8 +1,8 @@
# Generated by Django 4.2.3 on 2023-07-06 22:53 # Generated by Django 4.2.3 on 2023-07-06 22:53
import django.db.models.deletion
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):

View file

@ -1,9 +1,10 @@
from django.db import models
from django.core.validators import RegexValidator from django.core.validators import RegexValidator
from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from oauth2_provider.models import AbstractApplication
from markdownx.models import MarkdownxField from markdownx.models import MarkdownxField
from journal.renderers import render_md from oauth2_provider.models import AbstractApplication
from journal.models.renderers import render_md
class Application(AbstractApplication): class Application(AbstractApplication):

View file

@ -1,10 +1,10 @@
from django.urls import path, re_path, include
from django.contrib import admin from django.contrib import admin
from django.contrib.auth import views as auth_views from django.contrib.auth import views as auth_views
from django.urls import include, path, re_path
from oauth2_provider import views as oauth2_views from oauth2_provider import views as oauth2_views
from oauth2_provider.views import oidc as oidc_views from oauth2_provider.views import oidc as oidc_views
from .views import *
from .views import *
_urlpatterns = [ _urlpatterns = [
re_path( re_path(

View file

@ -1,23 +1,22 @@
from django.shortcuts import render from dateutil.relativedelta import relativedelta
from loguru import logger from django.conf import settings
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.forms.models import modelform_factory
from django.shortcuts import render
from django.urls import reverse from django.urls import reverse
from django.utils import timezone
from loguru import logger
from oauth2_provider.forms import AllowForm from oauth2_provider.forms import AllowForm
from oauth2_provider.models import get_application_model from oauth2_provider.generators import generate_client_id, generate_client_secret
from oauth2_provider.models import AccessToken, RefreshToken, get_application_model
from oauth2_provider.settings import oauth2_settings
from oauth2_provider.views import ApplicationRegistration as BaseApplicationRegistration from oauth2_provider.views import ApplicationRegistration as BaseApplicationRegistration
from oauth2_provider.views import ApplicationUpdate as BaseApplicationUpdate from oauth2_provider.views import ApplicationUpdate as BaseApplicationUpdate
from oauth2_provider.views.base import AuthorizationView as BaseAuthorizationView from oauth2_provider.views.base import AuthorizationView as BaseAuthorizationView
from oauth2_provider.settings import oauth2_settings
from oauth2_provider.generators import generate_client_id, generate_client_secret
from common.api import api
from oauthlib.common import generate_token from oauthlib.common import generate_token
from oauth2_provider.models import AccessToken
from django.utils import timezone from common.api import api
from dateutil.relativedelta import relativedelta
from oauth2_provider.models import RefreshToken
from django.conf import settings
from .models import Application
from django.forms.models import modelform_factory
from .models import Application from .models import Application

View file

@ -1,15 +1,17 @@
from .models import *
from ninja import Schema
from common.api import *
from oauth2_provider.decorators import protected_resource
from ninja.security import django_auth
from django.contrib.auth.decorators import login_required
from catalog.common.models import *
from typing import List
from ninja.pagination import paginate
from ninja import Field
from datetime import datetime from datetime import datetime
from typing import List
from django.contrib.auth.decorators import login_required
from django.utils import timezone from django.utils import timezone
from ninja import Field, Schema
from ninja.pagination import paginate
from ninja.security import django_auth
from oauth2_provider.decorators import protected_resource
from catalog.common.models import *
from common.api import *
from .models import *
class MarkSchema(Schema): class MarkSchema(Schema):

View file

@ -7,9 +7,10 @@ class JournalConfig(AppConfig):
def ready(self): def ready(self):
# load key modules in proper order, make sure class inject and signal works as expected # load key modules in proper order, make sure class inject and signal works as expected
from . import api
from .models import Tag, Rating
from catalog.models import Indexer from catalog.models import Indexer
from . import api
from .models import Rating, Tag
Indexer.register_list_model(Tag) Indexer.register_list_model(Tag)
Indexer.register_piece_model(Rating) Indexer.register_piece_model(Rating)

View file

@ -1,10 +1,12 @@
from django.utils.translation import gettext_lazy as _ import os
from datetime import datetime
from django.conf import settings from django.conf import settings
from django.utils.translation import gettext_lazy as _
from openpyxl import Workbook from openpyxl import Workbook
from catalog.common.models import IdType from catalog.common.models import IdType
from common.utils import GenerateDateUUIDMediaFilePath from common.utils import GenerateDateUUIDMediaFilePath
from datetime import datetime
import os
from journal.models import * from journal.models import *

View file

@ -1,8 +1,11 @@
from django.contrib.syndication.views import Feed
from journal.renderers import render_md
import mimetypes import mimetypes
from .models import *
from django.conf import settings from django.conf import settings
from django.contrib.syndication.views import Feed
from journal.models.renderers import render_md
from .models import *
MAX_ITEM_PER_TYPE = 10 MAX_ITEM_PER_TYPE = 10

View file

@ -1,9 +1,11 @@
from django import forms from django import forms
from markdownx.fields import MarkdownxFormField
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from .models import * from markdownx.fields import MarkdownxFormField
from common.forms import PreviewImageInput from common.forms import PreviewImageInput
from .models import *
class ReviewForm(forms.ModelForm): class ReviewForm(forms.ModelForm):
class Meta: class Meta:

View file

@ -1,18 +1,21 @@
import openpyxl
import re
from markdownify import markdownify as md
from datetime import datetime
import logging import logging
import pytz
from django.conf import settings
from user_messages import api as msg
import django_rq
from common.utils import GenerateDateUUIDMediaFilePath
import os import os
import re
from datetime import datetime
import django_rq
import openpyxl
import pytz
from auditlog.context import set_actor from auditlog.context import set_actor
from django.conf import settings
from markdownify import markdownify as md
from user_messages import api as msg
from catalog.common import * from catalog.common import *
from catalog.common.downloaders import * from catalog.common.downloaders import *
from catalog.models import *
from catalog.sites.douban import DoubanDownloader from catalog.sites.douban import DoubanDownloader
from common.utils import GenerateDateUUIDMediaFilePath
from journal.models import * from journal.models import *
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View file

@ -1,14 +1,15 @@
import re import re
from datetime import datetime from datetime import datetime
from user_messages import api as msg
import django_rq import django_rq
from django.utils.timezone import make_aware
from auditlog.context import set_actor from auditlog.context import set_actor
from django.utils.timezone import make_aware
from user_messages import api as msg
from catalog.common import * from catalog.common import *
from catalog.common.downloaders import *
from catalog.models import * from catalog.models import *
from journal.models import * from journal.models import *
from catalog.common.downloaders import *
re_list = r"^https://www.goodreads.com/list/show/\d+" re_list = r"^https://www.goodreads.com/list/show/\d+"
re_shelf = r"^https://www.goodreads.com/review/list/\d+[^?]*\?shelf=[^&]+" re_shelf = r"^https://www.goodreads.com/review/list/\d+[^?]*\?shelf=[^&]+"

View file

@ -1,19 +1,21 @@
from django.core.files import uploadedfile
import listparser
from catalog.sites.rss import RSS
import openpyxl
import re
from markdownify import markdownify as md
from datetime import datetime
import logging import logging
import os
import re
from datetime import datetime
import django_rq
import listparser
import openpyxl
import pytz import pytz
from django.conf import settings from django.conf import settings
from django.core.files import uploadedfile
from markdownify import markdownify as md
from user_messages import api as msg from user_messages import api as msg
import django_rq
from common.utils import GenerateDateUUIDMediaFilePath
import os
from catalog.common import * from catalog.common import *
from catalog.common.downloaders import * from catalog.common.downloaders import *
from catalog.sites.rss import RSS
from common.utils import GenerateDateUUIDMediaFilePath
from journal.models import * from journal.models import *

View file

@ -1,7 +1,9 @@
from django.core.management.base import BaseCommand
import pprint import pprint
from journal.models import *
from django.core.management.base import BaseCommand
from journal.importers.douban import DoubanImporter from journal.importers.douban import DoubanImporter
from journal.models import *
from users.models import User from users.models import User

View file

@ -1,13 +1,15 @@
# Generated by Django 3.2.16 on 2023-01-12 01:32 # Generated by Django 3.2.16 on 2023-01-12 01:32
import catalog.common.utils import uuid
import django.core.validators import django.core.validators
from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
import django.utils.timezone import django.utils.timezone
import journal.mixins
import markdownx.models import markdownx.models
import uuid from django.db import migrations, models
import catalog.common.utils
import journal.models.mixins
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -39,7 +41,7 @@ class Migration(migrations.Migration):
"abstract": False, "abstract": False,
"base_manager_name": "objects", "base_manager_name": "objects",
}, },
bases=(models.Model, journal.mixins.UserOwnedObjectMixin), bases=(models.Model, journal.models.mixins.UserOwnedObjectMixin),
), ),
migrations.CreateModel( migrations.CreateModel(
name="Collection", name="Collection",

View file

@ -1,8 +1,8 @@
# Generated by Django 3.2.16 on 2023-01-12 01:32 # Generated by Django 3.2.16 on 2023-01-12 01:32
import django.db.models.deletion
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):

View file

@ -1,9 +1,10 @@
# Generated by Django 3.2.16 on 2023-01-12 21:06 # Generated by Django 3.2.16 on 2023-01-12 21:06
import catalog.common.utils
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
import catalog.common.utils
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [

View file

@ -1,8 +1,8 @@
# Generated by Django 3.2.16 on 2023-01-14 03:34 # Generated by Django 3.2.16 on 2023-01-14 03:34
import django.db.models.deletion
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):

View file

@ -1,8 +1,8 @@
# Generated by Django 3.2.16 on 2023-01-14 13:39 # Generated by Django 3.2.16 on 2023-01-14 13:39
import django.db.models.deletion
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):

View file

@ -1,7 +1,7 @@
# Generated by Django 3.2.16 on 2023-01-17 03:51 # Generated by Django 3.2.16 on 2023-01-17 03:51
from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):

View file

@ -1,7 +1,7 @@
# Generated by Django 3.2.16 on 2023-01-31 20:14 # Generated by Django 3.2.16 on 2023-01-31 20:14
from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):

View file

@ -1,7 +1,7 @@
# Generated by Django 3.2.19 on 2023-06-05 02:31 # Generated by Django 3.2.19 on 2023-06-05 02:31
from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):

View file

@ -1,7 +1,7 @@
# Generated by Django 4.2.3 on 2023-07-06 22:53 # Generated by Django 4.2.3 on 2023-07-06 22:53
from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,31 @@
from .collection import Collection, CollectionMember, FeaturedCollection
from .comment import Comment
from .common import (
Piece,
UserOwnedObjectMixin,
VisibilityType,
max_visiblity_to,
q_visible_to,
query_following,
query_item_category,
query_visible,
)
from .like import Like
from .mark import Mark
from .rating import Rating
from .review import Review
from .shelf import (
Shelf,
ShelfLogEntry,
ShelfManager,
ShelfMember,
ShelfType,
ShelfTypeNames,
)
from .tag import Tag, TagManager, TagMember
from .utils import (
journal_exists_for_item,
remove_data_by_user,
reset_journal_visibility_for_user,
update_journal_for_merged_item,
)

View file

@ -0,0 +1,111 @@
import re
from functools import cached_property
from django.db import connection, models
from django.utils.translation import gettext_lazy as _
from catalog.collection.models import Collection as CatalogCollection
from catalog.common import jsondata
from catalog.common.utils import DEFAULT_ITEM_COVER, piece_cover_path
from catalog.models import Item
from users.models import User
from .common import Piece
from .itemlist import List, ListMember
from .renderers import render_md
_RE_HTML_TAG = re.compile(r"<[^>]*>")
class CollectionMember(ListMember):
parent = models.ForeignKey(
"Collection", related_name="members", on_delete=models.CASCADE
)
note = jsondata.CharField(_("备注"), null=True, blank=True)
class Collection(List):
url_path = "collection"
MEMBER_CLASS = CollectionMember
catalog_item = models.OneToOneField(
CatalogCollection, on_delete=models.PROTECT, related_name="journal_item"
)
title = models.CharField(_("标题"), max_length=1000, default="")
brief = models.TextField(_("简介"), blank=True, default="")
cover = models.ImageField(
upload_to=piece_cover_path, default=DEFAULT_ITEM_COVER, blank=True
)
items = models.ManyToManyField(
Item, through="CollectionMember", related_name="collections"
)
collaborative = models.PositiveSmallIntegerField(
default=0
) # 0: Editable by owner only / 1: Editable by bi-direction followers
featured_by_users = models.ManyToManyField(
to=User, related_name="featured_collections", through="FeaturedCollection"
)
@property
def html(self):
html = render_md(self.brief)
return html
@property
def plain_description(self):
html = render_md(self.brief)
return _RE_HTML_TAG.sub(" ", html)
def featured_by_user_since(self, user):
f = FeaturedCollection.objects.filter(target=self, owner=user).first()
return f.created_time if f else None
def get_stats_for_user(self, user):
items = list(self.members.all().values_list("item_id", flat=True))
stats = {"total": len(items)}
for st, shelf in user.shelf_manager.shelf_list.items():
stats[st] = shelf.members.all().filter(item_id__in=items).count()
stats["percentage"] = (
round(stats["complete"] * 100 / stats["total"]) if stats["total"] else 0
)
return stats
def get_progress_for_user(self, user):
items = list(self.members.all().values_list("item_id", flat=True))
if len(items) == 0:
return 0
shelf = user.shelf_manager.shelf_list["complete"]
return round(
shelf.members.all().filter(item_id__in=items).count() * 100 / len(items)
)
def save(self, *args, **kwargs):
if getattr(self, "catalog_item", None) is None:
self.catalog_item = CatalogCollection()
if (
self.catalog_item.title != self.title
or self.catalog_item.brief != self.brief
):
self.catalog_item.title = self.title
self.catalog_item.brief = self.brief
self.catalog_item.cover = self.cover # type: ignore
self.catalog_item.save()
super().save(*args, **kwargs)
class FeaturedCollection(Piece):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
target = models.ForeignKey(Collection, on_delete=models.CASCADE)
created_time = models.DateTimeField(auto_now_add=True)
edited_time = models.DateTimeField(auto_now=True)
class Meta:
unique_together = [["owner", "target"]]
@property
def visibility(self):
return self.target.visibility
@cached_property
def progress(self):
return self.target.get_progress_for_user(self.owner)

Some files were not shown because too many files have changed in this diff Show more