Skip to content

Commit 27391c7

Browse files
committed
feat: experimental htmlkit
1 parent 385e211 commit 27391c7

File tree

7 files changed

+385
-23
lines changed

7 files changed

+385
-23
lines changed

Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM python:alpine AS base
1+
FROM python:slim AS base
22
WORKDIR /app
33

44

@@ -14,6 +14,7 @@ RUN --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
1414

1515
FROM base
1616

17+
RUN apt update && apt install --no-install-recommends -y libx11-6
1718
COPY --link --from=build /app/.venv/ .venv
1819
COPY --link . .
1920

pdm.lock

Lines changed: 23 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ dependencies = [
1010
"nonebot-adapter-milky~=0.5.0rc3",
1111
"nonebot-plugin-alconna~=0.59",
1212
"nonebot-plugin-apscheduler~=0.5",
13+
"nonebot-plugin-htmlkit @ https://github.com/ProgramRipper/plugin-htmlkit/releases/download/0.1.0-rc1/nonebot_plugin_htmlkit-0.1.0rc1-cp310-abi3-manylinux_2_34_x86_64.whl",
1314
"nonebot-plugin-htmlrender~=0.6",
1415
"nonebot-plugin-orm[sqlite]~=0.8",
1516
"nonebot-plugin-uninfo @ https://github.com/RF-Tar-Railt/nonebot-plugin-uninfo/archive/5b87d916af09d6a878039d3445193efda2ed1af3.zip",
@@ -30,6 +31,7 @@ adapters = [
3031
plugins = [
3132
"nonebot_plugin_alconna",
3233
"nonebot_plugin_apscheduler",
34+
"nonebot_plugin_htmlkit",
3335
"nonebot_plugin_htmlrender",
3436
"nonebot_plugin_orm",
3537
"nonebot_plugin_uninfo",

src/plugins/bilibili/plugins/dynamic/__init__.py

Lines changed: 86 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from asyncio import gather
22
from contextlib import asynccontextmanager
3+
from importlib.resources import as_file, files
34
from queue import PriorityQueue
45
from typing import Annotated, Any, AsyncGenerator
56

@@ -11,16 +12,18 @@
1112
from nonebot.plugin import PluginMetadata
1213
from nonebot_plugin_alconna import Alconna, Image, Subcommand, UniMessage, on_alconna
1314
from nonebot_plugin_apscheduler import scheduler
15+
from nonebot_plugin_htmlkit import template_to_pic
1416
from nonebot_plugin_htmlrender.browser import get_browser
1517
from nonebot_plugin_orm import async_scoped_session, get_session
1618
from nonebot_plugin_uninfo import MEMBER
1719
from nonebot_plugin_uninfo.orm import SceneModel, SceneOrm
1820
from playwright.async_api import BrowserContext, Page
1921
from sqlalchemy import exists, select
2022

21-
from .....utils import run_task, send_message
23+
from .....utils import css_fetch_fn, img_fetch_fn, run_task, send_message
2224
from ... import plugin_config as bilibili_config
2325
from ...utils import UID_ARG, get_share_click, handle_error, raise_for_status
26+
from . import templates
2427
from .config import Config
2528
from .models import Dynamic, Dynamics, Subscription
2629

@@ -82,7 +85,19 @@ async def get_dynamics(page: int = 1) -> Dynamics:
8285
"type": "all",
8386
"page": page,
8487
"features": ",".join(
85-
("itemOpusStyle", "listOnlyfans", "opusBigCover", "onlyfansVote")
88+
(
89+
"itemOpusStyle",
90+
"listOnlyfans",
91+
"opusBigCover",
92+
"onlyfansVote",
93+
"decorationCard",
94+
"onlyfansAssetsV2",
95+
"forwardListHidden",
96+
"ugcDelete",
97+
"onlyfansQaCard",
98+
"commentsNewVersion",
99+
"avatarAutoTheme",
100+
)
86101
),
87102
},
88103
)
@@ -163,7 +178,7 @@ async def render_screenshot(id_str: str) -> bytes:
163178
)
164179
await page.add_style_tag(
165180
content="""
166-
* {
181+
body {
167182
font-family: "LXGW ZhenKai GB", "LXGW WenKai GB", sans-serif !important;
168183
}
169184
@@ -198,15 +213,35 @@ async def render_screenshot(id_str: str) -> bytes:
198213
async def broadcast(dynamics: list[Dynamic]):
199214
async with get_session() as session:
200215
for dynamic in dynamics:
201-
screenshot, url, subs = await gather(
202-
render_screenshot(dynamic["id_str"]),
203-
get_share_click(dynamic["id_str"], "dynamic", "dt.dt-detail.0.0.pv"),
204-
session.scalars(
205-
select(Subscription).where(
206-
Subscription.uid == dynamic["modules"]["module_author"]["mid"]
207-
)
208-
),
209-
)
216+
with as_file(files(templates)) as templates_path:
217+
screenshot, url, subs = await gather(
218+
(
219+
template_to_pic(
220+
str(templates_path),
221+
"draw.html.j2",
222+
dynamic,
223+
max_width=360 * 3,
224+
device_height=640 * 3,
225+
allow_refit=False,
226+
img_fetch_fn=img_fetch_fn,
227+
css_fetch_fn=css_fetch_fn,
228+
image_format="jpeg",
229+
jpeg_quality=80,
230+
)
231+
if dynamic["type"] == "DYNAMIC_TYPE_DRAW"
232+
and not dynamic["modules"]["module_dynamic"]["additional"]
233+
else render_screenshot(dynamic["id_str"])
234+
),
235+
get_share_click(
236+
dynamic["id_str"], "dynamic", "dt.dt-detail.0.0.pv"
237+
),
238+
session.scalars(
239+
select(Subscription).where(
240+
Subscription.uid
241+
== dynamic["modules"]["module_author"]["mid"]
242+
)
243+
),
244+
)
210245

211246
msg = plugin_config.template.format(
212247
name=dynamic["modules"]["module_author"]["name"],
@@ -310,16 +345,50 @@ async def _(id_str: str):
310345
dynamic = raise_for_status(
311346
await client.get(
312347
"/polymer/web-dynamic/v1/detail",
313-
params={"id": id_str, "features": "itemOpusStyle"},
348+
params={
349+
"id": id_str,
350+
"features": ",".join(
351+
(
352+
"itemOpusStyle",
353+
"listOnlyfans",
354+
"opusBigCover",
355+
"onlyfansVote",
356+
"decorationCard",
357+
"onlyfansAssetsV2",
358+
"forwardListHidden",
359+
"ugcDelete",
360+
"onlyfansQaCard",
361+
"commentsNewVersion",
362+
"avatarAutoTheme",
363+
)
364+
),
365+
},
314366
)
315367
)["item"]
316368
except Exception:
317369
await handle_error("获取动态信息失败")
318370

319-
screenshot, url = await gather(
320-
render_screenshot(id_str),
321-
get_share_click(id_str, "dynamic", "dt.dt-detail.0.0.pv"),
322-
)
371+
with as_file(files(templates)) as templates_path:
372+
screenshot, url = await gather(
373+
(
374+
template_to_pic(
375+
str(templates_path),
376+
"draw.html.j2",
377+
dynamic,
378+
max_width=360 * 3,
379+
device_height=640 * 3,
380+
allow_refit=False,
381+
img_fetch_fn=img_fetch_fn,
382+
css_fetch_fn=css_fetch_fn,
383+
image_format="jpeg",
384+
jpeg_quality=80,
385+
)
386+
if dynamic["type"] == "DYNAMIC_TYPE_DRAW"
387+
and not dynamic["modules"]["module_dynamic"]["additional"]
388+
else render_screenshot(dynamic["id_str"])
389+
),
390+
get_share_click(id_str, "dynamic", "dt.dt-detail.0.0.pv"),
391+
)
323392
await plugin_config.template.format(
324393
name=dynamic["modules"]["module_author"]["name"],
325394
action=dynamic["modules"]["module_author"]["pub_action"]

src/plugins/bilibili/plugins/dynamic/models.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import TypedDict
1+
from typing import Any, TypedDict
22

33
from nonebot_plugin_orm import Model
44
from nonebot_plugin_uninfo.orm import SceneModel
@@ -14,6 +14,7 @@ class ModuleAuthor(TypedDict):
1414

1515
class Modules(TypedDict):
1616
module_author: ModuleAuthor
17+
module_dynamic: dict[str, Any]
1718

1819

1920
class Dynamic(TypedDict):

0 commit comments

Comments
 (0)