添加 Theme 功能

This commit is contained in:
Azide
2023-10-13 23:18:39 +08:00
committed by felinae98
parent 6aaec45d15
commit f202071e9f
57 changed files with 1709 additions and 802 deletions
+87 -69
View File
@@ -1,14 +1,56 @@
from typing import Any
from pathlib import Path
from functools import partial
from httpx import AsyncClient
from nonebot.plugin import require
from bs4 import BeautifulSoup as bs
from pydantic import Field, BaseModel
from ..post import Post
from ..types import Target, RawPost, Category
from .platform import NewMessage, StatusChange
from ..utils.scheduler_config import SchedulerConfig
from .platform import NewMessage, StatusChange, CategoryNotRecognize
class ArkResponseBase(BaseModel):
code: int
msg: str
class BulletinListItem(BaseModel):
cid: str
title: str
category: int
display_time: str = Field(alias="displayTime")
updated_at: int = Field(alias="updatedAt")
sticky: bool
class BulletinList(BaseModel):
list: list[BulletinListItem]
class Config:
extra = "ignore"
class BulletinData(BaseModel):
cid: str
display_type: int = Field(alias="displayType")
title: str
category: int
header: str
content: str
jump_link: str = Field(alias="jumpLink")
banner_image_url: str = Field(alias="bannerImageUrl")
display_time: str = Field(alias="displayTime")
updated_at: int = Field(alias="updatedAt")
class ArkBulletinListResponse(ArkResponseBase):
data: BulletinList
class ArkBulletinResponse(ArkResponseBase):
data: BulletinData
class ArknightsSchedConf(SchedulerConfig):
@@ -26,74 +68,52 @@ class Arknights(NewMessage):
is_common = False
scheduler = ArknightsSchedConf
has_target = False
default_theme = "arknights"
@classmethod
async def get_target_name(cls, client: AsyncClient, target: Target) -> str | None:
return "明日方舟游戏信息"
async def get_sub_list(self, _) -> list[RawPost]:
async def get_sub_list(self, _) -> list[BulletinListItem]:
raw_data = await self.client.get("https://ak-webview.hypergryph.com/api/game/bulletinList?target=IOS")
return raw_data.json()["data"]["list"]
return ArkBulletinListResponse.parse_obj(raw_data.json()).data.list
def get_id(self, post: RawPost) -> Any:
return post["cid"]
def get_id(self, post: BulletinListItem) -> Any:
return post.cid
def get_date(self, _: RawPost) -> Any:
return None
def get_date(self, post: BulletinListItem) -> Any:
return post.updated_at
def get_category(self, _) -> Category:
return Category(1)
async def parse(self, raw_post: RawPost) -> Post:
async def parse(self, raw_post: BulletinListItem) -> Post:
raw_data = await self.client.get(
f"https://ak-webview.hypergryph.com/api/game/bulletin/{self.get_id(post=raw_post)}"
)
raw_data = raw_data.json()["data"]
data = ArkBulletinResponse.parse_obj(raw_data.json()).data
announce_title = raw_data.get("header") if raw_data.get("header") != "" else raw_data.get("title")
text = ""
def title_escape(text: str) -> str:
return text.replace("\n", " - ")
pics = []
if raw_data["bannerImageUrl"]:
pics.append(raw_post["bannerImageUrl"])
elif raw_data["content"]:
require("nonebot_plugin_htmlrender")
from nonebot_plugin_htmlrender import template_to_pic
template_path = str(Path(__file__).parent.parent / "post/templates/ark_announce")
pic_data = await template_to_pic(
template_path=template_path,
template_name="index.html",
templates={
"bannerImageUrl": raw_data["bannerImageUrl"],
"announce_title": announce_title,
"content": raw_data["content"],
},
pages={
"viewport": {"width": 400, "height": 100},
"base_url": f"file://{template_path}",
},
)
# render = Render()
# viewport = {"width": 320, "height": 6400, "deviceScaleFactor": 3}
# pic_data = await render.render(
# announce_url, viewport=viewport, target="div.main"
# )
if pic_data:
pics.append(pic_data)
else:
text = "图片渲染失败"
# gen title, content
if data.header:
# header是title的更详细版本
# header会和content一起出现
title = data.header
else:
raise CategoryNotRecognize("未找到可渲染部分")
# 只有一张图片
title = title_escape(data.title)
return Post(
"arknights",
text=text,
url="",
target_name="明日方舟游戏内公告",
pics=pics,
self,
content=data.content,
title=title,
nickname="明日方舟游戏内公告",
images=[data.banner_image_url] if data.banner_image_url else None,
url=data.jump_link or None,
timestamp=data.updated_at,
compress=True,
override_use_pic=False,
)
@@ -106,6 +126,7 @@ class AkVersion(StatusChange):
is_common = False
scheduler = ArknightsSchedConf
has_target = False
default_theme = "brief"
@classmethod
async def get_target_name(cls, client: AsyncClient, target: Target) -> str | None:
@@ -122,18 +143,15 @@ class AkVersion(StatusChange):
def compare_status(self, _, old_status, new_status):
res = []
ArkUpdatePost = partial(Post, self, "", nickname="明日方舟更新信息")
if old_status.get("preAnnounceType") == 2 and new_status.get("preAnnounceType") == 0:
res.append(
Post("arknights", text="登录界面维护公告上线(大概是开始维护了)", target_name="明日方舟更新信息")
)
res.append(ArkUpdatePost(title="登录界面维护公告上线(大概是开始维护了)"))
elif old_status.get("preAnnounceType") == 0 and new_status.get("preAnnounceType") == 2:
res.append(
Post("arknights", text="登录界面维护公告下线(大概是开服了,冲!)", target_name="明日方舟更新信息")
)
res.append(ArkUpdatePost(title="登录界面维护公告下线(大概是开服了,冲!)"))
if old_status.get("clientVersion") != new_status.get("clientVersion"):
res.append(Post("arknights", text="游戏本体更新(大更新)", target_name="明日方舟更新信息"))
res.append(ArkUpdatePost(title="游戏本体更新(大更新)"))
if old_status.get("resVersion") != new_status.get("resVersion"):
res.append(Post("arknights", text="游戏资源更新(小更新)", target_name="明日方舟更新信息"))
res.append(ArkUpdatePost(title="游戏资源更新(小更新)"))
return res
def get_category(self, _):
@@ -180,13 +198,12 @@ class MonsterSiren(NewMessage):
imgs = [x["src"] for x in soup("img")]
text = f'{raw_post["title"]}\n{soup.text.strip()}'
return Post(
"monster-siren",
text=text,
pics=imgs,
self,
text,
images=imgs,
url=url,
target_name="塞壬唱片新闻",
nickname="塞壬唱片新闻",
compress=True,
override_use_pic=False,
)
@@ -199,6 +216,7 @@ class TerraHistoricusComic(NewMessage):
is_common = False
scheduler = ArknightsSchedConf
has_target = False
default_theme = "brief"
@classmethod
async def get_target_name(cls, client: AsyncClient, target: Target) -> str | None:
@@ -220,11 +238,11 @@ class TerraHistoricusComic(NewMessage):
async def parse(self, raw_post: RawPost) -> Post:
url = f'https://terra-historicus.hypergryph.com/comic/{raw_post["comicCid"]}/episode/{raw_post["episodeCid"]}'
return Post(
"terra-historicus",
text=f'{raw_post["title"]} - {raw_post["episodeShortTitle"]}',
pics=[raw_post["coverUrl"]],
self,
raw_post["subtitle"],
title=f'{raw_post["title"]} - {raw_post["episodeShortTitle"]}',
images=[raw_post["coverUrl"]],
url=url,
target_name="泰拉记事社漫画",
nickname="泰拉记事社漫画",
compress=True,
override_use_pic=False,
)
+16 -11
View File
@@ -193,7 +193,7 @@ class Bilibili(NewMessage):
text += orig_text
else:
raise CategoryNotSupport(post_type)
return Post("bilibili", text=text, url=url, pics=pic, target_name=target_name)
return Post(self, text, url=url, images=pic, nickname=target_name)
class Bilibililive(StatusChange):
@@ -206,6 +206,7 @@ class Bilibililive(StatusChange):
name = "Bilibili直播"
has_target = True
use_batch = True
default_theme = "brief"
@unique
class LiveStatus(Enum):
@@ -334,11 +335,12 @@ class Bilibililive(StatusChange):
title = f"[{self.categories[raw_post.category].rstrip('提醒')}] {raw_post.title}"
target_name = f"{raw_post.uname} {raw_post.area_name}"
return Post(
self.name,
text=title,
self,
"",
title=title,
url=url,
pics=list(pic),
target_name=target_name,
images=list(pic),
nickname=target_name,
compress=True,
)
@@ -353,6 +355,7 @@ class BilibiliBangumi(StatusChange):
name = "Bilibili剧集"
has_target = True
parse_target_promot = "请输入剧集主页"
default_theme = "brief"
_url = "https://api.bilibili.com/pgc/review/user"
@@ -384,7 +387,7 @@ class BilibiliBangumi(StatusChange):
if res_dict["code"] == 0:
return {
"index": res_dict["result"]["media"]["new_ep"]["index"],
"index_show": res_dict["result"]["media"]["new_ep"]["index"],
"index_show": res_dict["result"]["media"]["new_ep"]["index_show"],
"season_id": res_dict["result"]["media"]["season_id"],
}
else:
@@ -412,13 +415,15 @@ class BilibiliBangumi(StatusChange):
url = lastest_episode["link"]
pic: list[str] = [lastest_episode["cover"]]
target_name = detail_dict["result"]["season_title"]
text = lastest_episode["share_copy"]
content = raw_post["index_show"]
title = lastest_episode["share_copy"]
return Post(
self.name,
text=text,
self,
content,
title=title,
url=url,
pics=list(pic),
target_name=target_name,
images=list(pic),
nickname=target_name,
compress=True,
)
+3 -2
View File
@@ -40,6 +40,7 @@ class FF14(NewMessage):
return None
async def parse(self, raw_post: RawPost) -> Post:
text = f'{raw_post["Title"]}\n{raw_post["Summary"]}'
title = raw_post["Title"]
text = raw_post["Summary"]
url = raw_post["Author"]
return Post("ff14", text=text, url=url, target_name="最终幻想XIV官方公告")
return Post(self, text, title=title, url=url, nickname="最终幻想XIV官方公告")
+4 -4
View File
@@ -155,11 +155,11 @@ class McbbsNews(NewMessage):
pics = await self._news_render(post_url, f"#{post_id}")
return Post(
self.name,
text="{}\n\n└由 {} 发表".format(post["title"], post["author"]),
self,
"{}\n\n└由 {} 发表".format(post["title"], post["author"]),
url=post_url,
pics=list(pics),
target_name=post["category"],
images=list(pics),
nickname=post["category"],
)
async def _news_render(self, url: str, selector: str) -> list[bytes]:
+2 -2
View File
@@ -68,7 +68,7 @@ class NcmArtist(NewMessage):
target_name = raw_post["artist"]["name"]
pics = [raw_post["picUrl"]]
url = "https://music.163.com/#/album?id={}".format(raw_post["id"])
return Post("ncm-artist", text=text, url=url, pics=pics, target_name=target_name)
return Post(self, text, url=url, images=pics, nickname=target_name)
class NcmRadio(NewMessage):
@@ -126,4 +126,4 @@ class NcmRadio(NewMessage):
target_name = raw_post["radio"]["name"]
pics = [raw_post["coverUrl"]]
url = "https://music.163.com/#/program/{}".format(raw_post["id"])
return Post("ncm-radio", text=text, url=url, pics=pics, target_name=target_name)
return Post(self, text, url=url, images=pics, nickname=target_name)
+2
View File
@@ -95,6 +95,8 @@ class Platform(metaclass=PlatformABCMeta, base=True):
client: AsyncClient
reverse_category: dict[str, Category]
use_batch: bool = False
# TODO: 限定可使用的theme名称
default_theme: str = "basic"
@classmethod
@abstractmethod
+11 -10
View File
@@ -53,28 +53,29 @@ class Rss(NewMessage):
entry["_target_name"] = feed.feed.title
return feed.entries
def _text_process(self, title: str, desc: str) -> str:
def _text_process(self, title: str, desc: str) -> tuple[str | None, str]:
"""检查标题和描述是否相似,如果相似则标题为None, 否则返回标题和描述"""
similarity = 1.0 if len(title) == 0 or len(desc) == 0 else text_similarity(title, desc)
if similarity > 0.8:
text = title if len(title) > len(desc) else desc
else:
text = title + "\n\n" + desc
return text
return None, title if len(title) > len(desc) else desc
return title, desc
async def parse(self, raw_post: RawPost) -> Post:
title = raw_post.get("title", "")
soup = bs(raw_post.description, "html.parser")
desc = soup.text.strip()
text = self._text_process(title, desc)
title, desc = self._text_process(title, desc)
pics = [x.attrs["src"] for x in soup("img")]
if raw_post.get("media_content"):
for media in raw_post["media_content"]:
if media.get("medium") == "image" and media.get("url"):
pics.append(media.get("url"))
return Post(
"rss",
text=text,
self,
desc,
title=title,
url=raw_post.link,
pics=pics,
target_name=raw_post["_target_name"],
images=pics,
nickname=raw_post["_target_name"],
)
+4 -4
View File
@@ -155,9 +155,9 @@ class Weibo(NewMessage):
detail_url = f"https://weibo.com/{info['user']['id']}/{info['bid']}"
# return parsed_text, detail_url, pic_urls
return Post(
"weibo",
text=parsed_text,
self,
parsed_text,
url=detail_url,
pics=pics,
target_name=info["user"]["screen_name"],
images=pics,
nickname=info["user"]["screen_name"],
)