@sophiacyl/dsh-plugin-waves 0.0.0-stage → 0.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/DSH-GO-VERIFICATION.md +57 -0
  2. package/ICON.png +0 -0
  3. package/LICENSE +674 -0
  4. package/README.md +251 -2
  5. package/cordis.patch.yml +8 -0
  6. package/install.ps1 +0 -0
  7. package/install.sh +209 -0
  8. package/lib/client.js +1511 -0
  9. package/lib/host/aliashint.js +70 -0
  10. package/lib/host/attachments.js +25 -0
  11. package/lib/host/command.js +34 -0
  12. package/lib/host/consts.js +16 -0
  13. package/lib/host/dataguide.js +35 -0
  14. package/lib/host/imagebridge.js +41 -0
  15. package/lib/host/native-result.js +91 -0
  16. package/lib/host/native.js +191 -0
  17. package/lib/host/proxy.js +59 -0
  18. package/lib/host/results.js +67 -0
  19. package/lib/host/service.js +263 -0
  20. package/lib/host/tool.js +185 -0
  21. package/lib/host/troubleshoot.js +31 -0
  22. package/lib/host/worldbook.js +80 -0
  23. package/lib/index.js +74 -0
  24. package/locale/en.json +6 -0
  25. package/locale/zh.json +6 -0
  26. package/package.json +136 -4
  27. package/service/ICON.png +0 -0
  28. package/service/ai/AI_DATA.md +221 -0
  29. package/service/knowledge/additional/manual.jsonl +5 -0
  30. package/service/knowledge/wiki/baike.jsonl +1231 -0
  31. package/service/knowledge/wiki/chengjiu.jsonl +36 -0
  32. package/service/knowledge/wiki/gonglve.jsonl +383 -0
  33. package/service/knowledge/wiki/huodong.jsonl +427 -0
  34. package/service/knowledge/wiki/renwu.jsonl +412 -0
  35. package/service/knowledge/wiki/tujian.jsonl +2889 -0
  36. package/service/knowledge/wiki/zixun.jsonl +47 -0
  37. package/service/plugins/__init__.py +0 -0
  38. package/service/pyproject.toml +40 -0
  39. package/service/rover/__init__.py +0 -0
  40. package/service/rover/ai_core/__init__.py +0 -0
  41. package/service/rover/ai_core/models.py +50 -0
  42. package/service/rover/ai_core/rag/__init__.py +5 -0
  43. package/service/rover/ai_core/rag/knowledge.py +23 -0
  44. package/service/rover/ai_core/register.py +86 -0
  45. package/service/rover/ai_core/resource.py +6 -0
  46. package/service/rover/ai_core/skills/__init__.py +0 -0
  47. package/service/rover/ai_core/skills/operations.py +8 -0
  48. package/service/rover/api.py +720 -0
  49. package/service/rover/api_render.py +161 -0
  50. package/service/rover/app_life.py +154 -0
  51. package/service/rover/aps.py +47 -0
  52. package/service/rover/avatar.py +85 -0
  53. package/service/rover/bot.py +133 -0
  54. package/service/rover/builtin.py +152 -0
  55. package/service/rover/cards/__init__.py +26 -0
  56. package/service/rover/cards/_shared.py +129 -0
  57. package/service/rover/cards/char_list.py +258 -0
  58. package/service/rover/cards/char_panel.py +1353 -0
  59. package/service/rover/cards/echo_list.py +206 -0
  60. package/service/rover/cards/matrix_roles.py +25 -0
  61. package/service/rover/cards/rank_boards.py +714 -0
  62. package/service/rover/cards/rank_total.py +664 -0
  63. package/service/rover/compat.py +215 -0
  64. package/service/rover/config.py +163 -0
  65. package/service/rover/custom_panel.py +220 -0
  66. package/service/rover/data_store.py +31 -0
  67. package/service/rover/gss.py +19 -0
  68. package/service/rover/handler.py +191 -0
  69. package/service/rover/help/__init__.py +0 -0
  70. package/service/rover/help/draw_new_plugin_help.py +332 -0
  71. package/service/rover/help/model.py +16 -0
  72. package/service/rover/help/utils.py +7 -0
  73. package/service/rover/hooks.py +420 -0
  74. package/service/rover/html_actions.py +236 -0
  75. package/service/rover/i18n.py +19 -0
  76. package/service/rover/knowledge.py +235 -0
  77. package/service/rover/logger.py +102 -0
  78. package/service/rover/main.py +33 -0
  79. package/service/rover/media.py +222 -0
  80. package/service/rover/message_models.py +23 -0
  81. package/service/rover/models.py +92 -0
  82. package/service/rover/native_media.py +64 -0
  83. package/service/rover/ocr.py +79 -0
  84. package/service/rover/pool.py +43 -0
  85. package/service/rover/restart.py +36 -0
  86. package/service/rover/segment.py +143 -0
  87. package/service/rover/server.py +131 -0
  88. package/service/rover/status/__init__.py +0 -0
  89. package/service/rover/status/models.py +10 -0
  90. package/service/rover/status/plugin_status.py +17 -0
  91. package/service/rover/subscribe.py +148 -0
  92. package/service/rover/sv.py +403 -0
  93. package/service/rover/templates/char_list.html +182 -0
  94. package/service/rover/templates/char_panel.html +465 -0
  95. package/service/rover/templates/echo_list.html +221 -0
  96. package/service/rover/templates/rank_all_total.html +193 -0
  97. package/service/rover/templates/rank_board.html +107 -0
  98. package/service/rover/templates/rank_level_total.html +57 -0
  99. package/service/rover/templates/rank_matrix_total.html +66 -0
  100. package/service/rover/templates/rank_phantom_total.html +180 -0
  101. package/service/rover/templates/rank_slash_total.html +38 -0
  102. package/service/rover/trigger.py +98 -0
  103. package/service/rover/utils/__init__.py +0 -0
  104. package/service/rover/utils/boardcast/__init__.py +0 -0
  105. package/service/rover/utils/boardcast/models.py +15 -0
  106. package/service/rover/utils/cookie_manager/__init__.py +0 -0
  107. package/service/rover/utils/cookie_manager/qrlogin.py +24 -0
  108. package/service/rover/utils/database/__init__.py +0 -0
  109. package/service/rover/utils/database/base_models.py +1771 -0
  110. package/service/rover/utils/database/models.py +80 -0
  111. package/service/rover/utils/database/startup.py +60 -0
  112. package/service/rover/utils/default_bg/bg.jpg +0 -0
  113. package/service/rover/utils/download_resource/__init__.py +0 -0
  114. package/service/rover/utils/download_resource/download_core.py +164 -0
  115. package/service/rover/utils/download_resource/download_file.py +46 -0
  116. package/service/rover/utils/fonts/__init__.py +0 -0
  117. package/service/rover/utils/fonts/fonts.py +33 -0
  118. package/service/rover/utils/image/__init__.py +0 -0
  119. package/service/rover/utils/image/convert.py +51 -0
  120. package/service/rover/utils/image/image_tools.py +30 -0
  121. package/service/rover/utils/image/utils.py +70 -0
  122. package/service/rover/utils/plugins_config/__init__.py +0 -0
  123. package/service/rover/utils/plugins_config/gs_config.py +506 -0
  124. package/service/rover/utils/plugins_config/models.py +182 -0
  125. package/service/rover/web_app.py +3 -0
  126. package/service/rover/webconsole/__init__.py +0 -0
  127. package/service/rover/webconsole/mount_app.py +26 -0
  128. package/service/tools/migrate.py +351 -0
  129. package/service/tools/regression.py +87 -0
  130. package/service/tools/smoke.py +63 -0
  131. package/service/tools/update_plugins.py +212 -0
  132. package/service/tools/verify_actions.py +104 -0
  133. package/service/tools/verify_card.py +82 -0
  134. package/service/tools/wwdata.py +665 -0
  135. package/tests/compat.test.js +181 -0
  136. package/tests/imagebridge.test.js +58 -0
  137. package/tests/media.test.js +68 -0
  138. package/tests/native.test.js +127 -0
  139. package/tests/runtime.test.js +69 -0
  140. package/tests/service.test.js +48 -0
@@ -0,0 +1,206 @@
1
+ """声骸仓库卡片: 原 PIL 版声骸列表改为 HTML 输出, 版式照搬 350x600 卡格与 4 列网格。"""
2
+
3
+ import asyncio
4
+ import importlib
5
+ from pathlib import Path
6
+ from typing import Any, Dict, List, Tuple
7
+
8
+ from rover.logger import logger
9
+
10
+ TEMPLATE = "echo_list.html"
11
+ TEMPLATES_DIR = Path(__file__).resolve().parents[1] / "templates"
12
+
13
+ # 卡格几何, 与 PIL 版逐项对齐
14
+ CARD_W, CARD_H = 350, 600
15
+ COL_PITCH, ROW_PITCH = 390, 570
16
+ COLUMNS = 4
17
+ PROP_TOP, PROP_PITCH = 217, 55
18
+
19
+ _env = None
20
+
21
+
22
+ def _template():
23
+ global _env
24
+ if _env is None:
25
+ from jinja2 import Environment, FileSystemLoader, select_autoescape
26
+
27
+ _env = Environment(
28
+ loader=FileSystemLoader(str(TEMPLATES_DIR)),
29
+ autoescape=select_autoescape(["html"]),
30
+ )
31
+ return _env.get_template(TEMPLATE)
32
+
33
+
34
+ def _css_color(value: Any) -> str:
35
+ """词条配色在插件里是颜色名或 RGB 元组。"""
36
+ if isinstance(value, (tuple, list)):
37
+ parts = list(value)[:3]
38
+ return "rgb({}, {}, {})".format(*parts)
39
+ return str(value)
40
+
41
+
42
+ def _font_css_url(render_utils) -> str:
43
+ css = render_utils._FONTS_DIR / render_utils._FONT_CSS_NAME
44
+ if css.exists():
45
+ return f"{render_utils._get_local_base_url()}/waves/fonts/{render_utils._FONT_CSS_NAME}"
46
+ return render_utils._get_font_css_url()
47
+
48
+
49
+ def _build_context(module, image, render_utils, account_info, avatar, echo_assets, page, max_page, user_pref) -> Dict:
50
+ texture = module.TEXT_PATH
51
+ # 同一素材在 20 张卡里反复出现, 统一收进 CSS 类, 元素只带类名
52
+ assets: List[str] = []
53
+ classes: Dict[Tuple, str] = {}
54
+
55
+ def asset_class(key: Tuple, make) -> str:
56
+ if key not in classes:
57
+ assets.append(make())
58
+ classes[key] = f"a{len(assets) - 1}"
59
+ return classes[key]
60
+
61
+ echoes: List[Dict] = []
62
+ for index, asset in enumerate(echo_assets):
63
+ echo = asset["echo"]
64
+ phantom = echo.phantom
65
+ icon = asset["phantom_icon"]
66
+
67
+ title = f"sh_title_{echo.score_bg}.png"
68
+ if not (texture / title).exists():
69
+ title = "sh_title_c.png"
70
+
71
+ props = []
72
+ for i, prop in enumerate(echo.props):
73
+ prop_img = asset["prop_imgs"][i]
74
+ props.append(
75
+ {
76
+ "icon_class": asset_class(
77
+ ("prop", prop.attributeName),
78
+ lambda img=prop_img: image.pil_to_b64(img.resize((40, 40)), quality=80),
79
+ ),
80
+ "name": prop.attributeName[:6],
81
+ "value": prop.attributeValue,
82
+ "name_color": _css_color(echo.name_colors[i]),
83
+ "value_color": _css_color(echo.num_colors[i]),
84
+ }
85
+ )
86
+
87
+ echoes.append(
88
+ {
89
+ "left": COL_PITCH * (index % COLUMNS),
90
+ "top": ROW_PITCH * (index // COLUMNS),
91
+ "title_class": asset_class(("title", title), lambda: image.img_to_b64(texture / title)),
92
+ "role_class": asset_class(
93
+ ("role", echo.roleId),
94
+ lambda: image.pil_to_b64(asset["role_avatar"], quality=80),
95
+ ),
96
+ "icon_class": asset_class(
97
+ ("phantom", phantom.phantomProp.phantomId),
98
+ lambda: image.pil_to_b64(icon.resize((100, 100)), quality=80),
99
+ ),
100
+ "fetter_class": asset_class(
101
+ ("fetter", phantom.fetterDetail.name),
102
+ lambda: image.pil_to_b64(asset["fetter_icon"].resize((50, 50)), quality=80),
103
+ ),
104
+ # 角标原本贴在整图 (205, 0) 处, 缩到 100x100 后按比例给百分比
105
+ "fetter_left": 205 / max(icon.width, 1) * 100,
106
+ "fetter_size": 50 / max(icon.width, 1) * 100,
107
+ "name": phantom.phantomProp.name.replace("·", " ").replace("(", " ").replace(")", ""),
108
+ "level": phantom.level,
109
+ "score": echo.score,
110
+ "cost": phantom.cost,
111
+ "props": props,
112
+ "command": f"{module.PREFIX}{echo.roleName}面板" if echo.roleName else "",
113
+ }
114
+ )
115
+
116
+ rows = (len(echoes) + COLUMNS - 1) // COLUMNS
117
+
118
+ return {
119
+ "font_css_url": _font_css_url(render_utils),
120
+ "bg_url": image.pil_to_b64(image.get_waves_bg(bg="bg3", crop=False), quality=75),
121
+ "footer_url": render_utils.get_footer_b64(footer_type="white") or "",
122
+ "sh_bg_url": image.img_to_b64(texture / "sh_bg.png"),
123
+ "promote_url": image.img_to_b64(texture / "promote_icon.png"),
124
+ "avatar_url": image.pil_to_b64(avatar, quality=80),
125
+ "assets": assets,
126
+ "user_name": account_info.name[:10],
127
+ "user_id": module.hide_uid(account_info.id, user_pref=user_pref),
128
+ "level": account_info.level,
129
+ "world_level": account_info.worldLevel,
130
+ "show_stats": account_info.is_full,
131
+ "page_text": f"第{page}/{max_page}页" if page > 1 else "",
132
+ "card_w": CARD_W,
133
+ "card_h": CARD_H,
134
+ "prop_top": PROP_TOP,
135
+ "prop_gap": PROP_PITCH - 40,
136
+ "grid_w": COL_PITCH * (COLUMNS - 1) + CARD_W,
137
+ "grid_h": ROW_PITCH * max(rows - 1, 0) + CARD_H,
138
+ "echoes": echoes,
139
+ }
140
+
141
+
142
+ def _patch_echo_list(module) -> None:
143
+ from rover.html_actions import annotate_html
144
+ from rover.media import HtmlBytes
145
+
146
+ original = module._compose_echo_list
147
+ package = module.__name__.rsplit(".", 2)[0]
148
+ image = importlib.import_module(f"{package}.utils.image")
149
+ render_utils = importlib.import_module(f"{package}.utils.render_utils")
150
+
151
+ async def compose(
152
+ account_info,
153
+ avatar,
154
+ avatar_ring,
155
+ echo_assets,
156
+ page,
157
+ max_page,
158
+ user_pref,
159
+ title_bar_logo,
160
+ ):
161
+ try:
162
+ context = await asyncio.to_thread(
163
+ _build_context,
164
+ module,
165
+ image,
166
+ render_utils,
167
+ account_info,
168
+ avatar,
169
+ echo_assets,
170
+ page,
171
+ max_page,
172
+ user_pref,
173
+ )
174
+ html = annotate_html(_template().render(**context), TEMPLATE, context)
175
+ logger.info(f"[声骸仓库] {len(html) / 1024 / 1024:.2f}MB")
176
+ return HtmlBytes(html, TEMPLATE)
177
+ except Exception as e:
178
+ logger.error(f"[声骸仓库] HTML 渲染失败, 回退原图: {e}")
179
+ return await original(
180
+ account_info,
181
+ avatar,
182
+ avatar_ring,
183
+ echo_assets,
184
+ page,
185
+ max_page,
186
+ user_pref,
187
+ title_bar_logo,
188
+ )
189
+
190
+ module._compose_echo_list = compose
191
+
192
+ original_convert = module.convert_img
193
+
194
+ async def convert_img(img, *args, **kwargs):
195
+ if isinstance(img, HtmlBytes):
196
+ return img
197
+ return await original_convert(img, *args, **kwargs)
198
+
199
+ module.convert_img = convert_img
200
+
201
+
202
+ PATCHES = {
203
+ "XutheringWavesUID": {
204
+ "wutheringwaves_echo.draw_echo_list": _patch_echo_list,
205
+ },
206
+ }
@@ -0,0 +1,25 @@
1
+ """矩阵卡的角色 id。
2
+
3
+ 上游给模板的角色项只有图标和命座, 没有 id, 点击注解就无从下手。
4
+ 构图时每个真实角色都会取一次流派徽标, 借这一步把 id 顺手记下来。
5
+ """
6
+
7
+ from rover.logger import logger
8
+
9
+
10
+ def _patch(m) -> None:
11
+ original = m.get_skill_branch_emblem_b64
12
+
13
+ def get_skill_branch_emblem_b64(role_id, branch_index):
14
+ from rover.html_actions import record_role_id
15
+
16
+ try:
17
+ record_role_id(role_id)
18
+ except Exception as e:
19
+ logger.debug(f"[鸣潮·交互] 矩阵角色 id 记录失败: {e}")
20
+ return original(role_id, branch_index)
21
+
22
+ m.get_skill_branch_emblem_b64 = get_skill_branch_emblem_b64
23
+
24
+
25
+ PATCHES = {"XutheringWavesUID": {"wutheringwaves_abyss.draw_matrix_card": _patch}}