migrate to black 24
This commit is contained in:
parent
a71283e6d5
commit
55b1f1b365
29 changed files with 176 additions and 76 deletions
|
@ -1,12 +1,15 @@
|
||||||
exclude: ^test_data/
|
exclude: ^test_data/
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.4.0
|
rev: v4.6.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-yaml
|
- id: check-yaml
|
||||||
- id: check-json
|
- id: check-json
|
||||||
- id: check-xml
|
- id: check-xml
|
||||||
- id: check-toml
|
- id: check-toml
|
||||||
|
- id: check-ast
|
||||||
|
- id: check-docstring-first
|
||||||
|
- id: check-executables-have-shebangs
|
||||||
- id: check-symlinks
|
- id: check-symlinks
|
||||||
- id: check-added-large-files
|
- id: check-added-large-files
|
||||||
args: [--maxkb=1024]
|
args: [--maxkb=1024]
|
||||||
|
@ -21,7 +24,7 @@ repos:
|
||||||
- id: mixed-line-ending
|
- id: mixed-line-ending
|
||||||
|
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.3.5
|
rev: v0.4.7
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff
|
||||||
# - id: ruff-format
|
# - id: ruff-format
|
||||||
|
@ -33,7 +36,7 @@ repos:
|
||||||
args: ["--profile=black"]
|
args: ["--profile=black"]
|
||||||
|
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 22.12.0
|
rev: 24.4.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ 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.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import include, path
|
from django.urls import include, path
|
||||||
|
|
|
@ -279,7 +279,8 @@ class BooksTWTestCase(TestCase):
|
||||||
self.assertEqual(site.resource.id_value, "0010947886")
|
self.assertEqual(site.resource.id_value, "0010947886")
|
||||||
self.assertEqual(site.resource.item.isbn, "9786263152236")
|
self.assertEqual(site.resource.item.isbn, "9786263152236")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
site.resource.item.title, "阿拉伯人三千年:從民族、部落、語言、文化、宗教到帝國,綜覽阿拉伯世界的崛起、衰落與再興"
|
site.resource.item.title,
|
||||||
|
"阿拉伯人三千年:從民族、部落、語言、文化、宗教到帝國,綜覽阿拉伯世界的崛起、衰落與再興",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ 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
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
|
|
@ -71,7 +71,8 @@ class SteamTestCase(TestCase):
|
||||||
self.assertEqual(site.ready, True)
|
self.assertEqual(site.ready, True)
|
||||||
self.assertEqual(site.resource.metadata["title"], "Portal 2")
|
self.assertEqual(site.resource.metadata["title"], "Portal 2")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
site.resource.metadata["brief"], "“终身测试计划”现已升级,您可以为您自己或您的好友设计合作谜题!"
|
site.resource.metadata["brief"],
|
||||||
|
"“终身测试计划”现已升级,您可以为您自己或您的好友设计合作谜题!",
|
||||||
)
|
)
|
||||||
self.assertIsInstance(site.resource.item, Game)
|
self.assertIsInstance(site.resource.item, Game)
|
||||||
self.assertEqual(site.resource.item.steam, "620")
|
self.assertEqual(site.resource.item.steam, "620")
|
||||||
|
@ -102,7 +103,9 @@ class DoubanGameTestCase(TestCase):
|
||||||
self.assertEqual(site.resource.metadata["title"], "传送门2 Portal 2")
|
self.assertEqual(site.resource.metadata["title"], "传送门2 Portal 2")
|
||||||
self.assertIsInstance(site.resource.item, Game)
|
self.assertIsInstance(site.resource.item, Game)
|
||||||
self.assertEqual(site.resource.item.douban_game, "10734307")
|
self.assertEqual(site.resource.item.douban_game, "10734307")
|
||||||
self.assertEqual(site.resource.item.genre, ["第一人称射击", "益智", "射击", "动作"])
|
self.assertEqual(
|
||||||
|
site.resource.item.genre, ["第一人称射击", "益智", "射击", "动作"]
|
||||||
|
)
|
||||||
self.assertEqual(site.resource.item.other_title, [])
|
self.assertEqual(site.resource.item.other_title, [])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -118,14 +118,21 @@ class Migration(migrations.Migration):
|
||||||
"title",
|
"title",
|
||||||
models.CharField(default="", max_length=1000, verbose_name="标题"),
|
models.CharField(default="", max_length=1000, verbose_name="标题"),
|
||||||
),
|
),
|
||||||
("brief", models.TextField(blank=True, default="", verbose_name="简介")),
|
(
|
||||||
|
"brief",
|
||||||
|
models.TextField(blank=True, default="", verbose_name="简介"),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"primary_lookup_id_type",
|
"primary_lookup_id_type",
|
||||||
models.CharField(max_length=50, null=True, verbose_name="主要标识类型"),
|
models.CharField(
|
||||||
|
max_length=50, null=True, verbose_name="主要标识类型"
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"primary_lookup_id_value",
|
"primary_lookup_id_value",
|
||||||
models.CharField(max_length=1000, null=True, verbose_name="主要标识数值"),
|
models.CharField(
|
||||||
|
max_length=1000, null=True, verbose_name="主要标识数值"
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"metadata",
|
"metadata",
|
||||||
|
@ -184,14 +191,21 @@ class Migration(migrations.Migration):
|
||||||
"title",
|
"title",
|
||||||
models.CharField(default="", max_length=1000, verbose_name="标题"),
|
models.CharField(default="", max_length=1000, verbose_name="标题"),
|
||||||
),
|
),
|
||||||
("brief", models.TextField(blank=True, default="", verbose_name="简介")),
|
(
|
||||||
|
"brief",
|
||||||
|
models.TextField(blank=True, default="", verbose_name="简介"),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"primary_lookup_id_type",
|
"primary_lookup_id_type",
|
||||||
models.CharField(max_length=50, null=True, verbose_name="主要标识类型"),
|
models.CharField(
|
||||||
|
max_length=50, null=True, verbose_name="主要标识类型"
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"primary_lookup_id_value",
|
"primary_lookup_id_value",
|
||||||
models.CharField(max_length=1000, null=True, verbose_name="主要标识数值"),
|
models.CharField(
|
||||||
|
max_length=1000, null=True, verbose_name="主要标识数值"
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"metadata",
|
"metadata",
|
||||||
|
@ -505,12 +519,17 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"id_value",
|
"id_value",
|
||||||
models.CharField(blank=True, max_length=1000, verbose_name="源网站ID"),
|
models.CharField(
|
||||||
|
blank=True, max_length=1000, verbose_name="源网站ID"
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"raw_url",
|
"raw_url",
|
||||||
models.CharField(
|
models.CharField(
|
||||||
blank=True, max_length=1000, unique=True, verbose_name="源网站ID"
|
blank=True,
|
||||||
|
max_length=1000,
|
||||||
|
unique=True,
|
||||||
|
verbose_name="源网站ID",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
# Generated by Django 4.2.13 on 2024-06-02 16:17
|
# Generated by Django 4.2.13 on 2024-06-02 16:17
|
||||||
|
|
||||||
import catalog.common.utils
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
import catalog.common.utils
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
|
|
@ -396,9 +396,7 @@ class PerformanceProduction(Item):
|
||||||
return (
|
return (
|
||||||
self.cover.url # type:ignore
|
self.cover.url # type:ignore
|
||||||
if self.cover and self.cover != DEFAULT_ITEM_COVER
|
if self.cover and self.cover != DEFAULT_ITEM_COVER
|
||||||
else self.show.cover_image_url
|
else self.show.cover_image_url if self.show else None
|
||||||
if self.show
|
|
||||||
else None
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_linked_items_from_external_resource(self, resource: ExternalResource):
|
def update_linked_items_from_external_resource(self, resource: ExternalResource):
|
||||||
|
|
|
@ -30,7 +30,9 @@ class DoubanDramaTestCase(TestCase):
|
||||||
resource = site.get_resource_ready()
|
resource = site.get_resource_ready()
|
||||||
item = site.get_item()
|
item = site.get_item()
|
||||||
self.assertEqual(item.title, "不眠之人·拿破仑")
|
self.assertEqual(item.title, "不眠之人·拿破仑")
|
||||||
self.assertEqual(item.other_title, ["眠らない男・ナポレオン ―愛と栄光の涯(はて)に―"])
|
self.assertEqual(
|
||||||
|
item.other_title, ["眠らない男・ナポレオン ―愛と栄光の涯(はて)に―"]
|
||||||
|
)
|
||||||
self.assertEqual(item.genre, ["音乐剧"])
|
self.assertEqual(item.genre, ["音乐剧"])
|
||||||
self.assertEqual(item.troupe, ["宝塚歌剧团"])
|
self.assertEqual(item.troupe, ["宝塚歌剧团"])
|
||||||
self.assertEqual(item.composer, ["ジェラール・プレスギュルヴィック"])
|
self.assertEqual(item.composer, ["ジェラール・プレスギュルヴィック"])
|
||||||
|
@ -74,7 +76,9 @@ class DoubanDramaTestCase(TestCase):
|
||||||
# item.version, ["08星组公演版", "10年月組公演版", "17年星組公演版", "ュージカル(2017年)版"]
|
# item.version, ["08星组公演版", "10年月組公演版", "17年星組公演版", "ュージカル(2017年)版"]
|
||||||
# )
|
# )
|
||||||
self.assertEqual(item.director, ["小池修一郎", "小池 修一郎", "石丸さち子"])
|
self.assertEqual(item.director, ["小池修一郎", "小池 修一郎", "石丸さち子"])
|
||||||
self.assertEqual(item.playwright, ["小池修一郎", "Baroness Orczy(原作)", "小池 修一郎"])
|
self.assertEqual(
|
||||||
|
item.playwright, ["小池修一郎", "Baroness Orczy(原作)", "小池 修一郎"]
|
||||||
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
item.actor,
|
item.actor,
|
||||||
[
|
[
|
||||||
|
|
|
@ -354,7 +354,7 @@ class Indexer:
|
||||||
"query_by": ",".join(SEARCHABLE_ATTRIBUTES),
|
"query_by": ",".join(SEARCHABLE_ATTRIBUTES),
|
||||||
"filter_by": filters,
|
"filter_by": filters,
|
||||||
# "facet_by": "category",
|
# "facet_by": "category",
|
||||||
"sort_by": "_text_match:desc,rating_count:desc"
|
"sort_by": "_text_match:desc,rating_count:desc",
|
||||||
# 'facetsDistribution': ['_class'],
|
# 'facetsDistribution': ['_class'],
|
||||||
# 'sort_by': None,
|
# 'sort_by': None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ Scraping the website directly.
|
||||||
- It requires Apple Developer Membership ($99 per year) to obtain a token.
|
- It requires Apple Developer Membership ($99 per year) to obtain a token.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,9 @@ class Bangumi(AbstractSite):
|
||||||
model = "TVSeason" if is_series else "Movie"
|
model = "TVSeason" if is_series else "Movie"
|
||||||
if dt:
|
if dt:
|
||||||
year = dt.split("-")[0]
|
year = dt.split("-")[0]
|
||||||
showtime = [{"time": dt, "region": "首播日期" if is_series else "发布日期"}]
|
showtime = [
|
||||||
|
{"time": dt, "region": "首播日期" if is_series else "发布日期"}
|
||||||
|
]
|
||||||
case 3:
|
case 3:
|
||||||
model = "Album"
|
model = "Album"
|
||||||
case 4:
|
case 4:
|
||||||
|
|
|
@ -3,6 +3,7 @@ BoardGameGeek
|
||||||
|
|
||||||
ref: https://boardgamegeek.com/wiki/page/BGG_XML_API2
|
ref: https://boardgamegeek.com/wiki/page/BGG_XML_API2
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import html
|
import html
|
||||||
|
|
||||||
from langdetect import detect
|
from langdetect import detect
|
||||||
|
|
|
@ -55,7 +55,9 @@ class BooksTW(AbstractSite):
|
||||||
)
|
)
|
||||||
translators = [s.strip() for s in translators]
|
translators = [s.strip() for s in translators]
|
||||||
|
|
||||||
language_elem = content.xpath("//div/ul/li[starts-with(text(),'語言:')]/text()")
|
language_elem = content.xpath(
|
||||||
|
"//div/ul/li[starts-with(text(),'語言:')]/text()"
|
||||||
|
)
|
||||||
language = (
|
language = (
|
||||||
language_elem[0].strip().split(":")[1].strip() if language_elem else None # type: ignore
|
language_elem[0].strip().split(":")[1].strip() if language_elem else None # type: ignore
|
||||||
)
|
)
|
||||||
|
@ -70,9 +72,11 @@ class BooksTW(AbstractSite):
|
||||||
pub_date = content.xpath("string(//div/ul/li[contains(text(),'出版日期:')])")
|
pub_date = content.xpath("string(//div/ul/li[contains(text(),'出版日期:')])")
|
||||||
pub_date = re.match(
|
pub_date = re.match(
|
||||||
r"(\d+)/(\d+)/(\d+)\s*$",
|
r"(\d+)/(\d+)/(\d+)\s*$",
|
||||||
pub_date.strip().split(":", 1)[1].strip().split(" ", 1)[0] # type: ignore
|
(
|
||||||
if pub_date
|
pub_date.strip().split(":", 1)[1].strip().split(" ", 1)[0] # type: ignore
|
||||||
else "",
|
if pub_date
|
||||||
|
else ""
|
||||||
|
),
|
||||||
)
|
)
|
||||||
if pub_date:
|
if pub_date:
|
||||||
pub_year = int(pub_date[1])
|
pub_year = int(pub_date[1])
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
"""
|
"""
|
||||||
Discogs.
|
Discogs.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
|
@ -139,10 +139,11 @@ class IGDB(AbstractSite):
|
||||||
"brief": brief,
|
"brief": brief,
|
||||||
"official_site": official_site,
|
"official_site": official_site,
|
||||||
"igdb_id": r["id"],
|
"igdb_id": r["id"],
|
||||||
"cover_image_url": "https:"
|
"cover_image_url": (
|
||||||
+ r["cover"]["url"].replace("t_thumb", "t_cover_big")
|
"https:" + r["cover"]["url"].replace("t_thumb", "t_cover_big")
|
||||||
if r.get("cover")
|
if r.get("cover")
|
||||||
else None,
|
else None
|
||||||
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if steam_url:
|
if steam_url:
|
||||||
|
|
|
@ -83,13 +83,13 @@ class IMDB(AbstractSite):
|
||||||
"year": d["releaseYear"]["year"] if d.get("releaseYear") else None,
|
"year": d["releaseYear"]["year"] if d.get("releaseYear") else None,
|
||||||
"is_series": d["titleType"]["isSeries"],
|
"is_series": d["titleType"]["isSeries"],
|
||||||
"is_episode": d["titleType"]["isEpisode"],
|
"is_episode": d["titleType"]["isEpisode"],
|
||||||
"genre": [x["text"] for x in d["genres"]["genres"]]
|
"genre": (
|
||||||
if d.get("genres")
|
[x["text"] for x in d["genres"]["genres"]] if d.get("genres") else []
|
||||||
else [],
|
),
|
||||||
"brief": d["plot"].get("plotText") if d.get("plot") else None,
|
"brief": d["plot"].get("plotText") if d.get("plot") else None,
|
||||||
"cover_image_url": d["primaryImage"].get("url")
|
"cover_image_url": (
|
||||||
if d.get("primaryImage")
|
d["primaryImage"].get("url") if d.get("primaryImage") else None
|
||||||
else None,
|
),
|
||||||
}
|
}
|
||||||
if d.get("series"):
|
if d.get("series"):
|
||||||
episode_info = d["series"].get("episodeNumber")
|
episode_info = d["series"].get("episodeNumber")
|
||||||
|
|
|
@ -90,9 +90,9 @@ class RSS(AbstractSite):
|
||||||
metadata={
|
metadata={
|
||||||
"title": feed["title"],
|
"title": feed["title"],
|
||||||
"brief": bleach.clean(feed["description"], strip=True),
|
"brief": bleach.clean(feed["description"], strip=True),
|
||||||
"hosts": [feed.get("itunes_author")]
|
"hosts": (
|
||||||
if feed.get("itunes_author")
|
[feed.get("itunes_author")] if feed.get("itunes_author") else []
|
||||||
else [],
|
),
|
||||||
"official_site": feed.get("link"),
|
"official_site": feed.get("link"),
|
||||||
"cover_image_url": feed.get("cover_url"),
|
"cover_image_url": feed.get("cover_url"),
|
||||||
"genre": feed.get("itunes_categories", [None])[0],
|
"genre": feed.get("itunes_categories", [None])[0],
|
||||||
|
@ -126,9 +126,11 @@ class RSS(AbstractSite):
|
||||||
"brief": bleach.clean(episode.get("description"), strip=True),
|
"brief": bleach.clean(episode.get("description"), strip=True),
|
||||||
"description_html": episode.get("description_html"),
|
"description_html": episode.get("description_html"),
|
||||||
"cover_url": episode.get("episode_art_url"),
|
"cover_url": episode.get("episode_art_url"),
|
||||||
"media_url": episode.get("enclosures")[0].get("url")
|
"media_url": (
|
||||||
if episode.get("enclosures")
|
episode.get("enclosures")[0].get("url")
|
||||||
else None,
|
if episode.get("enclosures")
|
||||||
|
else None
|
||||||
|
),
|
||||||
"pub_date": make_aware(
|
"pub_date": make_aware(
|
||||||
datetime.fromtimestamp(episode.get("published"))
|
datetime.fromtimestamp(episode.get("published"))
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
"""
|
"""
|
||||||
Spotify
|
Spotify
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
|
|
|
@ -24,6 +24,7 @@ tv specials are are shown as movies
|
||||||
For now, we follow Douban convention, but keep an eye on it in case it breaks its own rules...
|
For now, we follow Douban convention, but keep an eye on it in case it breaks its own rules...
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
from typing import TYPE_CHECKING, overload
|
from typing import TYPE_CHECKING, overload
|
||||||
|
|
|
@ -37,7 +37,18 @@ def export_marks_task(user):
|
||||||
)
|
)
|
||||||
if not os.path.exists(os.path.dirname(filename)):
|
if not os.path.exists(os.path.dirname(filename)):
|
||||||
os.makedirs(os.path.dirname(filename))
|
os.makedirs(os.path.dirname(filename))
|
||||||
heading = ["标题", "简介", "豆瓣评分", "链接", "创建时间", "我的评分", "标签", "评论", "NeoDB链接", "其它ID"]
|
heading = [
|
||||||
|
"标题",
|
||||||
|
"简介",
|
||||||
|
"豆瓣评分",
|
||||||
|
"链接",
|
||||||
|
"创建时间",
|
||||||
|
"我的评分",
|
||||||
|
"标签",
|
||||||
|
"评论",
|
||||||
|
"NeoDB链接",
|
||||||
|
"其它ID",
|
||||||
|
]
|
||||||
wb = Workbook()
|
wb = Workbook()
|
||||||
# adding write_only=True will speed up but corrupt the xlsx and won't be importable
|
# adding write_only=True will speed up but corrupt the xlsx and won't be importable
|
||||||
for status, label in [
|
for status, label in [
|
||||||
|
|
|
@ -207,7 +207,10 @@ class DoubanImporter:
|
||||||
f"豆瓣标记和评论导入完成,共处理{self.total}篇,已存在{self.skipped}篇,新增{self.imported}篇。",
|
f"豆瓣标记和评论导入完成,共处理{self.total}篇,已存在{self.skipped}篇,新增{self.imported}篇。",
|
||||||
)
|
)
|
||||||
if len(self.failed):
|
if len(self.failed):
|
||||||
msg.error(self.user, f'豆瓣评论导入时未能处理以下网址:\n{" , ".join(self.failed)}')
|
msg.error(
|
||||||
|
self.user,
|
||||||
|
f'豆瓣评论导入时未能处理以下网址:\n{" , ".join(self.failed)}',
|
||||||
|
)
|
||||||
|
|
||||||
def import_mark_sheet(self, worksheet, shelf_type, sheet_name):
|
def import_mark_sheet(self, worksheet, shelf_type, sheet_name):
|
||||||
prefix = f"{self.user} {sheet_name}|"
|
prefix = f"{self.user} {sheet_name}|"
|
||||||
|
|
|
@ -71,7 +71,10 @@ class Migration(migrations.Migration):
|
||||||
"title",
|
"title",
|
||||||
models.CharField(default="", max_length=1000, verbose_name="标题"),
|
models.CharField(default="", max_length=1000, verbose_name="标题"),
|
||||||
),
|
),
|
||||||
("brief", models.TextField(blank=True, default="", verbose_name="简介")),
|
(
|
||||||
|
"brief",
|
||||||
|
models.TextField(blank=True, default="", verbose_name="简介"),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"cover",
|
"cover",
|
||||||
models.ImageField(
|
models.ImageField(
|
||||||
|
|
|
@ -32,27 +32,51 @@ def user_stats_of(collection: Collection, identity: APIdentity):
|
||||||
def prural_items(count: int, category: str):
|
def prural_items(count: int, category: str):
|
||||||
match category:
|
match category:
|
||||||
case "book":
|
case "book":
|
||||||
return ngettext("%(count)d book", "%(count)d books", count,) % {
|
return ngettext(
|
||||||
|
"%(count)d book",
|
||||||
|
"%(count)d books",
|
||||||
|
count,
|
||||||
|
) % {
|
||||||
"count": count,
|
"count": count,
|
||||||
}
|
}
|
||||||
case "movie":
|
case "movie":
|
||||||
return ngettext("%(count)d movie", "%(count)d movies", count,) % {
|
return ngettext(
|
||||||
|
"%(count)d movie",
|
||||||
|
"%(count)d movies",
|
||||||
|
count,
|
||||||
|
) % {
|
||||||
"count": count,
|
"count": count,
|
||||||
}
|
}
|
||||||
case "tv":
|
case "tv":
|
||||||
return ngettext("%(count)d tv show", "%(count)d tv shows", count,) % {
|
return ngettext(
|
||||||
|
"%(count)d tv show",
|
||||||
|
"%(count)d tv shows",
|
||||||
|
count,
|
||||||
|
) % {
|
||||||
"count": count,
|
"count": count,
|
||||||
}
|
}
|
||||||
case "music":
|
case "music":
|
||||||
return ngettext("%(count)d album", "%(count)d albums", count,) % {
|
return ngettext(
|
||||||
|
"%(count)d album",
|
||||||
|
"%(count)d albums",
|
||||||
|
count,
|
||||||
|
) % {
|
||||||
"count": count,
|
"count": count,
|
||||||
}
|
}
|
||||||
case "game":
|
case "game":
|
||||||
return ngettext("%(count)d game", "%(count)d games", count,) % {
|
return ngettext(
|
||||||
|
"%(count)d game",
|
||||||
|
"%(count)d games",
|
||||||
|
count,
|
||||||
|
) % {
|
||||||
"count": count,
|
"count": count,
|
||||||
}
|
}
|
||||||
case "podcast":
|
case "podcast":
|
||||||
return ngettext("%(count)d podcast", "%(count)d podcasts", count,) % {
|
return ngettext(
|
||||||
|
"%(count)d podcast",
|
||||||
|
"%(count)d podcasts",
|
||||||
|
count,
|
||||||
|
) % {
|
||||||
"count": count,
|
"count": count,
|
||||||
}
|
}
|
||||||
case "performance":
|
case "performance":
|
||||||
|
@ -64,6 +88,10 @@ def prural_items(count: int, category: str):
|
||||||
"count": count,
|
"count": count,
|
||||||
}
|
}
|
||||||
case _:
|
case _:
|
||||||
return ngettext("%(count)d item", "%(count)d items", count,) % {
|
return ngettext(
|
||||||
|
"%(count)d item",
|
||||||
|
"%(count)d items",
|
||||||
|
count,
|
||||||
|
) % {
|
||||||
"count": count,
|
"count": count,
|
||||||
}
|
}
|
||||||
|
|
|
@ -294,13 +294,15 @@ def get_related_acct_list(site, token, api):
|
||||||
r: list[dict[str, str]] = response.json()
|
r: list[dict[str, str]] = response.json()
|
||||||
results.extend(
|
results.extend(
|
||||||
map(
|
map(
|
||||||
lambda u: ( # type: ignore
|
lambda u: (
|
||||||
u["acct"]
|
( # type: ignore
|
||||||
if u["acct"].find("@") != -1
|
u["acct"]
|
||||||
else u["acct"] + "@" + site
|
if u["acct"].find("@") != -1
|
||||||
)
|
else u["acct"] + "@" + site
|
||||||
if "acct" in u
|
)
|
||||||
else u,
|
if "acct" in u
|
||||||
|
else u
|
||||||
|
),
|
||||||
r,
|
r,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -684,9 +686,11 @@ def share_collection(collection, comment, user, visibility_no, link):
|
||||||
if user == collection.owner.user
|
if user == collection.owner.user
|
||||||
else (
|
else (
|
||||||
_("shared {username}'s collection").format(
|
_("shared {username}'s collection").format(
|
||||||
username=" @" + collection.owner.user.mastodon_acct + " "
|
username=(
|
||||||
if collection.owner.user.mastodon_acct
|
" @" + collection.owner.user.mastodon_acct + " "
|
||||||
else " " + collection.owner.username + " "
|
if collection.owner.user.mastodon_acct
|
||||||
|
else " " + collection.owner.username + " "
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
black~=22.12.0
|
black~=24.4.2
|
||||||
coverage
|
coverage
|
||||||
django-debug-toolbar
|
django-debug-toolbar
|
||||||
django-stubs
|
django-stubs
|
||||||
djlint~=1.34.0
|
djlint~=1.34.1
|
||||||
isort~=5.13.2
|
isort~=5.13.2
|
||||||
lxml-stubs
|
lxml-stubs
|
||||||
pre-commit
|
pre-commit
|
||||||
|
|
|
@ -206,9 +206,9 @@ def connect_redirect_back(request):
|
||||||
)
|
)
|
||||||
return register_new_user(
|
return register_new_user(
|
||||||
request,
|
request,
|
||||||
username=None
|
username=(
|
||||||
if settings.MASTODON_ALLOW_ANY_SITE
|
None if settings.MASTODON_ALLOW_ANY_SITE else user_data["username"]
|
||||||
else user_data["username"],
|
),
|
||||||
mastodon_username=user_data["username"],
|
mastodon_username=user_data["username"],
|
||||||
mastodon_id=user_data["id"],
|
mastodon_id=user_data["id"],
|
||||||
mastodon_site=site,
|
mastodon_site=site,
|
||||||
|
|
|
@ -86,9 +86,11 @@ def init_identity(apps, schema_editor):
|
||||||
local=True,
|
local=True,
|
||||||
username=username,
|
username=username,
|
||||||
domain_name=domain,
|
domain_name=domain,
|
||||||
deleted=None
|
deleted=(
|
||||||
if user.is_active
|
None
|
||||||
else user.mastodon_last_reachable + timedelta(days=90),
|
if user.is_active
|
||||||
|
else user.mastodon_last_reachable + timedelta(days=90)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
takahe_user = TakaheUser.objects.create(
|
takahe_user = TakaheUser.objects.create(
|
||||||
pk=user.pk, email=handler, admin=user.is_superuser, password=user.password
|
pk=user.pk, email=handler, admin=user.is_superuser, password=user.password
|
||||||
|
|
|
@ -427,12 +427,16 @@ class User(AbstractUser):
|
||||||
sp = name.split("@")
|
sp = name.split("@")
|
||||||
if len(sp) == 2:
|
if len(sp) == 2:
|
||||||
query_kwargs = {
|
query_kwargs = {
|
||||||
"mastodon_username__iexact"
|
(
|
||||||
if case_sensitive
|
"mastodon_username__iexact"
|
||||||
else "mastodon_username": sp[0],
|
if case_sensitive
|
||||||
"mastodon_site__iexact"
|
else "mastodon_username"
|
||||||
if case_sensitive
|
): sp[0],
|
||||||
else "mastodon_site": sp[1],
|
(
|
||||||
|
"mastodon_site__iexact"
|
||||||
|
if case_sensitive
|
||||||
|
else "mastodon_site"
|
||||||
|
): sp[1],
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
Loading…
Add table
Reference in a new issue