From 5f59f9f180fce4da59087ce08b073c4138fd0573 Mon Sep 17 00:00:00 2001 From: yqy Date: Tue, 28 Apr 2026 00:39:51 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9C=A8=20=E5=85=AC=E5=91=8A=E5=8D=A1?= =?UTF-8?q?=E7=89=87=E6=94=B9=E4=B8=BA=20DNA=20=E9=A3=8E=E6=A0=BC=E6=B7=B1?= =?UTF-8?q?=E7=B4=AB=E6=A8=A1=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 列表页:星空背景 + 深色面板卡片 + 砖红/金强调,3 列 × 7 行展示 20 条 - 详情页:富文本分页,6000px 阈值;卡片头像/二维码/作者 - 命令仅支持短序号 (1~20),不再透出 postId - 字段对齐真实接口:postCover / videoContent.coverUrl / imgContent[].url、showTime - 帖子 web URL 修正为 https://dnabbs.yingxiong.com/pc/detail/{postId} - 资产收回 dna_ann/,不再侵入 utils/ --- DNAUID/dna_ann/__init__.py | 119 ++-- DNAUID/dna_ann/_image.py | 124 ++++ DNAUID/dna_ann/ann_card.py | 528 ++++++++++-------- .../texture2d/dna_official_avatar.jpeg | Bin 0 -> 105779 bytes DNAUID/dna_ann/utils.py | 159 ++++++ 5 files changed, 645 insertions(+), 285 deletions(-) create mode 100644 DNAUID/dna_ann/_image.py create mode 100644 DNAUID/dna_ann/texture2d/dna_official_avatar.jpeg create mode 100644 DNAUID/dna_ann/utils.py diff --git a/DNAUID/dna_ann/__init__.py b/DNAUID/dna_ann/__init__.py index 37b217a..90cfa4c 100644 --- a/DNAUID/dna_ann/__init__.py +++ b/DNAUID/dna_ann/__init__.py @@ -1,6 +1,7 @@ +from __future__ import annotations + import random import asyncio -from typing import List from gsuid_core.sv import SV from gsuid_core.aps import scheduler @@ -9,79 +10,74 @@ from gsuid_core.models import Event from gsuid_core.subscribe import gs_subscribe +from .utils import resolve_index, fetch_ann_list, build_index_map +from .ann_card import draw_ann_list_img, draw_ann_detail_img from ..utils.dna_api import dna_api -from ..dna_ann.ann_card import ann_detail_card from ..utils.msgs.notify import send_dna_notify from ..dna_config.dna_config import DNAConfig sv_ann = SV("DNA公告") sv_ann_sub = SV("订阅DNA公告", pm=3) -task_name_ann = "订阅DNA公告" -ann_minute_check: int = DNAConfig.get_config("AnnMinuteCheck").data or 10 +TASK_NAME_ANN = "订阅DNA公告" +ANN_MIN_CHECK: int = DNAConfig.get_config("AnnMinuteCheck").data or 10 @sv_ann.on_command("公告") async def ann_dna(bot: Bot, ev: Event): - ann_id = ev.text - if not ann_id: - ann_list = await dna_api.get_ann_list() - if not ann_list: - return await bot.send("获取公告列表失败") - anns = "\n".join([f"{x['postId']}" for x in ann_list]) - return await send_dna_notify(bot, ev, f"公告列表: \n{anns}") + text = ev.text.strip().replace("#", "") + + if not text: + result = await draw_ann_list_img() + if isinstance(result, str): + return await send_dna_notify(bot, ev, result) + return await bot.send(result) # type: ignore - ann_id = ann_id.replace("#", "") - if not ann_id.isdigit(): - raise Exception("公告ID不正确") + posts = await fetch_ann_list(prefer_cache=True) + if not posts: + return await send_dna_notify(bot, ev, "获取公告列表失败") - img = await ann_detail_card(ann_id) - return await bot.send(img) # type: ignore + post_id = resolve_index(text, build_index_map(posts)) + if post_id is None: + return await send_dna_notify(bot, ev, "公告序号不正确,发送 公告 查看可用列表") + + result = await draw_ann_detail_img(post_id) + if isinstance(result, str): + return await send_dna_notify(bot, ev, result) + return await bot.send(result) # type: ignore @sv_ann_sub.on_fullmatch("订阅公告") async def sub_ann_dna(bot: Bot, ev: Event): if not ev.group_id: - return await bot.send("请在群聊中订阅") + return await send_dna_notify(bot, ev, "请在群聊中订阅") if not DNAConfig.get_config("DNAAnnOpen").data: - return await bot.send("二重螺旋公告推送功能已关闭") - - data = await gs_subscribe.get_subscribe(task_name_ann) - if data: - for subscribe in data: - if subscribe.group_id == ev.group_id: - return await bot.send("已经订阅了二重螺旋公告!") + return await send_dna_notify(bot, ev, "二重螺旋公告推送功能已关闭") - await gs_subscribe.add_subscribe( - "session", - task_name=task_name_ann, - event=ev, - extra_message="", - ) + data = await gs_subscribe.get_subscribe(TASK_NAME_ANN) + if data and any(sub.group_id == ev.group_id for sub in data): + return await send_dna_notify(bot, ev, "已经订阅了二重螺旋公告!") - logger.info(data) - await bot.send("成功订阅二重螺旋公告!") + await gs_subscribe.add_subscribe("session", TASK_NAME_ANN, ev, extra_message="") + await send_dna_notify(bot, ev, "成功订阅二重螺旋公告!") @sv_ann_sub.on_fullmatch(("取消订阅公告", "取消公告", "退订公告")) async def unsub_ann_dna(bot: Bot, ev: Event): if not ev.group_id: - return await bot.send("请在群聊中取消订阅") + return await send_dna_notify(bot, ev, "请在群聊中取消订阅") - data = await gs_subscribe.get_subscribe(task_name_ann) - if data: - for subscribe in data: - if subscribe.group_id == ev.group_id: - await gs_subscribe.delete_subscribe("session", task_name_ann, ev) - return await bot.send("成功取消订阅二重螺旋公告!") - else: - if not DNAConfig.get_config("DNAAnnOpen").data: - return await bot.send("二重螺旋公告推送功能已关闭") + data = await gs_subscribe.get_subscribe(TASK_NAME_ANN) + if data and any(sub.group_id == ev.group_id for sub in data): + await gs_subscribe.delete_subscribe("session", TASK_NAME_ANN, ev) + return await send_dna_notify(bot, ev, "成功取消订阅二重螺旋公告!") - return await bot.send("未曾订阅二重螺旋公告!") + if not DNAConfig.get_config("DNAAnnOpen").data: + return await send_dna_notify(bot, ev, "二重螺旋公告推送功能已关闭") + return await send_dna_notify(bot, ev, "未曾订阅二重螺旋公告!") -@scheduler.scheduled_job("interval", minutes=ann_minute_check) +@scheduler.scheduled_job("interval", minutes=ANN_MIN_CHECK) async def check_dna_ann(): if not DNAConfig.get_config("DNAAnnOpen").data: return @@ -90,42 +86,39 @@ async def check_dna_ann(): async def check_dna_ann_state(): logger.info("[二重螺旋公告] 定时任务: 二重螺旋公告查询..") - datas = await gs_subscribe.get_subscribe(task_name_ann) - if not datas: + subs = await gs_subscribe.get_subscribe(TASK_NAME_ANN) + if not subs: logger.info("[二重螺旋公告] 暂无群订阅") return - ids: List[int] = DNAConfig.get_config("DNAAnnIds").data or [] new_ann_list = await dna_api.get_ann_list() if not new_ann_list: return - new_ann_ids = [int(x["postId"]) for x in new_ann_list] - if not ids: - DNAConfig.set_config("DNAAnnIds", new_ann_ids) + known_ids: list[int] = DNAConfig.get_config("DNAAnnIds").data or [] + fresh_ids = [int(post["postId"]) for post in new_ann_list] + + if not known_ids: + DNAConfig.set_config("DNAAnnIds", fresh_ids) logger.info("[二重螺旋公告] 初始成功, 将在下个轮询中更新.") return - new_ann_need_send = [] - for ann_id in new_ann_ids: - if ann_id not in ids: - new_ann_need_send.append(ann_id) - - if not new_ann_need_send: + pending = [post_id for post_id in fresh_ids if post_id not in known_ids] + if not pending: logger.info("[二重螺旋公告] 没有最新公告") return - logger.info(f"[二重螺旋公告] 更新公告id: {new_ann_need_send}") - save_ids = sorted(ids, reverse=True)[:50] + new_ann_ids - DNAConfig.set_config("DNAAnnIds", list(set(save_ids))) + logger.info(f"[二重螺旋公告] 更新公告id: {pending}") + merged = sorted(set(known_ids) | set(fresh_ids), reverse=True)[:50] + DNAConfig.set_config("DNAAnnIds", merged) - for ann_id in new_ann_need_send: + for post_id in pending: try: - img = await ann_detail_card(ann_id, is_check_time=True) + img = await draw_ann_detail_img(post_id, is_check_time=True) if isinstance(img, str): continue - for subscribe in datas: - await subscribe.send(img) # type: ignore + for sub in subs: + await sub.send(img) # type: ignore await asyncio.sleep(random.uniform(1, 3)) except Exception as e: logger.exception(e) diff --git a/DNAUID/dna_ann/_image.py b/DNAUID/dna_ann/_image.py new file mode 100644 index 0000000..a4eb5bb --- /dev/null +++ b/DNAUID/dna_ann/_image.py @@ -0,0 +1,124 @@ +from __future__ import annotations + +import hashlib +from pathlib import Path +from urllib.parse import quote_plus + +from PIL import Image, ImageOps, ImageDraw, ImageFont + +from gsuid_core.utils.download_resource.download_file import download + +from ..utils.resource.RESOURCE_PATH import ANN_CARD_PATH + +Color = tuple[int, int, int] | tuple[int, int, int, int] +Size = tuple[int, int] + +DEFAULT_LINE_GAP = 8 +DEFAULT_ELLIPSIS = "..." + +QR_CACHE_PATH = ANN_CARD_PATH / "qr" +PREVIEW_CACHE_PATH = ANN_CARD_PATH / "preview" +DETAIL_CACHE_PATH = ANN_CARD_PATH / "detail" + + +def cache_name(*parts: object, ext: str = "png") -> str: + raw = "|".join(str(part) for part in parts) + return f"{hashlib.sha1(raw.encode('utf-8')).hexdigest()}.{ext}" + + +async def fetch_image(path: Path, pic_url: str, *, name: str | None = None) -> Image.Image: + path.mkdir(parents=True, exist_ok=True) + file_name = name or pic_url.split("/")[-1] + target = path / file_name + if not target.exists(): + await download(pic_url, path, file_name, tag="[DNA]") + return Image.open(target).convert("RGBA") + + +async def load_qr_code(url: str, size: int = 220) -> Image.Image | None: + qr_url = f"https://api.qrserver.com/v1/create-qr-code/?size={size}x{size}&data={quote_plus(url)}" + try: + image = await fetch_image(QR_CACHE_PATH, qr_url, name=cache_name("qr", url, size)) + except OSError: + return None + return image.convert("RGB").resize((size, size), Image.Resampling.LANCZOS) + + +def shrink_to_width(image: Image.Image, max_width: int) -> Image.Image: + if image.width <= max_width: + return image + ratio = max_width / image.width + return image.resize((int(max_width), int(image.height * ratio)), Image.Resampling.LANCZOS) + + +def fit_image(image: Image.Image, size: Size) -> Image.Image: + return ImageOps.fit(image.convert("RGB"), size, method=Image.Resampling.LANCZOS) + + +def rounded_mask(size: Size, radius: int) -> Image.Image: + mask = Image.new("L", size, 0) + ImageDraw.Draw(mask).rounded_rectangle((0, 0, size[0], size[1]), radius=radius, fill=255) + return mask + + +def line_height(font: ImageFont.FreeTypeFont) -> int: + return sum(font.getmetrics()) + + +def wrap_text( + draw: ImageDraw.ImageDraw, + text: str, + font: ImageFont.FreeTypeFont, + max_width: int, + max_lines: int | None = None, + ellipsis: str = DEFAULT_ELLIPSIS, +) -> list[str]: + lines: list[str] = [] + raw_lines = text.splitlines() if text else [""] + for raw_line in raw_lines: + current = "" + for char in raw_line: + trial = f"{current}{char}" + width = draw.textbbox((0, 0), trial, font=font)[2] + if current and width > max_width: + lines.append(current) + current = char + else: + current = trial + lines.append(current if current else " ") + + if max_lines and len(lines) > max_lines: + lines = lines[:max_lines] + lines[-1] = lines[-1].rstrip(" .") + ellipsis + return lines + + +def draw_text_block( + draw: ImageDraw.ImageDraw, + xy: tuple[int, int], + text: str, + font: ImageFont.FreeTypeFont, + fill: Color, + max_width: int, + *, + line_gap: int = DEFAULT_LINE_GAP, + max_lines: int | None = None, +) -> int: + x, y = xy + lines = wrap_text(draw, text, font, max_width, max_lines) + text_height = line_height(font) + for index, line in enumerate(lines): + draw.text((x, y), line, font=font, fill=fill) + y += text_height + if index != len(lines) - 1: + y += line_gap + return y + + +def round_avatar(avatar: Image.Image, size: int) -> Image.Image: + canvas = Image.new("RGBA", (size, size), (0, 0, 0, 0)) + head = avatar.convert("RGBA").resize((size, size), Image.Resampling.LANCZOS) + mask = Image.new("L", (size, size), 0) + ImageDraw.Draw(mask).ellipse((0, 0, size, size), fill=255) + canvas.paste(head, (0, 0), mask) + return canvas diff --git a/DNAUID/dna_ann/ann_card.py b/DNAUID/dna_ann/ann_card.py index 6773240..b4a23cc 100644 --- a/DNAUID/dna_ann/ann_card.py +++ b/DNAUID/dna_ann/ann_card.py @@ -1,248 +1,332 @@ -import re -import html +from __future__ import annotations + import time -from typing import List, Union -from datetime import datetime +from pathlib import Path -from PIL import Image, ImageOps, ImageDraw +from PIL import Image, ImageDraw from gsuid_core.logger import logger from gsuid_core.utils.image.convert import convert_img -from gsuid_core.utils.image.image_tools import easy_paste - -from ..utils import dna_api, get_datetime -from ..utils.image import download_pic_from_url -from ..utils.fonts.dna_fonts import unicode_font_26 -from ..utils.resource.RESOURCE_PATH import ANN_CARD_PATH - - -async def ann_batch_card(post_content: List, drow_height: float) -> bytes: - im = Image.new("RGB", (1080, drow_height), "#f9f6f2") # type: ignore - draw = ImageDraw.Draw(im) - x, y = 0, 0 - - for temp in post_content: - if temp["contentType"] == 1: - content = temp["content"] - drow_duanluo, _, drow_line_height, _ = split_text(content) - for duanluo, line_count in drow_duanluo: - if duanluo.strip(): - draw.text((x, y), duanluo, fill=(0, 0, 0), font=unicode_font_26) - y += drow_line_height * line_count + 30 - elif ( - temp["contentType"] == 2 and "url" in temp and temp["url"].lower().endswith(("jpg", "png", "jpeg", "webp")) - ): - img = await download_pic_from_url(ANN_CARD_PATH, temp["url"]) - img_x = 0 - if img.width > im.width: - ratio = im.width / img.width - img = img.resize((int(img.width * ratio), int(img.height * ratio))) - else: - img_x = (im.width - img.width) // 2 - easy_paste(im, img, (img_x, y)) - y += img.size[1] + 40 - elif ( - temp["contentType"] == 5 - and "contentVideo" in temp - and "coverUrl" in temp["contentVideo"] - and temp["contentVideo"]["coverUrl"].lower().endswith(("jpg", "png", "jpeg", "webp")) - ): - try: - video_temp = temp["contentVideo"] - img = await download_pic_from_url(ANN_CARD_PATH, video_temp["coverUrl"]) - img_x = 0 - if img.width > im.width: - ratio = im.width / img.width - img = img.resize((int(img.width * ratio), int(img.height * ratio))) - else: - img_x = (im.width - img.width) // 2 - easy_paste(im, img, (img_x, y)) - y += img.size[1] + 40 - except Exception: - pass - - if hasattr(unicode_font_26, "getbbox"): - bbox = unicode_font_26.getbbox("囗") - padding = ( - int(bbox[2] - bbox[0]), - int(bbox[3] - bbox[1]), - int(bbox[2] - bbox[0]), - int(bbox[3] - bbox[1]), + +from .utils import ( + LIST_DISPLAY_LIMIT, + pick_time, + get_post_url, + pick_preview, + pick_subject, + extract_blocks, + fetch_ann_list, + format_post_time, + post_time_to_timestamp, +) +from ..utils import dna_api +from ._image import ( + DETAIL_CACHE_PATH, + PREVIEW_CACHE_PATH, + fit_image, + wrap_text, + cache_name, + fetch_image, + line_height, + load_qr_code, + round_avatar, + rounded_mask, + draw_text_block, + shrink_to_width, +) +from ..utils.image import ( + COLOR_GOLDENROD, + COLOR_FIRE_BRICK, + COLOR_PALE_GOLDENROD, + get_dna_bg, +) +from ..dna_config.prefix import DNA_PREFIX +from ..utils.fonts.dna_fonts import ( + unicode_font_18, + unicode_font_22, + unicode_font_24, + unicode_font_26, + unicode_font_28, + unicode_font_60, +) + +WIDTH = 1080 +PADDING = 40 +GRID_GAP = 24 +CARD_RADIUS = 22 +PAGE_LIMIT = 6000 + +GRID_COLS = 3 + +# DNA 深色面板配色 +COLOR_PANEL_DARK = (22, 18, 36, 220) +COLOR_PANEL_BORDER = (90, 70, 130, 180) +COLOR_TITLE_LIGHT = (245, 240, 225) +COLOR_TEXT_LIGHT = (210, 205, 220) +COLOR_MUTED_LIGHT = (150, 145, 175) +COLOR_DIVIDER_DARK = (95, 80, 130, 180) + +_OFFICIAL_AVATAR = Path(__file__).parent / "texture2d" / "dna_official_avatar.jpeg" + + +async def _load_preview(url: str, width: int, height: int) -> Image.Image | None: + if not url: + return None + try: + image = await fetch_image(PREVIEW_CACHE_PATH, url, name=cache_name("preview", url)) + except OSError: + return None + return fit_image(image, (width, height)) + + +async def _load_detail_image(url: str, max_width: int) -> Image.Image: + try: + image = await fetch_image(DETAIL_CACHE_PATH, url, name=cache_name("detail", url)) + except OSError: + return Image.new("RGB", (max_width, 320), (40, 30, 60)) + return shrink_to_width(image.convert("RGB"), max_width) + + +def _load_avatar(size: int) -> Image.Image: + if _OFFICIAL_AVATAR.exists(): + return round_avatar(Image.open(_OFFICIAL_AVATAR).convert("RGBA"), size) + return round_avatar(Image.new("RGB", (size, size), COLOR_FIRE_BRICK), size) + + +def _draw_dark_panel(canvas: Image.Image, box: tuple[int, int, int, int], *, radius: int = CARD_RADIUS) -> None: + layer = Image.new("RGBA", canvas.size, (0, 0, 0, 0)) + draw = ImageDraw.Draw(layer) + draw.rounded_rectangle(box, radius=radius, fill=COLOR_PANEL_DARK) + draw.rounded_rectangle(box, radius=radius, outline=COLOR_PANEL_BORDER, width=2) + canvas.alpha_composite(layer) + + +async def draw_ann_list_img() -> bytes | str: + posts = await fetch_ann_list(prefer_cache=True) + if not posts: + return "获取公告列表失败" + + visible = posts[:LIST_DISPLAY_LIMIT] + rows = (len(visible) + GRID_COLS - 1) // GRID_COLS + + grid_width = WIDTH - PADDING * 2 + card_width = (grid_width - GRID_GAP * (GRID_COLS - 1)) // GRID_COLS + image_height = 156 + card_height = 308 + + title_band_height = 168 + title_to_grid_gap = 32 + footer_card_height = 96 + grid_to_footer_gap = 36 + canvas_height = ( + title_band_height + + title_to_grid_gap + + rows * card_height + + max(0, rows - 1) * GRID_GAP + + grid_to_footer_gap + + footer_card_height + + PADDING + ) + + canvas = get_dna_bg(WIDTH, canvas_height).convert("RGBA") + + # 顶部加深一层让标题更显眼 + title_overlay = Image.new("RGBA", (WIDTH, title_band_height), (10, 8, 20, 80)) + canvas.alpha_composite(title_overlay, (0, 0)) + + draw = ImageDraw.Draw(canvas) + draw.text( + (PADDING, title_band_height // 2), + "二重螺旋公告", + font=unicode_font_60, + fill=COLOR_PALE_GOLDENROD, + anchor="lm", + ) + # 标题左侧装饰条 + draw.rounded_rectangle( + (PADDING - 12, title_band_height // 2 - 32, PADDING - 4, title_band_height // 2 + 32), + radius=4, + fill=COLOR_FIRE_BRICK, + ) + + grid_top = title_band_height + title_to_grid_gap + for idx, post in enumerate(visible, start=1): + col = (idx - 1) % GRID_COLS + row = (idx - 1) // GRID_COLS + left = PADDING + col * (card_width + GRID_GAP) + top = grid_top + row * (card_height + GRID_GAP) + right = left + card_width + bottom = top + card_height + + _draw_dark_panel(canvas, (left, top, right, bottom)) + draw = ImageDraw.Draw(canvas) + + preview = await _load_preview(pick_preview(post), card_width, image_height) + if preview is not None: + canvas.paste(preview, (left, top), rounded_mask((card_width, image_height), CARD_RADIUS)) + + badge_w, badge_h = 76, 40 + badge_left = left + 14 + badge_top = top + 14 + draw.rounded_rectangle( + (badge_left, badge_top, badge_left + badge_w, badge_top + badge_h), + radius=12, + fill=COLOR_FIRE_BRICK, + ) + draw.text( + (badge_left + badge_w // 2, badge_top + badge_h // 2), + f"#{idx}", + font=unicode_font_24, + fill=COLOR_PALE_GOLDENROD, + anchor="mm", + ) + + text_left = left + 18 + text_top = top + image_height + 16 + text_right = right - 18 + subject_bottom = draw_text_block( + draw, + (text_left, text_top), + pick_subject(post), + unicode_font_22, + COLOR_TITLE_LIGHT, + text_right - text_left, + line_gap=4, + max_lines=3, ) - else: - w, h = unicode_font_26.getsize("囗") # type: ignore - padding = (w, h, w, h) - return await convert_img(ImageOps.expand(im, padding, "#f9f6f2")) + time_text = pick_time(post) + if time_text: + draw.text( + (text_left, subject_bottom + 12), + time_text, + font=unicode_font_18, + fill=COLOR_MUTED_LIGHT, + ) + + footer_top = grid_top + rows * card_height + max(0, rows - 1) * GRID_GAP + grid_to_footer_gap + _draw_dark_panel(canvas, (PADDING, footer_top, WIDTH - PADDING, footer_top + footer_card_height)) + draw = ImageDraw.Draw(canvas) + draw.text( + (PADDING + 28, footer_top + footer_card_height // 2), + f"发送 {DNA_PREFIX}公告 + 序号 查看详情,例如:{DNA_PREFIX}公告 1", + font=unicode_font_22, + fill=COLOR_TEXT_LIGHT, + anchor="lm", + ) + + return await convert_img(canvas) -async def ann_detail_card(post_id: Union[int, str], is_check_time=False) -> Union[bytes, str, List[bytes]]: +async def draw_ann_detail_img(post_id: int | str, *, is_check_time: bool = False) -> bytes | str | list[bytes]: post_id = str(post_id) - ann_list = await dna_api.get_ann_list(True) - if not ann_list: - raise Exception("获取游戏公告失败,请检查接口是否正常") - content = [x for x in ann_list if x["postId"] == post_id] - if not content: + posts = await fetch_ann_list(prefer_cache=True) + matched = next((p for p in posts if str(p.get("postId")) == post_id), None) + if matched is None: return "未找到该公告" res = await dna_api.get_post_detail(post_id) - if not res.is_success or not res.data or not isinstance(res.data, dict): + if not res.is_success or not isinstance(res.data, dict): return "未找到该公告" - post_data = res.data - post_detail = post_data["postDetail"] - + detail = res.data.get("postDetail") or {} if is_check_time: - post_time = format_post_time(post_detail["postTime"]) - now_time = int(time.time()) - logger.debug(f"公告id: {post_id}, post_time: {post_time}, now_time: {now_time}, delta: {now_time - post_time}") - if post_time and post_time < now_time - 86400: + post_time = post_time_to_timestamp(detail.get("postTime")) + now = int(time.time()) + logger.debug(f"[DNA公告] {post_id} post_time={post_time} now={now} delta={now - post_time}") + if post_time and post_time < now - 86400: return "该公告已过期" - post_content = post_detail["postContent"] - if not post_content: + blocks = extract_blocks(detail.get("postContent") or []) + if not blocks: return "未找到该公告" - drow_height = 0 - index_start = 0 - index_end = 0 - imgs = [] - for index, temp in enumerate(post_content): - content_type = temp["contentType"] - if content_type == 1: - # 文案 - content = temp["content"] - ( - x_drow_duanluo, - x_drow_note_height, - x_drow_line_height, - x_drow_height, - ) = split_text(content) - if content.strip(): - drow_height += x_drow_height + 30 - elif content_type == 2 and "url" in temp and temp["url"].lower().endswith(("jpg", "png", "jpeg", "webp")): - # 图片 - img = await download_pic_from_url(ANN_CARD_PATH, temp["url"]) - img_height = img.size[1] - if img.width > 1080: - ratio = 1080 / img.width - img_height = int(img.height * ratio) - drow_height += img_height + 40 - elif ( - content_type == 5 - and "contentVideo" in temp - and "coverUrl" in temp["contentVideo"] - and temp["contentVideo"]["coverUrl"].lower().endswith(("jpg", "png", "jpeg", "webp", "webp")) - ): - try: - # 视频图片 - video_temp = temp["contentVideo"] - img = await download_pic_from_url(ANN_CARD_PATH, video_temp["coverUrl"]) - img_height = img.size[1] - if img.width > 1080: - ratio = 1080 / img.width - img_height = int(img.height * ratio) - drow_height += img_height + 40 - except Exception: - pass - - index_end = index + 1 - if drow_height > 5000: - img = await ann_batch_card(post_content[index_start:index_end], drow_height) - index_start = index_end - index_end = index + 1 - drow_height = 0 - imgs.append(img) - - else: - if drow_height > 0 and index_end > index_start: - img = await ann_batch_card(post_content[index_start:index_end], drow_height) - imgs.append(img) - - return imgs - - -def split_text(content: str): - # 常见 HTML 实体与换行的预处理 - content = _normalize_content(content) - # 按规定宽度分组 - max_line_height, total_lines = 0, 0 - allText = [] - for text in content.split("\n"): - duanluo, line_height, line_count = get_duanluo(text) - max_line_height = max(line_height, max_line_height) - total_lines += line_count - allText.append((duanluo, line_count)) - line_height = max_line_height - total_height = total_lines * line_height - drow_height = total_lines * line_height - return allText, total_height, line_height, drow_height - - -def get_duanluo(text: str): - txt = Image.new("RGBA", (600, 800), (255, 255, 255, 0)) - draw = ImageDraw.Draw(txt) - # 所有文字的段落 - duanluo = "" - max_width = 1050 - # 宽度总和 - sum_width = 0 - # 几行 - line_count = 1 - # 行高 - line_height = 0 - for char in text: - left, top, right, bottom = draw.textbbox((0, 0), char, unicode_font_26) - width, height = (right - left, bottom - top) - sum_width += width - if sum_width > max_width: # 超过预设宽度就修改段落 以及当前行数 - line_count += 1 - sum_width = 0 - duanluo += "\n" - duanluo += char - line_height = max(height, line_height) - if not duanluo.endswith("\n"): - duanluo += "\n" - return duanluo, line_height, line_count - - -def _normalize_content(content: str) -> str: - try: - text = html.unescape(content) - except Exception: - text = content - text = re.sub(r"", "\n", text, flags=re.IGNORECASE) - text = text.replace("\u00a0", " ") + subject = detail.get("postTitle") or pick_subject(matched) + time_text = format_post_time(detail.get("postTime") or matched.get("postTime")) + qr_image = await load_qr_code(get_post_url(post_id)) + avatar_image = _load_avatar(120) - return text + pages: list[Image.Image] = [] + page, draw, y = _start_page(0) + qr_bottom = y + page.paste(avatar_image, (PADDING, y), avatar_image) + draw.text((PADDING + 140, y + 32), "二重螺旋官方", font=unicode_font_26, fill=COLOR_TITLE_LIGHT) + draw.text((PADDING + 140, y + 74), "官方资讯发布", font=unicode_font_22, fill=COLOR_MUTED_LIGHT) + y += 146 -def format_post_time(post_time: str) -> int: - try: - full_time = f"{get_datetime().year}-{post_time}" - timestamp = datetime.strptime(full_time, "%Y-%m-%d").timestamp() - return int(timestamp) - except ValueError: - pass + qr_left = WIDTH - PADDING + if qr_image: + qr_size = 164 + qr_box_w = qr_size + 20 + qr_box_h = qr_size + 20 + qr_left = WIDTH - PADDING - qr_box_w + qr_top = PADDING + qr_bottom = qr_top + qr_box_h + qr_panel = Image.new("RGBA", (qr_box_w, qr_box_h), (245, 240, 225, 245)) + page.alpha_composite(qr_panel, (qr_left, qr_top)) + page.paste(qr_image.resize((qr_size, qr_size), Image.Resampling.LANCZOS), (qr_left + 10, qr_top + 10)) - # 17小时前 正则转化为timestamp - try: - match = re.search(r"(\d+)小时前", post_time) - if match: - hours = int(match.group(1)) - return int(time.time()) - hours * 3600 - except Exception: - pass + title_width = (qr_left - 24) - PADDING if qr_image else WIDTH - PADDING * 2 + y = draw_text_block(draw, (PADDING, y), subject, unicode_font_60, COLOR_PALE_GOLDENROD, title_width, line_gap=10) + y += 18 + if time_text: + draw.text((PADDING, y), f"时间:{time_text}", font=unicode_font_22, fill=COLOR_MUTED_LIGHT) + y += 36 - try: - timestamp = datetime.strptime(post_time, "%Y-%m-%d").timestamp() - return int(timestamp) - except ValueError: - pass + y = max(y, qr_bottom + 20) + draw.line((PADDING, y, WIDTH - PADDING, y), fill=COLOR_DIVIDER_DARK, width=2) + y += 26 + + content_width = WIDTH - PADDING * 2 + body_line_height = line_height(unicode_font_28) + + for kind, value in blocks: + if kind == "text": + lines = wrap_text(draw, value, unicode_font_28, content_width) + for line in lines: + if y + body_line_height + PADDING > PAGE_LIMIT: + pages.append(_finalize_page(page, y)) + page, draw, y = _start_page(len(pages)) + fill = COLOR_GOLDENROD if line.startswith((">>>", "▸", "◆", "★")) else COLOR_TEXT_LIGHT + draw.text((PADDING, y), line, font=unicode_font_28, fill=fill) + y += body_line_height + 10 + y += 6 + continue + + image = await _load_detail_image(value, content_width) + image_x = (WIDTH - image.width) // 2 + crop_top = 0 + while crop_top < image.height: + remain = PAGE_LIMIT - y - PADDING + if remain < 200: + pages.append(_finalize_page(page, y)) + page, draw, y = _start_page(len(pages)) + remain = PAGE_LIMIT - y - PADDING + + crop_height = int(min(remain, image.height - crop_top)) + part = image.crop((0, crop_top, image.width, crop_top + crop_height)) + page.paste(part, (image_x, y)) + y += crop_height + 16 + crop_top += crop_height + if crop_top < image.height: + pages.append(_finalize_page(page, y)) + page, draw, y = _start_page(len(pages)) + + pages.append(_finalize_page(page, y)) + + rendered = [await convert_img(img) for img in pages] + return rendered[0] if len(rendered) == 1 else rendered + + +def _start_page(page_index: int) -> tuple[Image.Image, ImageDraw.ImageDraw, int]: + page = get_dna_bg(WIDTH, PAGE_LIMIT + 200).convert("RGBA") + draw = ImageDraw.Draw(page) + y = PADDING + if page_index > 0: + draw.text((PADDING, y), f"继续阅读 · 第 {page_index + 1} 页", font=unicode_font_22, fill=COLOR_MUTED_LIGHT) + y += 44 + return page, draw, y - try: - timestamp = datetime.strptime(post_time, "%Y-%m-%d %H:%M").timestamp() - return int(timestamp) - except ValueError: - pass - return 0 +def _finalize_page(page: Image.Image, bottom: int) -> Image.Image: + return page.crop((0, 0, WIDTH, bottom + PADDING)) diff --git a/DNAUID/dna_ann/texture2d/dna_official_avatar.jpeg b/DNAUID/dna_ann/texture2d/dna_official_avatar.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..d498db1d8807a3ade915d9e53eb0a64911008991 GIT binary patch literal 105779 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", flags=re.IGNORECASE) +_HTML_TAG_RE = re.compile(r"<[^>]+>") +_BLANK_LINE_RE = re.compile(r"\n{3,}") +_RELATIVE_TIME_PARTS = ("小时前", "分钟前", "刚刚") +_TIME_FORMATS = ("%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M", "%Y-%m-%d") +_IMAGE_EXTS = ("jpg", "jpeg", "png", "webp") + + +async def fetch_ann_list(*, prefer_cache: bool = True) -> list[dict[str, Any]]: + return await dna_api.get_ann_list(is_cache=prefer_cache) or [] + + +def build_index_map(posts: Iterable[dict[str, Any]]) -> dict[int, dict[str, Any]]: + return {idx: post for idx, post in enumerate(posts, start=1)} + + +def resolve_index(token: str, index_map: dict[int, dict[str, Any]]) -> str | None: + cleaned = token.strip().replace("#", "") + if not cleaned.isdigit(): + return None + post = index_map.get(int(cleaned)) + return str(post["postId"]) if post else None + + +def get_post_url(post_id: str) -> str: + return POST_DETAIL_URL_TPL.format(post_id=post_id) + + +def format_post_time(raw: Any) -> str: + if raw in (None, ""): + return "" + if isinstance(raw, (int, float)): + return datetime.fromtimestamp(int(raw)).strftime("%Y-%m-%d %H:%M") + + text = str(raw).strip() + if any(part in text for part in _RELATIVE_TIME_PARTS): + return text + + for fmt in _TIME_FORMATS: + try: + return datetime.strptime(text, fmt).strftime("%Y-%m-%d") + except ValueError: + continue + + try: + return datetime.strptime(f"{datetime.now().year}-{text}", "%Y-%m-%d").strftime("%Y-%m-%d") + except ValueError: + return text + + +def post_time_to_timestamp(raw: Any) -> int: + if raw in (None, ""): + return 0 + if isinstance(raw, (int, float)): + return int(raw) + + text = str(raw).strip() + match = re.search(r"(\d+)\s*小时前", text) + if match: + return int(time.time()) - int(match.group(1)) * 3600 + match = re.search(r"(\d+)\s*分钟前", text) + if match: + return int(time.time()) - int(match.group(1)) * 60 + + for fmt in _TIME_FORMATS: + try: + return int(datetime.strptime(text, fmt).timestamp()) + except ValueError: + continue + + try: + return int(datetime.strptime(f"{datetime.now().year}-{text}", "%Y-%m-%d").timestamp()) + except ValueError: + return 0 + + +def normalize_text(text: str) -> str: + raw = html.unescape(text) + raw = _HTML_BREAK_RE.sub("\n", raw) + raw = _HTML_TAG_RE.sub("", raw) + raw = raw.replace("\xa0", " ").replace("\r\n", "\n").replace("\r", "\n") + raw = _BLANK_LINE_RE.sub("\n\n", raw) + return raw.strip() + + +def extract_blocks(post_content: list[dict[str, Any]]) -> list[tuple[str, str]]: + blocks: list[tuple[str, str]] = [] + for item in post_content or []: + kind = item.get("contentType") + if kind == 1: + text = normalize_text(item.get("content") or "") + for line in text.splitlines(): + stripped = line.strip() + if stripped: + blocks.append(("text", stripped)) + elif kind == 2: + url = (item.get("url") or "").strip() + if url.lower().endswith(_IMAGE_EXTS): + blocks.append(("image", url)) + elif kind == 5: + video = item.get("contentVideo") or {} + cover = (video.get("coverUrl") or "").strip() + if cover.lower().endswith(_IMAGE_EXTS): + blocks.append(("image", cover)) + return blocks + + +def pick_preview(post: dict[str, Any]) -> str: + cover = (post.get("postCover") or "").strip() + if cover.lower().endswith(_IMAGE_EXTS): + return cover + video = post.get("videoContent") or {} + if isinstance(video, dict): + video_cover = (video.get("coverUrl") or "").strip() + if video_cover.lower().endswith(_IMAGE_EXTS): + return video_cover + images = post.get("imgContent") or [] + if isinstance(images, list): + for entry in images: + if isinstance(entry, dict): + url = (entry.get("url") or "").strip() + if url.lower().endswith(_IMAGE_EXTS): + return url + return "" + + +def pick_subject(post: dict[str, Any]) -> str: + title = (post.get("postTitle") or "").strip() + if title: + return title + content = post.get("postContent") + if isinstance(content, str): + text = normalize_text(content) + if text: + return text.splitlines()[0][:40] + return f"#{post.get('postId', '')}" + + +def pick_time(post: dict[str, Any]) -> str: + show = (post.get("showTime") or "").strip() + if show: + return show + raw = post.get("postTime") or post.get("createTime") + return format_post_time(raw) if raw else "" From 7ea65c9803f235c252eb8e50a0a72838712f8f1d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 21:45:29 +0000 Subject: [PATCH 2/2] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.14.10 → v0.15.12](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.10...v0.15.12) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bf62c19..6be960f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.14.10 + rev: v0.15.12 hooks: - id: ruff args: [--fix]