Skip to content

Commit

Permalink
feat: new subject review (#66)
Browse files Browse the repository at this point in the history
  • Loading branch information
trim21 authored Sep 27, 2024
1 parent bead421 commit 6757664
Show file tree
Hide file tree
Showing 43 changed files with 1,890 additions and 165 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: 'true'

- uses: actions/setup-python@v5
with:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: 'true'

- uses: actions/setup-python@v5
with:
Expand All @@ -33,6 +35,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: 'true'

- uses: actions/setup-python@v5
with:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/release-docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ jobs:

steps:
- uses: actions/checkout@v4
with:
submodules: 'true'

- uses: docker/login-action@v3
with:
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "common"]
path = common
url = https://github.com/Bangumi/common
2 changes: 1 addition & 1 deletion common
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"private": true,
"scripts": {},
"dependencies": {
"@bgm38/wiki": "^0.2.8",
"bootstrap": "^5.3.3",
"diff2html": "^3.4.48",
"jquery": "^3.7.1",
Expand Down
264 changes: 136 additions & 128 deletions poetry.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ uvicorn = { version = "^0.30.6" }
uuid-utils = "^0.9.0"
regex = "^2024.9.11"
bgm-tv-wiki = "^0.0.26"
pyyaml = "^6.0.2"
msgspec = "^0.18.6"

# speedup litestar
fast-query-parsers = "^1.0.3"
Expand Down
27 changes: 27 additions & 0 deletions scripts/build-common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import hashlib
import json
import shutil
from pathlib import Path

import yaml


project_root = Path(__file__, "../../").resolve()
common_path = project_root.joinpath("common").resolve()

target_path = project_root.joinpath("static/common")

shutil.rmtree(target_path)

target_path.mkdir(exist_ok=True, parents=True)

file: Path
for file in common_path.iterdir():
if file.suffix in {".yaml", ".yml"}:
target_path.joinpath(
file.with_suffix(
"." + hashlib.sha3_256(file.read_bytes()).hexdigest()[:6] + ".json"
).name
).write_bytes(
json.dumps(yaml.safe_load(file.read_bytes()), ensure_ascii=False, indent=2).encode()
)
1 change: 1 addition & 0 deletions scripts/fetch-static-files.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ def main() -> None:
("bootstrap", None),
("jquery", ("dist",)),
("js-cookie", None),
("@bgm38/wiki", None),
]:
download_npm_package(
pkg,
Expand Down
2 changes: 1 addition & 1 deletion server/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def internal_error_handler(req: Request, exc: Exception) -> Response[Any]:
return Response(
content={
"status_code": 500,
"detail": f"Internal Server Error: {type(exc)}",
"detail": "Internal Server Error",
"method": req.method,
"url": str(req.url),
},
Expand Down
121 changes: 109 additions & 12 deletions server/contrib.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from uuid import UUID

import litestar
import msgspec.json
from litestar import Response
from litestar.enums import RequestEncodingType
from litestar.exceptions import (
Expand All @@ -17,6 +18,7 @@
from litestar.response import Redirect, Template
from uuid_utils.compat import uuid7

from common.py.platform import PLATFORM_CONFIG, WIKI_TEMPLATES
from server.auth import require_user_login
from server.base import (
AuthorizedRequest,
Expand All @@ -30,7 +32,7 @@
)
from server.config import TURNSTILE_SECRET_KEY, UTC
from server.errors import BadRequestException
from server.model import PatchState, SubjectPatch
from server.model import PatchAction, PatchState, SubjectPatch, SubjectType
from server.router import Router
from server.strings import check_invalid_input_str, contains_invalid_input_str

Expand Down Expand Up @@ -289,15 +291,20 @@ async def _(request: AuthorizedRequest, patch_id: UUID) -> Response[Any]:
if not p:
raise NotFoundException()

if p["from_user_id"] != request.auth.user_id:
patch = SubjectPatch.from_dict(p)

if patch.from_user_id != request.auth.user_id:
raise PermissionDeniedException("you are not owner of this patch")

if p["state"] != PatchState.Pending:
if patch.state != PatchState.Pending:
raise BadRequestException("patch 已经被审核")

res = await http_client.get(f"https://next.bgm.tv/p1/wiki/subjects/{p['subject_id']}")
res.raise_for_status()
wiki = res.json()
if patch.action == PatchAction.Update:
res = await http_client.get(f"https://next.bgm.tv/p1/wiki/subjects/{p['subject_id']}")
res.raise_for_status()
wiki = res.json()
else:
wiki = {}

return Template(
"suggest.html.jinja2",
Expand Down Expand Up @@ -346,18 +353,38 @@ async def _(
if not p:
raise NotFoundException()

changed = {}
patch = SubjectPatch.from_dict(p)

res = await http_client.get(f"https://next.bgm.tv/p1/wiki/subjects/{p['subject_id']}")
res.raise_for_status()
original = res.json()
changed = {}

if p["from_user_id"] != request.auth.user_id:
if patch.from_user_id != request.auth.user_id:
raise PermissionDeniedException()

if p["state"] != PatchState.Pending:
if patch.state != PatchState.Pending:
raise BadRequestException("patch已经被审核")

if patch.action == PatchAction.Create:
await conn.execute(
"""
update subject_patch set name=$1, infobox=$2, summary=$3, nsfw=$4, reason=$5,
updated_at=$6
where id=$7
""",
data.name,
data.infobox,
data.summary,
data.nsfw is not None,
data.reason,
datetime.now(tz=UTC),
patch_id,
)

return Redirect(f"/subject/{patch_id}")

res = await http_client.get(f"https://next.bgm.tv/p1/wiki/subjects/{p['subject_id']}")
res.raise_for_status()
original = res.json()

for field in ["name", "infobox", "summary"]:
if getattr(data, field) != original[field]:
changed[field] = getattr(data, field)
Expand Down Expand Up @@ -536,3 +563,73 @@ async def delete_episode_patch(patch_id: UUID, request: AuthorizedRequest) -> Re
)

return Redirect("/?type=episode")


@router
@litestar.get(
"/new-subject/{subject_type:int}",
guards=[require_user_login],
)
async def new_subject(subject_type: SubjectType) -> Template:
return Template(
"new-subject.html.jinja2",
context={
"subject_type": subject_type,
"pp": PLATFORM_CONFIG.get(subject_type),
"platforms": msgspec.json.encode(PLATFORM_CONFIG.get(subject_type)).decode(),
"templates": WIKI_TEMPLATES,
},
)


@dataclass(frozen=True, slots=True, kw_only=True)
class NewSubject:
name: str
type_id: SubjectType
platform: int
infobox: str
summary: str
# HTML form will only include checkbox when it's checked,
# so any input is true, default value is false.
nsfw: str | None = None

patch_desc: str = ""
cf_turnstile_response: str


@router
@litestar.post(
"/new-subject",
guards=[require_user_login],
)
async def patch_for_new_subject(
data: Annotated[NewSubject, Body(media_type=RequestEncodingType.URL_ENCODED)],
request: AuthorizedRequest,
) -> Redirect:
if not request.auth.super_user():
await _validate_captcha(data.cf_turnstile_response)

if data.platform not in PLATFORM_CONFIG.get(data.type_id, {}):
raise BadRequestException("平台不正确")

pk = uuid7()

await pg.execute(
"""
insert into subject_patch (id, subject_id, from_user_id, reason, name, infobox, summary, nsfw,
subject_type, platform, patch_desc, action)
VALUES ($1, 0, $2, '', $3, $4, $5, $6, $7, $8, $9, $10)
""",
pk,
request.auth.user_id,
data.name,
data.infobox,
data.summary,
data.nsfw is not None,
data.type_id,
data.platform,
data.patch_desc,
PatchAction.Create,
)

return Redirect(f"/subject/{pk}")
2 changes: 1 addition & 1 deletion server/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ async def _(

if patch_type == PatchType.Subject:
table = "view_subject_patch"
column = "id,created_at,updated_at,reason,from_user_id,wiki_user_id,state,original_name,subject_type,comments_count"
column = "id,created_at,updated_at,reason,from_user_id,wiki_user_id,state,action,original_name,subject_type,comments_count"
elif patch_type == PatchType.Episode:
table = "view_episode_patch"
column = "id,created_at,updated_at,reason,from_user_id,wiki_user_id,state,original_name,comments_count,ep"
Expand Down
1 change: 1 addition & 0 deletions server/migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def load_sql(fn: str) -> str:
Migrate(10, create_or_update_view_sql),
Migrate(11, load_sql("011-extra-description.sql")),
Migrate(12, load_sql("012-show-ep-num.sql")),
Migrate(13, load_sql("013-add-subject-platform.sql")),
]

if not all(x <= y for x, y in itertools.pairwise(migrations)):
Expand Down
20 changes: 20 additions & 0 deletions server/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,23 @@ class PatchState(enum.IntEnum):
Outdated = 3


class PatchAction(enum.IntEnum):
Unknown = 0
Update = 1
Create = 2


class SubjectType(enum.IntEnum):
Book = 1
Anime = 2
Music = 3
Game = 4
Real = 6

def __str__(self) -> str:
return str(self.value)


T = TypeVar("T")


Expand Down Expand Up @@ -50,6 +67,9 @@ class SubjectPatch(PatchBase, kw_only=True, frozen=True):

nsfw: bool | None

platform: int | None
action: PatchAction


class EpisodePatch(PatchBase, kw_only=True, frozen=True):
episode_id: int
Expand Down
13 changes: 3 additions & 10 deletions server/patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
from uuid import UUID

import litestar
from litestar.exceptions import InternalServerException, NotFoundException
from litestar.exceptions import NotFoundException
from litestar.response import Redirect, Template
from sslog import logger

from server.base import Request, patch_keys, pg
from server.model import EpisodePatch, PatchState, PatchType, SubjectPatch
Expand Down Expand Up @@ -45,12 +44,9 @@ async def get_patch(patch_id: UUID, request: Request) -> Template:

infobox_patch = ""
if patch.infobox is not None:
if patch.original_infobox is None:
logger.error(f"broken patch {patch_id!r}")
raise InternalServerException
infobox_patch = "".join(
difflib.unified_diff(
(escape_invisible(patch.original_infobox) + "\n").splitlines(True),
(escape_invisible(patch.original_infobox or "") + "\n").splitlines(True),
(escape_invisible(patch.infobox) + "\n").splitlines(True),
"infobox",
"infobox",
Expand All @@ -60,13 +56,10 @@ async def get_patch(patch_id: UUID, request: Request) -> Template:

summary_patch = ""
if patch.summary is not None:
if patch.original_summary is None:
logger.error(f"broken patch {patch_id!r}")
raise InternalServerException
summary_patch = "".join(
# need a tailing new line to generate correct diff
difflib.unified_diff(
escape_invisible(patch.original_summary + "\n").splitlines(True),
(escape_invisible(patch.original_summary or "") + "\n").splitlines(True),
escape_invisible(patch.summary + "\n").splitlines(True),
"summary",
"summary",
Expand Down
Loading

0 comments on commit 6757664

Please sign in to comment.