improve logging
This commit is contained in:
parent
ce68abb9cc
commit
c670b69fdd
25 changed files with 207 additions and 223 deletions
|
@ -574,7 +574,10 @@ if SENTRY_DSN:
|
|||
sentry_sdk.init(
|
||||
dsn=SENTRY_DSN,
|
||||
environment=sentry_env or "unknown",
|
||||
integrations=[LoguruIntegration(), DjangoIntegration()],
|
||||
integrations=[
|
||||
DjangoIntegration(),
|
||||
LoguruIntegration(event_format="{name}:{function}:{line} - {message}"),
|
||||
],
|
||||
release=NEODB_VERSION,
|
||||
send_default_pii=True,
|
||||
traces_sample_rate=env("NEODB_SENTRY_SAMPLE_RATE"),
|
||||
|
|
|
@ -22,7 +22,7 @@ from os.path import exists
|
|||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from loguru import logger as _logger
|
||||
from loguru import logger
|
||||
|
||||
from catalog.common import (
|
||||
BaseSchema,
|
||||
|
@ -186,9 +186,9 @@ class Edition(Item):
|
|||
if work_res:
|
||||
work = work_res.item
|
||||
if not work:
|
||||
_logger.warning(f"Unable to find work for {work_res}")
|
||||
logger.warning(f"Unable to find work for {work_res}")
|
||||
else:
|
||||
_logger.warning(
|
||||
logger.warning(
|
||||
f'Unable to find resource for {w["id_type"]}:{w["id_value"]}'
|
||||
)
|
||||
work = Work.objects.filter(
|
||||
|
|
|
@ -11,14 +11,12 @@ import filetype
|
|||
import requests
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from loguru import logger
|
||||
from lxml import etree, html
|
||||
from PIL import Image
|
||||
from requests import Response
|
||||
from requests.exceptions import RequestException
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
RESPONSE_OK = 0 # response is ready for pasring
|
||||
RESPONSE_INVALID_CONTENT = -1 # content not valid but no need to retry
|
||||
RESPONSE_NETWORK_ERROR = -2 # network error, retry next proxied url
|
||||
|
@ -67,11 +65,11 @@ class MockResponse:
|
|||
try:
|
||||
self.content = Path(fn).read_bytes()
|
||||
self.status_code = 200
|
||||
_logger.debug(f"use local response for {url} from {fn}")
|
||||
logger.debug(f"use local response for {url} from {fn}")
|
||||
except Exception:
|
||||
self.content = b"Error: response file not found"
|
||||
self.status_code = 404
|
||||
_logger.debug(f"local response not found for {url} at {fn}")
|
||||
logger.debug(f"local response not found for {url} at {fn}")
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
|
@ -173,7 +171,7 @@ class BasicDownloader:
|
|||
) as fp:
|
||||
fp.write(resp.text)
|
||||
except Exception:
|
||||
_logger.warn("Save downloaded data failed.")
|
||||
logger.warning("Save downloaded data failed.")
|
||||
else:
|
||||
resp = MockResponse(self.url)
|
||||
response_type = self.validate_response(resp)
|
||||
|
@ -249,7 +247,7 @@ class RetryDownloader(BasicDownloader):
|
|||
elif self.response_type != RESPONSE_NETWORK_ERROR and retries == 0:
|
||||
raise DownloadError(self)
|
||||
elif retries > 0:
|
||||
_logger.debug("Retry " + self.url)
|
||||
logger.debug("Retry " + self.url)
|
||||
time.sleep((settings.DOWNLOADER_RETRIES - retries) * 0.5)
|
||||
raise DownloadError(self, "max out of retries")
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import logging
|
||||
import re
|
||||
import uuid
|
||||
from functools import cached_property
|
||||
|
@ -13,6 +12,7 @@ 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 loguru import logger
|
||||
from ninja import Field, Schema
|
||||
from polymorphic.models import PolymorphicModel
|
||||
|
||||
|
@ -24,8 +24,6 @@ from .utils import DEFAULT_ITEM_COVER, item_cover_path, resource_cover_path
|
|||
if TYPE_CHECKING:
|
||||
from users.models import User
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SiteName(models.TextChoices):
|
||||
Unknown = "unknown", _("Unknown")
|
||||
|
@ -406,7 +404,7 @@ class Item(SoftDeleteMixin, PolymorphicModel):
|
|||
res.save()
|
||||
|
||||
def recast_to(self, model):
|
||||
_logger.warn(f"recast item {self} to {model}")
|
||||
logger.warning(f"recast item {self} to {model}")
|
||||
if self.__class__ == model:
|
||||
return self
|
||||
if model not in Item.__subclasses__():
|
||||
|
@ -631,7 +629,7 @@ class ExternalResource(models.Model):
|
|||
site = self.get_site()
|
||||
return site.SITE_NAME if site else SiteName.Unknown
|
||||
except Exception:
|
||||
_logger.warning(f"Unknown site for {self}")
|
||||
logger.warning(f"Unknown site for {self}")
|
||||
return SiteName.Unknown
|
||||
|
||||
@property
|
||||
|
|
|
@ -7,19 +7,17 @@ a Site may scrape a url and store result in ResourceContent
|
|||
ResourceContent persists as an ExternalResource which may link to an Item
|
||||
"""
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Callable, Type, TypeVar
|
||||
|
||||
import django_rq
|
||||
import requests
|
||||
from loguru import logger
|
||||
from validators import url as url_validate
|
||||
|
||||
from .models import ExternalResource, IdealIdTypes, IdType, Item, SiteName
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ResourceContent:
|
||||
|
@ -238,7 +236,7 @@ class AbstractSite:
|
|||
if resource_content:
|
||||
p.update_content(resource_content)
|
||||
if not p.ready:
|
||||
_logger.error(f"unable to get resource {self.url} ready")
|
||||
logger.error(f"unable to get resource {self.url} ready")
|
||||
return None
|
||||
if auto_create: # and (p.item is None or p.item.is_deleted):
|
||||
self.get_item()
|
||||
|
@ -259,7 +257,7 @@ class AbstractSite:
|
|||
preloaded_content=linked_resource.get("content"),
|
||||
)
|
||||
else:
|
||||
_logger.error(f"unable to get site for {linked_url}")
|
||||
logger.error(f"unable to get site for {linked_url}")
|
||||
if p.related_resources or p.prematched_resources:
|
||||
django_rq.get_queue("crawl").enqueue(crawl_related_resources_task, p.pk)
|
||||
if p.item:
|
||||
|
@ -338,7 +336,7 @@ class SiteManager:
|
|||
def crawl_related_resources_task(resource_pk):
|
||||
resource = ExternalResource.objects.filter(pk=resource_pk).first()
|
||||
if not resource:
|
||||
_logger.warn(f"crawl resource not found {resource_pk}")
|
||||
logger.warning(f"crawl resource not found {resource_pk}")
|
||||
return
|
||||
links = (resource.related_resources or []) + (resource.prematched_resources or []) # type: ignore
|
||||
for w in links: # type: ignore
|
||||
|
@ -353,8 +351,8 @@ def crawl_related_resources_task(resource_pk):
|
|||
site.get_resource_ready(ignore_existing_content=False, auto_link=True)
|
||||
item = site.get_item()
|
||||
if item:
|
||||
_logger.info(f"crawled {w} {item}")
|
||||
logger.info(f"crawled {w} {item}")
|
||||
else:
|
||||
_logger.warn(f"crawl {w} failed")
|
||||
logger.warning(f"crawl {w} failed")
|
||||
except Exception as e:
|
||||
_logger.warn(f"crawl {w} error {e}")
|
||||
logger.warning(f"crawl {w} error {e}")
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
import logging
|
||||
import uuid
|
||||
|
||||
from django.utils import timezone
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
DEFAULT_ITEM_COVER = "item/default.svg"
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import logging
|
||||
|
||||
from auditlog.registry import auditlog
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from loguru import logger
|
||||
|
||||
from .book.models import Edition, EditionInSchema, EditionSchema, Series, Work
|
||||
from .collection.models import Collection as CatalogCollection
|
||||
|
@ -42,8 +41,6 @@ from .tv.models import (
|
|||
|
||||
from .search.models import Indexer # isort:skip
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# class Exhibition(Item):
|
||||
|
||||
|
@ -59,7 +56,7 @@ _logger = logging.getLogger(__name__)
|
|||
|
||||
def init_catalog_search_models():
|
||||
if settings.DISABLE_MODEL_SIGNAL:
|
||||
_logger.warn(
|
||||
logger.warning(
|
||||
"Catalog models are not being indexed with DISABLE_MODEL_SIGNAL configuration"
|
||||
)
|
||||
return
|
||||
|
@ -100,4 +97,4 @@ def init_catalog_audit_log():
|
|||
ExternalResource, include_fields=["item", "id_type", "id_value", "url"]
|
||||
)
|
||||
|
||||
# _logger.debug(f"Catalog audit log initialized for {item_content_types().values()}")
|
||||
# logger.debug(f"Catalog audit log initialized for {item_content_types().values()}")
|
||||
|
|
|
@ -53,7 +53,7 @@ class SearchResultItem:
|
|||
|
||||
class Goodreads:
|
||||
@classmethod
|
||||
def search(cls, q, page=1):
|
||||
def search(cls, q: str, page=1):
|
||||
results = []
|
||||
search_url = f"https://www.goodreads.com/search?page={page}&q={quote_plus(q)}"
|
||||
try:
|
||||
|
@ -115,7 +115,7 @@ class Goodreads:
|
|||
except requests.exceptions.RequestException as e:
|
||||
logger.warning(f"Search {search_url} error: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"Goodreads search '{q}' error: {e}")
|
||||
logger.error("Goodreads search error", extra={"query": q, "exception": e})
|
||||
return results
|
||||
|
||||
|
||||
|
@ -164,7 +164,7 @@ class GoogleBooks:
|
|||
except requests.exceptions.RequestException as e:
|
||||
logger.warning(f"Search {api_url} error: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"GoogleBooks search '{q}' error: {e}")
|
||||
logger.error("GoogleBooks search error", extra={"query": q, "exception": e})
|
||||
return results
|
||||
|
||||
|
||||
|
@ -206,7 +206,7 @@ class TheMovieDatabase:
|
|||
except requests.exceptions.RequestException as e:
|
||||
logger.warning(f"Search {api_url} error: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"TMDb search '{q}' error: {e}")
|
||||
logger.error("TMDb search error", extra={"query": q, "exception": e})
|
||||
return results
|
||||
|
||||
|
||||
|
@ -242,7 +242,7 @@ class Spotify:
|
|||
except requests.exceptions.RequestException as e:
|
||||
logger.warning(f"Search {api_url} error: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"Spotify search '{q}' error: {e}")
|
||||
logger.error("Spotify search error", extra={"query": q, "exception": e})
|
||||
return results
|
||||
|
||||
|
||||
|
@ -278,7 +278,7 @@ class Bandcamp:
|
|||
except requests.exceptions.RequestException as e:
|
||||
logger.warning(f"Search {search_url} error: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"Goodreads search '{q}' error: {e}")
|
||||
logger.error("Bandcamp search error", extra={"query": q, "exception": e})
|
||||
return results
|
||||
|
||||
|
||||
|
@ -305,7 +305,9 @@ class ApplePodcast:
|
|||
except requests.exceptions.RequestException as e:
|
||||
logger.warning(f"Search {search_url} error: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"ApplePodcast search '{q}' error: {e}")
|
||||
logger.error(
|
||||
"ApplePodcast search error", extra={"query": q, "exception": e}
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
|
@ -322,7 +324,10 @@ class Fediverse:
|
|||
)
|
||||
r = response.json()
|
||||
except Exception as e:
|
||||
logger.warning(f"Search {api_url} error: {e}")
|
||||
logger.error(
|
||||
f"Fediverse search {host} error",
|
||||
extra={"url": api_url, "query": q, "exception": e},
|
||||
)
|
||||
return []
|
||||
if "data" in r:
|
||||
for item in r["data"]:
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# pyright: reportFunctionMemberAccess=false
|
||||
import hashlib
|
||||
import logging
|
||||
|
||||
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
|
||||
|
||||
from catalog.common.sites import SiteManager
|
||||
|
@ -16,8 +16,6 @@ from .typesense import Indexer as TypeSenseIndexer
|
|||
|
||||
# from .meilisearch import Indexer as MeiliSearchIndexer
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DbIndexer:
|
||||
@classmethod
|
||||
|
@ -154,10 +152,10 @@ def _fetch_task(url, is_refetch, user):
|
|||
site.get_resource_ready(ignore_existing_content=is_refetch)
|
||||
item = site.get_item()
|
||||
if item:
|
||||
_logger.info(f"fetched {url} {item.url} {item}")
|
||||
logger.info(f"fetched {url} {item.url} {item}")
|
||||
item_url = item.url
|
||||
else:
|
||||
_logger.error(f"fetch {url} failed")
|
||||
logger.error(f"fetch {url} failed")
|
||||
except Exception as e:
|
||||
_logger.error(f"fetch {url} error {e}")
|
||||
logger.error(f"fetch {url} error", extra={"exception": e})
|
||||
return item_url
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import logging
|
||||
import types
|
||||
from datetime import timedelta
|
||||
from pprint import pprint
|
||||
|
|
|
@ -6,17 +6,16 @@ use (e.g. "portal-2") as id, which is different from real id in IGDB API
|
|||
|
||||
import datetime
|
||||
import json
|
||||
import logging
|
||||
|
||||
import requests
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from igdb.wrapper import IGDBWrapper
|
||||
from loguru import logger
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
_cache_key = "igdb_access_token"
|
||||
|
||||
|
||||
|
@ -32,8 +31,8 @@ def _igdb_access_token():
|
|||
token = j["access_token"]
|
||||
ttl = j["expires_in"] - 60
|
||||
cache.set(_cache_key, token, ttl)
|
||||
except Exception:
|
||||
_logger.error("unable to obtain IGDB token")
|
||||
except Exception as e:
|
||||
logger.error("unable to obtain IGDB token", extra={"exception": e})
|
||||
token = "<invalid>"
|
||||
return token
|
||||
|
||||
|
@ -156,7 +155,7 @@ class IGDB(AbstractSite):
|
|||
pd.cover_image = imgdl.download().content
|
||||
pd.cover_image_extention = imgdl.extention
|
||||
except Exception:
|
||||
_logger.debug(
|
||||
logger.debug(
|
||||
f'failed to download cover for {self.url} from {pd.metadata["cover_image_url"]}'
|
||||
)
|
||||
return pd
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import logging
|
||||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.cache import cache
|
||||
from django.core.paginator import Paginator
|
||||
|
@ -29,9 +27,6 @@ from .models import *
|
|||
from .search.views import *
|
||||
from .views_edit import *
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
NUM_REVIEWS_ON_ITEM_PAGE = 5
|
||||
NUM_REVIEWS_ON_LIST_PAGE = 20
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import logging
|
||||
|
||||
from auditlog.context import set_actor
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
@ -9,6 +7,7 @@ from django.shortcuts import get_object_or_404, redirect, render
|
|||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from loguru import logger
|
||||
|
||||
from common.utils import discord_send, get_uuid_or_404
|
||||
from journal.models import update_journal_for_merged_item
|
||||
|
@ -19,8 +18,6 @@ from .models import *
|
|||
from .search.views import *
|
||||
from .sites.imdb import IMDB as IMDB
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _add_error_map_detail(e):
|
||||
e.additonal_detail = []
|
||||
|
@ -171,7 +168,7 @@ def recast(request, item_path, item_uuid):
|
|||
raise BadRequest("Invalid target type")
|
||||
if isinstance(item, model):
|
||||
raise BadRequest("Same target type")
|
||||
_logger.warn(f"{request.user} recasting {item} to {model}")
|
||||
logger.warning(f"{request.user} recasting {item} to {model}")
|
||||
discord_send(
|
||||
"audit",
|
||||
f"{item.absolute_url}\n{item.__class__.__name__} ➡ {model.__name__}\nby [@{request.user.username}]({request.user.absolute_url})",
|
||||
|
@ -180,7 +177,7 @@ def recast(request, item_path, item_uuid):
|
|||
)
|
||||
if isinstance(item, TVShow):
|
||||
for season in item.seasons.all():
|
||||
_logger.warn(f"{request.user} recast orphaning season {season}")
|
||||
logger.warning(f"{request.user} recast orphaning season {season}")
|
||||
season.show = None
|
||||
season.save(update_fields=["show"])
|
||||
new_item = item.recast_to(model)
|
||||
|
@ -218,7 +215,7 @@ def assign_parent(request, item_path, item_uuid):
|
|||
raise BadRequest("Incompatible child item type")
|
||||
# if not request.user.is_staff and item.parent_item:
|
||||
# raise BadRequest("Already assigned to a parent item")
|
||||
_logger.warn(f"{request.user} assign {item} to {parent_item}")
|
||||
logger.warning(f"{request.user} assign {item} to {parent_item}")
|
||||
item.set_parent_item(parent_item)
|
||||
item.save()
|
||||
return redirect(item.url)
|
||||
|
@ -290,7 +287,7 @@ def merge(request, item_path, item_uuid):
|
|||
_("Cannot merge items in different categories")
|
||||
+ f" ({item.class_name} to {new_item.class_name})"
|
||||
)
|
||||
_logger.warn(f"{request.user} merges {item} to {new_item}")
|
||||
logger.warning(f"{request.user} merges {item} to {new_item}")
|
||||
item.merge_to(new_item)
|
||||
update_journal_for_merged_item(item_uuid)
|
||||
discord_send(
|
||||
|
@ -302,7 +299,7 @@ def merge(request, item_path, item_uuid):
|
|||
return redirect(new_item.url)
|
||||
else:
|
||||
if item.merged_to_item:
|
||||
_logger.warn(f"{request.user} cancels merge for {item}")
|
||||
logger.warning(f"{request.user} cancels merge for {item}")
|
||||
item.merge_to(None)
|
||||
discord_send(
|
||||
"audit",
|
||||
|
@ -334,7 +331,7 @@ def link_edition(request, item_path, item_uuid):
|
|||
"catalog_merge.html",
|
||||
{"item": item, "new_item": new_item, "mode": "link"},
|
||||
)
|
||||
_logger.warn(f"{request.user} merges {item} to {new_item}")
|
||||
logger.warning(f"{request.user} merges {item} to {new_item}")
|
||||
item.link_to_related_book(new_item)
|
||||
discord_send(
|
||||
"audit",
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import logging
|
||||
from typing import Any, Callable, List, Optional, Tuple, Type
|
||||
|
||||
from django.conf import settings
|
||||
from django.db.models import QuerySet
|
||||
from loguru import logger
|
||||
from ninja import NinjaAPI, Schema
|
||||
from ninja.pagination import PageNumberPagination as NinjaPageNumberPagination
|
||||
from ninja.security import HttpBearer
|
||||
|
@ -10,9 +10,6 @@ from oauth2_provider.oauth2_backends import OAuthLibCore
|
|||
from oauth2_provider.oauth2_validators import OAuth2Validator
|
||||
from oauthlib.oauth2 import Server
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
PERMITTED_WRITE_METHODS = ["PUT", "POST", "DELETE", "PATCH"]
|
||||
PERMITTED_READ_METHODS = ["GET", "HEAD", "OPTIONS"]
|
||||
|
||||
|
@ -20,7 +17,7 @@ PERMITTED_READ_METHODS = ["GET", "HEAD", "OPTIONS"]
|
|||
class OAuthAccessTokenAuth(HttpBearer):
|
||||
def authenticate(self, request, token) -> bool:
|
||||
if not token or not request.user.is_authenticated:
|
||||
_logger.debug("API auth: no access token or user not authenticated")
|
||||
logger.debug("API auth: no access token or user not authenticated")
|
||||
return False
|
||||
request_scopes = []
|
||||
request_method = request.method
|
||||
|
@ -34,7 +31,7 @@ class OAuthAccessTokenAuth(HttpBearer):
|
|||
core = OAuthLibCore(Server(validator))
|
||||
valid, oauthlib_req = core.verify_request(request, scopes=request_scopes)
|
||||
if not valid:
|
||||
_logger.debug(f"API auth: request scope {request_scopes} not verified")
|
||||
logger.debug(f"API auth: request scope {request_scopes} not verified")
|
||||
return valid
|
||||
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ class Command(BaseCommand):
|
|||
for job_id in options["runonce"]:
|
||||
run = JobManager.run(job_id)
|
||||
if not run:
|
||||
logger.error(f"Job not found: {job_id}")
|
||||
logger.error(f"job not found: {job_id}")
|
||||
if options["list"]:
|
||||
all_jobs = [j.__name__ for j in JobManager.registry]
|
||||
logger.info(f"{len(all_jobs)} available jobs: {' '.join(all_jobs)}")
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import logging
|
||||
import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
@ -36,8 +35,8 @@ def _fetch_remote_image(url):
|
|||
binary_file.write(raw_img)
|
||||
# logger.info(f'remote image saved as {local_url}')
|
||||
return local_url
|
||||
except Exception:
|
||||
logger.error(f"unable to fetch remote image {url}")
|
||||
except Exception as e:
|
||||
logger.error(f"unable to fetch image", extra={"url": url, "exception": e})
|
||||
return url
|
||||
|
||||
|
||||
|
@ -107,7 +106,9 @@ class DoubanImporter:
|
|||
self.import_from_file_task, job_id=jid
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
logger.error(
|
||||
f"unable to enqueue import {uploaded_file}", extra={"exception": e}
|
||||
)
|
||||
return False
|
||||
return True
|
||||
|
||||
|
@ -327,7 +328,7 @@ class DoubanImporter:
|
|||
# logger.info(f"matched {url}")
|
||||
print(".", end="", flush=True)
|
||||
except Exception as e:
|
||||
logger.error(f"fetching exception: {url} {e}")
|
||||
logger.error(f"fetching error: {url}", extra={"exception": e})
|
||||
if item is None:
|
||||
self.failed.append(str(url))
|
||||
return item
|
||||
|
|
|
@ -30,9 +30,9 @@ def render_relogin(request):
|
|||
"common/error.html",
|
||||
{
|
||||
"url": reverse("users:connect") + "?domain=" + request.user.mastodon_site,
|
||||
"msg": _("Data saved but unable to repost to Fediverse."),
|
||||
"msg": _("Data saved but unable to repost to Fediverse instance."),
|
||||
"secondary_msg": _(
|
||||
"Redirecting to your Mastodon instance now to re-authenticate."
|
||||
"Redirecting to your Fediverse instance now to re-authenticate."
|
||||
),
|
||||
},
|
||||
)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from django.conf import settings
|
||||
|
@ -10,6 +9,7 @@ from django.utils import timezone
|
|||
from django.utils.dateparse import parse_datetime
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from loguru import logger
|
||||
|
||||
from catalog.models import *
|
||||
from common.utils import AuthedHttpRequest, get_uuid_or_404
|
||||
|
@ -19,7 +19,6 @@ from takahe.utils import Takahe
|
|||
from ..models import Comment, Mark, ShelfManager, ShelfType, TagManager
|
||||
from .common import render_list, render_relogin, target_identity_required
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
PAGE_SIZE = 10
|
||||
|
||||
_checkmark = "✔️".encode("utf-8")
|
||||
|
@ -101,12 +100,12 @@ def mark(request: AuthedHttpRequest, item_uuid):
|
|||
created_time=mark_date,
|
||||
)
|
||||
except PermissionDenied:
|
||||
_logger.warn(f"post to mastodon error 401 {request.user}")
|
||||
logger.warning(f"post to mastodon error 401 {request.user}")
|
||||
return render_relogin(request)
|
||||
except ValueError as e:
|
||||
_logger.warn(f"post to mastodon error {e} {request.user}")
|
||||
logger.warning(f"post to mastodon error {e} {request.user}")
|
||||
err = (
|
||||
_("Content too long for your Mastodon instance.")
|
||||
_("Content too long for your Fediverse instance.")
|
||||
if str(e) == "422"
|
||||
else str(e)
|
||||
)
|
||||
|
@ -114,7 +113,9 @@ def mark(request: AuthedHttpRequest, item_uuid):
|
|||
request,
|
||||
"common/error.html",
|
||||
{
|
||||
"msg": _("Data saved but unable to repost to Fediverse."),
|
||||
"msg": _(
|
||||
"Data saved but unable to repost to Fediverse instance."
|
||||
),
|
||||
"secondary_msg": err,
|
||||
},
|
||||
)
|
||||
|
|
|
@ -6,7 +6,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-05-23 11:27-0400\n"
|
||||
"POT-Creation-Date: 2024-05-25 23:36-0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -92,315 +92,315 @@ msgstr "出品方"
|
|||
msgid "other title"
|
||||
msgstr "其它标题"
|
||||
|
||||
#: catalog/common/models.py:31
|
||||
#: catalog/common/models.py:29
|
||||
msgid "Unknown"
|
||||
msgstr "未知"
|
||||
|
||||
#: catalog/common/models.py:32
|
||||
#: catalog/common/models.py:30
|
||||
msgid "Douban"
|
||||
msgstr "豆瓣"
|
||||
|
||||
#: catalog/common/models.py:33 catalog/common/models.py:66
|
||||
#: catalog/common/models.py:31 catalog/common/models.py:64
|
||||
msgid "Goodreads"
|
||||
msgstr "Goodreads"
|
||||
|
||||
#: catalog/common/models.py:34 catalog/common/models.py:68
|
||||
#: catalog/common/models.py:32 catalog/common/models.py:66
|
||||
msgid "Google Books"
|
||||
msgstr "谷歌图书"
|
||||
|
||||
#: catalog/common/models.py:35
|
||||
#: catalog/common/models.py:33
|
||||
msgid "BooksTW"
|
||||
msgstr "博客來"
|
||||
|
||||
#: catalog/common/models.py:36 catalog/common/models.py:61
|
||||
#: catalog/common/models.py:34 catalog/common/models.py:59
|
||||
#: catalog/templates/movie.html:51 catalog/templates/tvseason.html:68
|
||||
#: catalog/templates/tvshow.html:63
|
||||
msgid "IMDb"
|
||||
msgstr "IMDb"
|
||||
|
||||
#: catalog/common/models.py:37
|
||||
#: catalog/common/models.py:35
|
||||
msgid "TMDB"
|
||||
msgstr "TMDB"
|
||||
|
||||
#: catalog/common/models.py:38 catalog/common/models.py:77
|
||||
#: catalog/common/models.py:36 catalog/common/models.py:75
|
||||
msgid "Bandcamp"
|
||||
msgstr "Bandcamp"
|
||||
|
||||
#: catalog/common/models.py:39
|
||||
#: catalog/common/models.py:37
|
||||
msgid "Spotify"
|
||||
msgstr "Spotify"
|
||||
|
||||
#: catalog/common/models.py:40
|
||||
#: catalog/common/models.py:38
|
||||
msgid "IGDB"
|
||||
msgstr "IGDB"
|
||||
|
||||
#: catalog/common/models.py:41
|
||||
#: catalog/common/models.py:39
|
||||
msgid "Steam"
|
||||
msgstr "Steam"
|
||||
|
||||
#: catalog/common/models.py:42 catalog/common/models.py:91
|
||||
#: catalog/common/models.py:40 catalog/common/models.py:89
|
||||
msgid "Bangumi"
|
||||
msgstr "Bangumi"
|
||||
|
||||
#: catalog/common/models.py:43
|
||||
#: catalog/common/models.py:41
|
||||
msgid "BGG"
|
||||
msgstr "BGG"
|
||||
|
||||
#: catalog/common/models.py:45
|
||||
#: catalog/common/models.py:43
|
||||
msgid "RSS"
|
||||
msgstr "RSS"
|
||||
|
||||
#: catalog/common/models.py:46
|
||||
#: catalog/common/models.py:44
|
||||
msgid "Discogs"
|
||||
msgstr "Discogs"
|
||||
|
||||
#: catalog/common/models.py:47 catalog/common/models.py:93
|
||||
#: catalog/common/models.py:45 catalog/common/models.py:91
|
||||
msgid "Apple Music"
|
||||
msgstr "苹果音乐"
|
||||
|
||||
#: catalog/common/models.py:48 catalog/common/models.py:94
|
||||
#: catalog/common/models.py:46 catalog/common/models.py:92
|
||||
msgid "Fediverse"
|
||||
msgstr "联邦宇宙"
|
||||
|
||||
#: catalog/common/models.py:52
|
||||
#: catalog/common/models.py:50
|
||||
msgid "WikiData"
|
||||
msgstr "维基数据"
|
||||
|
||||
#: catalog/common/models.py:53
|
||||
#: catalog/common/models.py:51
|
||||
msgid "ISBN10"
|
||||
msgstr "ISBN10"
|
||||
|
||||
#: catalog/common/models.py:54 catalog/templates/edition.html:19
|
||||
#: catalog/common/models.py:52 catalog/templates/edition.html:19
|
||||
msgid "ISBN"
|
||||
msgstr "ISBN"
|
||||
|
||||
#: catalog/common/models.py:55
|
||||
#: catalog/common/models.py:53
|
||||
msgid "ASIN"
|
||||
msgstr "ASIN"
|
||||
|
||||
#: catalog/common/models.py:56
|
||||
#: catalog/common/models.py:54
|
||||
msgid "ISSN"
|
||||
msgstr "ISSN"
|
||||
|
||||
#: catalog/common/models.py:57
|
||||
#: catalog/common/models.py:55
|
||||
msgid "CUBN"
|
||||
msgstr "统一书号"
|
||||
|
||||
#: catalog/common/models.py:58
|
||||
#: catalog/common/models.py:56
|
||||
msgid "ISRC"
|
||||
msgstr "ISRC"
|
||||
|
||||
#: catalog/common/models.py:59
|
||||
#: catalog/common/models.py:57
|
||||
msgid "GTIN UPC EAN"
|
||||
msgstr "条形码"
|
||||
|
||||
#: catalog/common/models.py:60
|
||||
#: catalog/common/models.py:58
|
||||
msgid "RSS Feed URL"
|
||||
msgstr "RSS网址"
|
||||
|
||||
#: catalog/common/models.py:62
|
||||
#: catalog/common/models.py:60
|
||||
msgid "TMDB TV Serie"
|
||||
msgstr "TMDB电视剧集"
|
||||
|
||||
#: catalog/common/models.py:63
|
||||
#: catalog/common/models.py:61
|
||||
msgid "TMDB TV Season"
|
||||
msgstr "TMDB电视分季"
|
||||
|
||||
#: catalog/common/models.py:64
|
||||
#: catalog/common/models.py:62
|
||||
msgid "TMDB TV Episode"
|
||||
msgstr "TMDB电视单集"
|
||||
|
||||
#: catalog/common/models.py:65
|
||||
#: catalog/common/models.py:63
|
||||
msgid "TMDB Movie"
|
||||
msgstr "TMDB电影"
|
||||
|
||||
#: catalog/common/models.py:67
|
||||
#: catalog/common/models.py:65
|
||||
msgid "Goodreads Work"
|
||||
msgstr "Goodreads著作"
|
||||
|
||||
#: catalog/common/models.py:69
|
||||
#: catalog/common/models.py:67
|
||||
msgid "Douban Book"
|
||||
msgstr "豆瓣图书"
|
||||
|
||||
#: catalog/common/models.py:70
|
||||
#: catalog/common/models.py:68
|
||||
msgid "Douban Book Work"
|
||||
msgstr "豆瓣图书著作"
|
||||
|
||||
#: catalog/common/models.py:71
|
||||
#: catalog/common/models.py:69
|
||||
msgid "Douban Movie"
|
||||
msgstr "豆瓣电影"
|
||||
|
||||
#: catalog/common/models.py:72
|
||||
#: catalog/common/models.py:70
|
||||
msgid "Douban Music"
|
||||
msgstr "豆瓣音乐"
|
||||
|
||||
#: catalog/common/models.py:73
|
||||
#: catalog/common/models.py:71
|
||||
msgid "Douban Game"
|
||||
msgstr "豆瓣游戏"
|
||||
|
||||
#: catalog/common/models.py:74
|
||||
#: catalog/common/models.py:72
|
||||
msgid "Douban Drama"
|
||||
msgstr "豆瓣舞台剧"
|
||||
|
||||
#: catalog/common/models.py:75
|
||||
#: catalog/common/models.py:73
|
||||
msgid "Douban Drama Version"
|
||||
msgstr "豆瓣舞台剧版本"
|
||||
|
||||
#: catalog/common/models.py:76
|
||||
#: catalog/common/models.py:74
|
||||
msgid "BooksTW Book"
|
||||
msgstr "博客来图书"
|
||||
|
||||
#: catalog/common/models.py:78
|
||||
#: catalog/common/models.py:76
|
||||
msgid "Spotify Album"
|
||||
msgstr "Spotify专辑"
|
||||
|
||||
#: catalog/common/models.py:79
|
||||
#: catalog/common/models.py:77
|
||||
msgid "Spotify Podcast"
|
||||
msgstr "Spotify播客"
|
||||
|
||||
#: catalog/common/models.py:88
|
||||
#: catalog/common/models.py:86
|
||||
msgid "IGDB Game"
|
||||
msgstr "IGDB游戏"
|
||||
|
||||
#: catalog/common/models.py:89
|
||||
#: catalog/common/models.py:87
|
||||
msgid "BGG Boardgame"
|
||||
msgstr "BGG桌游"
|
||||
|
||||
#: catalog/common/models.py:90
|
||||
#: catalog/common/models.py:88
|
||||
msgid "Steam Game"
|
||||
msgstr "Steam游戏"
|
||||
|
||||
#: catalog/common/models.py:92
|
||||
#: catalog/common/models.py:90
|
||||
msgid "Apple Podcast"
|
||||
msgstr "苹果播客"
|
||||
|
||||
#: catalog/common/models.py:110 catalog/common/models.py:127
|
||||
#: catalog/common/models.py:140 catalog/jobs/discover.py:91
|
||||
#: catalog/common/models.py:108 catalog/common/models.py:125
|
||||
#: catalog/common/models.py:138 catalog/jobs/discover.py:91
|
||||
#: common/templates/_header.html:25
|
||||
msgid "Book"
|
||||
msgstr "书"
|
||||
|
||||
#: catalog/common/models.py:111
|
||||
#: catalog/common/models.py:109
|
||||
msgid "TV Serie"
|
||||
msgstr "电视剧集"
|
||||
|
||||
#: catalog/common/models.py:112 catalog/templates/_sidebar_edit.html:140
|
||||
#: catalog/common/models.py:110 catalog/templates/_sidebar_edit.html:140
|
||||
msgid "TV Season"
|
||||
msgstr "电视分季"
|
||||
|
||||
#: catalog/common/models.py:113
|
||||
#: catalog/common/models.py:111
|
||||
msgid "TV Episode"
|
||||
msgstr "电视单集"
|
||||
|
||||
#: catalog/common/models.py:114 catalog/common/models.py:128
|
||||
#: catalog/common/models.py:141 catalog/templates/_sidebar_edit.html:133
|
||||
#: catalog/common/models.py:112 catalog/common/models.py:126
|
||||
#: catalog/common/models.py:139 catalog/templates/_sidebar_edit.html:133
|
||||
msgid "Movie"
|
||||
msgstr "电影"
|
||||
|
||||
#: catalog/common/models.py:115
|
||||
#: catalog/common/models.py:113
|
||||
msgid "Album"
|
||||
msgstr "专辑"
|
||||
|
||||
#: catalog/common/models.py:116 catalog/common/models.py:131
|
||||
#: catalog/common/models.py:144 common/templates/_header.html:41
|
||||
#: catalog/common/models.py:114 catalog/common/models.py:129
|
||||
#: catalog/common/models.py:142 common/templates/_header.html:41
|
||||
msgid "Game"
|
||||
msgstr "游戏"
|
||||
|
||||
#: catalog/common/models.py:117
|
||||
#: catalog/common/models.py:115
|
||||
msgid "Podcast Program"
|
||||
msgstr "播客节目"
|
||||
|
||||
#: catalog/common/models.py:118
|
||||
#: catalog/common/models.py:116
|
||||
msgid "Podcast Episode"
|
||||
msgstr "播客单集"
|
||||
|
||||
#: catalog/common/models.py:119 catalog/common/models.py:133
|
||||
#: catalog/common/models.py:146 common/templates/_header.html:45
|
||||
#: catalog/common/models.py:117 catalog/common/models.py:131
|
||||
#: catalog/common/models.py:144 common/templates/_header.html:45
|
||||
msgid "Performance"
|
||||
msgstr "演出"
|
||||
|
||||
#: catalog/common/models.py:120
|
||||
#: catalog/common/models.py:118
|
||||
msgid "Production"
|
||||
msgstr "上演"
|
||||
|
||||
#: catalog/common/models.py:121
|
||||
#: catalog/common/models.py:119
|
||||
msgid "Fanfic"
|
||||
msgstr "网文"
|
||||
|
||||
#: catalog/common/models.py:122 catalog/common/models.py:135
|
||||
#: catalog/common/models.py:120 catalog/common/models.py:133
|
||||
msgid "Exhibition"
|
||||
msgstr "展览"
|
||||
|
||||
#: catalog/common/models.py:123 catalog/common/models.py:136
|
||||
#: catalog/common/models.py:121 catalog/common/models.py:134
|
||||
#: journal/templates/collection.html:15 journal/templates/collection.html:22
|
||||
#: journal/templates/collection_edit.html:9
|
||||
#: journal/templates/collection_share.html:12
|
||||
msgid "Collection"
|
||||
msgstr "收藏单"
|
||||
|
||||
#: catalog/common/models.py:129 catalog/common/models.py:142
|
||||
#: catalog/common/models.py:127 catalog/common/models.py:140
|
||||
msgid "TV"
|
||||
msgstr "剧集"
|
||||
|
||||
#: catalog/common/models.py:130 catalog/common/models.py:143
|
||||
#: catalog/common/models.py:128 catalog/common/models.py:141
|
||||
#: common/templates/_header.html:37
|
||||
msgid "Music"
|
||||
msgstr "音乐"
|
||||
|
||||
#: catalog/common/models.py:132 catalog/common/models.py:145
|
||||
#: catalog/common/models.py:130 catalog/common/models.py:143
|
||||
#: catalog/templates/_sidebar_edit.html:152 common/templates/_header.html:33
|
||||
msgid "Podcast"
|
||||
msgstr "播客"
|
||||
|
||||
#: catalog/common/models.py:134
|
||||
#: catalog/common/models.py:132
|
||||
msgid "FanFic"
|
||||
msgstr "网文"
|
||||
|
||||
#: catalog/common/models.py:257 journal/models/collection.py:48
|
||||
#: catalog/common/models.py:255 journal/models/collection.py:48
|
||||
msgid "title"
|
||||
msgstr "标题"
|
||||
|
||||
#: catalog/common/models.py:258 journal/models/collection.py:49
|
||||
#: catalog/common/models.py:256 journal/models/collection.py:49
|
||||
msgid "description"
|
||||
msgstr "描述"
|
||||
|
||||
#: catalog/common/models.py:260 catalog/forms.py:26
|
||||
#: catalog/common/models.py:258 catalog/forms.py:26
|
||||
msgid "Primary ID Type"
|
||||
msgstr "主要标识类型"
|
||||
|
||||
#: catalog/common/models.py:263 catalog/forms.py:31
|
||||
#: catalog/common/models.py:261 catalog/forms.py:31
|
||||
msgid "Primary ID Value"
|
||||
msgstr "主要标识数据"
|
||||
|
||||
#: catalog/common/models.py:269
|
||||
#: catalog/common/models.py:267
|
||||
msgid "metadata"
|
||||
msgstr "元数据"
|
||||
|
||||
#: catalog/common/models.py:271
|
||||
#: catalog/common/models.py:269
|
||||
msgid "cover"
|
||||
msgstr "封面"
|
||||
|
||||
#: catalog/common/models.py:565
|
||||
#: catalog/common/models.py:563
|
||||
msgid "source site"
|
||||
msgstr "来源站点"
|
||||
|
||||
#: catalog/common/models.py:567
|
||||
#: catalog/common/models.py:565
|
||||
msgid "ID on source site"
|
||||
msgstr "来源站点标识"
|
||||
|
||||
#: catalog/common/models.py:569
|
||||
#: catalog/common/models.py:567
|
||||
msgid "source url"
|
||||
msgstr "来源站点网址"
|
||||
|
||||
#: catalog/common/models.py:581
|
||||
#: catalog/common/models.py:579
|
||||
msgid "IdType of the source site"
|
||||
msgstr "来源站点的主要标识类型"
|
||||
|
||||
#: catalog/common/models.py:587
|
||||
#: catalog/common/models.py:585
|
||||
msgid "Primary Id on the source site"
|
||||
msgstr "来源站点的主要标识数据"
|
||||
|
||||
#: catalog/common/models.py:590
|
||||
#: catalog/common/models.py:588
|
||||
msgid "url to the resource"
|
||||
msgstr "指向外部资源的网址"
|
||||
|
||||
|
@ -1361,17 +1361,17 @@ msgstr "{show_title} 第{season_number}季"
|
|||
msgid "{season_title} E{episode_number}"
|
||||
msgstr "{season_title} 第{episode_number}集"
|
||||
|
||||
#: catalog/views.py:53 catalog/views.py:76
|
||||
#: catalog/views.py:49 catalog/views.py:72
|
||||
msgid "Item not found"
|
||||
msgstr "条目不存在"
|
||||
|
||||
#: catalog/views.py:57 catalog/views.py:84
|
||||
#: catalog/views.py:53 catalog/views.py:80
|
||||
msgid "Item no longer exists"
|
||||
msgstr "条目已不存在"
|
||||
|
||||
#: catalog/views_edit.py:125 catalog/views_edit.py:148
|
||||
#: catalog/views_edit.py:200 catalog/views_edit.py:276
|
||||
#: catalog/views_edit.py:353 journal/views/collection.py:52
|
||||
#: catalog/views_edit.py:122 catalog/views_edit.py:145
|
||||
#: catalog/views_edit.py:197 catalog/views_edit.py:273
|
||||
#: catalog/views_edit.py:350 journal/views/collection.py:52
|
||||
#: journal/views/collection.py:102 journal/views/collection.py:114
|
||||
#: journal/views/collection.py:130 journal/views/collection.py:161
|
||||
#: journal/views/collection.py:180 journal/views/collection.py:200
|
||||
|
@ -1383,34 +1383,34 @@ msgstr "条目已不存在"
|
|||
msgid "Insufficient permission"
|
||||
msgstr "权限不足"
|
||||
|
||||
#: catalog/views_edit.py:203 journal/views/collection.py:229
|
||||
#: catalog/views_edit.py:200 journal/views/collection.py:229
|
||||
#: journal/views/collection.py:296 journal/views/common.py:81
|
||||
#: journal/views/mark.py:139 journal/views/post.py:41 journal/views/post.py:55
|
||||
#: journal/views/review.py:93 journal/views/review.py:96 users/views.py:169
|
||||
msgid "Invalid parameter"
|
||||
msgstr "无效参数"
|
||||
|
||||
#: catalog/views_edit.py:252
|
||||
#: catalog/views_edit.py:249
|
||||
msgid "Must be a TV Season with IMDB id and season id"
|
||||
msgstr ""
|
||||
|
||||
#: catalog/views_edit.py:257
|
||||
#: catalog/views_edit.py:254
|
||||
msgid "Updating episodes"
|
||||
msgstr ""
|
||||
|
||||
#: catalog/views_edit.py:287
|
||||
#: catalog/views_edit.py:284
|
||||
msgid "Cannot be merged to an item already deleted or merged"
|
||||
msgstr ""
|
||||
|
||||
#: catalog/views_edit.py:290
|
||||
#: catalog/views_edit.py:287
|
||||
msgid "Cannot merge items in different categories"
|
||||
msgstr ""
|
||||
|
||||
#: catalog/views_edit.py:327
|
||||
#: catalog/views_edit.py:324
|
||||
msgid "Cannot be linked to an item already deleted or merged"
|
||||
msgstr ""
|
||||
|
||||
#: catalog/views_edit.py:329
|
||||
#: catalog/views_edit.py:326
|
||||
msgid "Cannot link items other than editions"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2238,7 +2238,7 @@ msgstr "日历"
|
|||
msgid "annual summary"
|
||||
msgstr "年度小结"
|
||||
|
||||
#: journal/templates/profile.html:131 mastodon/api.py:676
|
||||
#: journal/templates/profile.html:131 mastodon/api.py:677
|
||||
msgid "collection"
|
||||
msgstr "收藏单"
|
||||
|
||||
|
@ -2386,21 +2386,21 @@ msgstr "找不到条目,请使用本站条目网址。"
|
|||
msgid "Login required"
|
||||
msgstr "登录后访问"
|
||||
|
||||
#: journal/views/common.py:33 journal/views/mark.py:117
|
||||
msgid "Data saved but unable to repost to Fediverse."
|
||||
msgstr "数据已保存但未能转发到联邦宇宙。"
|
||||
#: journal/views/common.py:33 journal/views/mark.py:116
|
||||
msgid "Data saved but unable to repost to Fediverse instance."
|
||||
msgstr "数据已保存但未能转发到联邦实例。"
|
||||
|
||||
#: journal/views/common.py:35
|
||||
msgid "Redirecting to your Mastodon instance now to re-authenticate."
|
||||
msgstr "正在重定向到你的Mastodon实例以重新认证。"
|
||||
msgid "Redirecting to your Fediverse instance now to re-authenticate."
|
||||
msgstr "正在重定向到你的联邦实例以重新认证。"
|
||||
|
||||
#: journal/views/common.py:42
|
||||
msgid "List not found."
|
||||
msgstr "列表未找到"
|
||||
|
||||
#: journal/views/mark.py:109
|
||||
msgid "Content too long for your Mastodon instance."
|
||||
msgstr "内容过长,超出了你的Mastodon实例的限制。"
|
||||
#: journal/views/mark.py:107
|
||||
msgid "Content too long for your Fediverse instance."
|
||||
msgstr "内容过长,超出了你的联邦实例的限制。"
|
||||
|
||||
#: journal/views/mark.py:161 journal/views/review.py:30
|
||||
msgid "Content not found"
|
||||
|
@ -2444,16 +2444,16 @@ msgstr "标签已更新"
|
|||
msgid "Summary posted to timeline."
|
||||
msgstr "总结已发布到时间轴"
|
||||
|
||||
#: mastodon/api.py:519 takahe/utils.py:514
|
||||
#: mastodon/api.py:520 takahe/utils.py:514
|
||||
#, python-brace-format
|
||||
msgid "regarding {item_title}, may contain spoiler or triggering content"
|
||||
msgstr "关于 {item_title},可能包含剧透或敏感内容"
|
||||
|
||||
#: mastodon/api.py:681
|
||||
#: mastodon/api.py:682
|
||||
msgid "shared my collection"
|
||||
msgstr "分享我的收藏单"
|
||||
|
||||
#: mastodon/api.py:684
|
||||
#: mastodon/api.py:685
|
||||
#, python-brace-format
|
||||
msgid "shared {username}'s collection"
|
||||
msgstr "分享 {username} 的收藏单"
|
||||
|
@ -2801,8 +2801,8 @@ msgid "Authentication failed"
|
|||
msgstr "认证失败"
|
||||
|
||||
#: users/account.py:159
|
||||
msgid "Invalid response from Mastodon instance."
|
||||
msgstr "Mastodon实例返回信息无效"
|
||||
msgid "Invalid response from Fediverse instance."
|
||||
msgstr "联邦实例返回信息无效"
|
||||
|
||||
#: users/account.py:169
|
||||
msgid "Invalid cookie data."
|
||||
|
@ -2813,12 +2813,12 @@ msgid "Invalid instance domain"
|
|||
msgstr "实例域名无效"
|
||||
|
||||
#: users/account.py:182
|
||||
msgid "Invalid token from Mastodon instance."
|
||||
msgstr "Mastodon实例返回了无效的认证令牌。"
|
||||
msgid "Invalid token from Fediverse instance."
|
||||
msgstr "联邦实例返回了无效的认证令牌。"
|
||||
|
||||
#: users/account.py:205 users/account.py:559
|
||||
msgid "Invalid account data from Mastodon instance."
|
||||
msgstr "Mastodon实例返回了无效的账号数据。"
|
||||
msgid "Invalid account data from Fediverse instance."
|
||||
msgstr "联邦实例返回了无效的账号数据。"
|
||||
|
||||
#: users/account.py:230
|
||||
msgid "Registration is for invitation only"
|
||||
|
@ -2953,39 +2953,39 @@ msgstr "登录信息已更新"
|
|||
msgid "Account mismatch."
|
||||
msgstr "账号信息不匹配。"
|
||||
|
||||
#: users/data.py:123
|
||||
#: users/data.py:124
|
||||
msgid "Generating exports."
|
||||
msgstr "正在生成导出文件。"
|
||||
|
||||
#: users/data.py:135
|
||||
#: users/data.py:136
|
||||
msgid "Export file expired. Please export again."
|
||||
msgstr "导出文件已失效,请重新导出"
|
||||
|
||||
#: users/data.py:146
|
||||
#: users/data.py:147
|
||||
msgid "Sync in progress."
|
||||
msgstr "正在同步。"
|
||||
|
||||
#: users/data.py:160
|
||||
#: users/data.py:161
|
||||
msgid "Settings saved."
|
||||
msgstr "设置已保存"
|
||||
|
||||
#: users/data.py:171
|
||||
#: users/data.py:172
|
||||
msgid "Reset completed."
|
||||
msgstr "重置已完成。"
|
||||
|
||||
#: users/data.py:180
|
||||
#: users/data.py:181
|
||||
msgid "Import in progress."
|
||||
msgstr "正在导出"
|
||||
|
||||
#: users/data.py:182
|
||||
#: users/data.py:183
|
||||
msgid "Invalid URL."
|
||||
msgstr "无效网址。"
|
||||
|
||||
#: users/data.py:196 users/data.py:221 users/data.py:236
|
||||
#: users/data.py:197 users/data.py:222 users/data.py:237
|
||||
msgid "File is uploaded and will be imported soon."
|
||||
msgstr "文件已上传,等待后台导入。"
|
||||
|
||||
#: users/data.py:199 users/data.py:239
|
||||
#: users/data.py:200 users/data.py:240
|
||||
msgid "Invalid file."
|
||||
msgstr "无效文件。"
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ reportIncompatibleVariableOverride = false
|
|||
reportUnusedImport = false
|
||||
reportUnknownVariableType = false
|
||||
reportConstantRedefinition = false
|
||||
reportUnusedCallResult = false
|
||||
|
||||
[tool.djlint]
|
||||
ignore="T002,T003,H005,H006,H019,H020,H021,H023,H030,H031,D018"
|
||||
|
|
|
@ -6,7 +6,6 @@ ActivityManager generates chronological view for user and, in future, ActivitySt
|
|||
|
||||
"""
|
||||
|
||||
import logging
|
||||
from functools import cached_property
|
||||
from typing import Type
|
||||
|
||||
|
@ -15,6 +14,7 @@ from django.db import models
|
|||
from django.db.models import Q
|
||||
from django.db.models.signals import post_delete, post_save, pre_delete
|
||||
from django.utils import timezone
|
||||
from loguru import logger
|
||||
|
||||
from catalog.common.models import Item
|
||||
from journal.models import (
|
||||
|
@ -29,8 +29,6 @@ from journal.models import (
|
|||
)
|
||||
from users.models import APIdentity
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ActivityTemplate(models.TextChoices):
|
||||
MarkItem = "mark_item"
|
||||
|
@ -105,7 +103,7 @@ class DataSignalManager:
|
|||
@staticmethod
|
||||
def add_handler_for_model(model):
|
||||
if settings.DISABLE_MODEL_SIGNAL:
|
||||
_logger.warn(
|
||||
logger.warning(
|
||||
f"{model.__name__} are not being indexed with DISABLE_MODEL_SIGNAL configuration"
|
||||
)
|
||||
return
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import logging
|
||||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.shortcuts import redirect, render
|
||||
from django.urls import reverse
|
||||
|
|
|
@ -156,7 +156,7 @@ def connect_redirect_back(request):
|
|||
"common/error.html",
|
||||
{
|
||||
"msg": _("Authentication failed"),
|
||||
"secondary_msg": _("Invalid response from Mastodon instance."),
|
||||
"secondary_msg": _("Invalid response from Fediverse instance."),
|
||||
},
|
||||
)
|
||||
site = request.session.get("mastodon_domain")
|
||||
|
@ -179,7 +179,7 @@ def connect_redirect_back(request):
|
|||
"common/error.html",
|
||||
{
|
||||
"msg": _("Authentication failed"),
|
||||
"secondary_msg": _("Invalid token from Mastodon instance."),
|
||||
"secondary_msg": _("Invalid token from Fediverse instance."),
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -202,7 +202,7 @@ def connect_redirect_back(request):
|
|||
"common/error.html",
|
||||
{
|
||||
"msg": _("Authentication failed"),
|
||||
"secondary_msg": _("Invalid account data from Mastodon instance."),
|
||||
"secondary_msg": _("Invalid account data from Fediverse instance."),
|
||||
},
|
||||
)
|
||||
return register_new_user(
|
||||
|
@ -348,7 +348,7 @@ def send_verification_link(user_id, action, email, code=""):
|
|||
fail_silently=False,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
logger.error(f"send email {email} failed", extra={"exception": e})
|
||||
|
||||
|
||||
@require_http_methods(["POST"])
|
||||
|
@ -418,7 +418,7 @@ def verify_email(request):
|
|||
else:
|
||||
return register_new_user(request, username=None, email=email)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
logger.error("verify email error", extra={"exception": e, "s": s})
|
||||
error = _("Unable to verify")
|
||||
return render(
|
||||
request, "users/verify_email.html", {"success": False, "error": error}
|
||||
|
@ -556,7 +556,7 @@ def swap_login(request, token, site, refresh_token):
|
|||
)
|
||||
else:
|
||||
messages.add_message(
|
||||
request, messages.ERROR, _("Invalid account data from Mastodon instance.")
|
||||
request, messages.ERROR, _("Invalid account data from Fediverse instance.")
|
||||
)
|
||||
return redirect(reverse("users:data"))
|
||||
|
||||
|
|
|
@ -66,7 +66,9 @@ class Task(models.Model):
|
|||
task.state = cls.States.complete
|
||||
task.save(update_fields=["state"])
|
||||
except Exception as e:
|
||||
logger.error(f"Task {task} Exception {e}")
|
||||
logger.error(
|
||||
f"error running {cls.__name__}", extra={"exception": e, "task": task_id}
|
||||
)
|
||||
task.message = "Error occured."
|
||||
task.state = cls.States.failed
|
||||
task.save(update_fields=["state", "message"])
|
||||
|
|
|
@ -310,7 +310,10 @@ class User(AbstractUser):
|
|||
f = ContentFile(r.content, name=identity.icon_uri.split("/")[-1])
|
||||
identity.icon.save(f.name, f, save=False)
|
||||
except Exception as e:
|
||||
logger.error(f"Get icon failed: {identity} {identity.icon_uri} {e}")
|
||||
logger.error(
|
||||
f"fetch icon failed: {identity} {identity.icon_uri}",
|
||||
extra={"exception": e},
|
||||
)
|
||||
identity.save()
|
||||
|
||||
def refresh_mastodon_data(self, skip_detail=False):
|
||||
|
|
Loading…
Add table
Reference in a new issue