Skip to content

Commit 70ad6c2

Browse files
committed
fix: 表情包无法注册
1 parent c963f5e commit 70ad6c2

4 files changed

Lines changed: 115 additions & 40 deletions

File tree

dashboard/src/index.css

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -384,12 +384,8 @@
384384
:root[data-dashboard-style='future-retro'],
385385
:root[data-dashboard-style='future-retro'] body {
386386
background-color: var(--retro-paper);
387-
background-image:
388-
var(--retro-paper-texture),
389-
radial-gradient(circle at 12% 18%, rgb(255 248 226 / 0.44) 0 14%, transparent 36%);
390-
background-size:
391-
180px 180px,
392-
100% 100%;
387+
background-image: var(--retro-paper-texture);
388+
background-size: 180px 180px;
393389
color: var(--retro-ink);
394390
font-family: var(--typography-font-family-base);
395391
}
@@ -404,12 +400,8 @@
404400

405401
:root[data-dashboard-style='future-retro'] [data-dashboard-shell='true'] {
406402
background-color: var(--retro-paper);
407-
background-image:
408-
var(--retro-paper-texture),
409-
radial-gradient(circle at 12% 18%, rgb(255 248 226 / 0.44) 0 14%, transparent 36%);
410-
background-size:
411-
180px 180px,
412-
100% 100%;
403+
background-image: var(--retro-paper-texture);
404+
background-size: 180px 180px;
413405
color: var(--retro-ink);
414406
}
415407

@@ -459,12 +451,8 @@
459451
:root[data-dashboard-style='future-retro'] [data-dashboard-header='true'],
460452
:root[data-dashboard-style='future-retro'] [data-dashboard-sidebar='true'] {
461453
background-color: var(--retro-paper) !important;
462-
background-image:
463-
var(--retro-paper-texture),
464-
radial-gradient(circle at 12% 18%, rgb(255 248 226 / 0.32) 0 14%, transparent 36%) !important;
465-
background-size:
466-
180px 180px,
467-
100% 100% !important;
454+
background-image: var(--retro-paper-texture) !important;
455+
background-size: 180px 180px !important;
468456
border-color: var(--retro-line) !important;
469457
border-width: 0 var(--retro-stroke) 0 0 !important;
470458
box-shadow: none !important;

dashboard/src/lib/prompt-generator-api.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,25 @@ import { parseResponse } from '@/lib/api-helpers'
22
import { fetchWithAuth } from '@/lib/fetch-with-auth'
33
import type { ApiResponse } from '@/types/api'
44

5+
const PROMPT_GENERATOR_METHOD_NOT_ALLOWED_MESSAGE =
6+
'生成失败:可能是模型不支持或前后端版本不匹配,请换用文本聊天模型,或刷新并重启 WebUI 后再试。'
7+
8+
function normalizePromptGeneratorError<T>(result: ApiResponse<T>): ApiResponse<T> {
9+
if (result.success) {
10+
return result
11+
}
12+
13+
const normalizedError = result.error.toLowerCase()
14+
if (normalizedError.includes('method not allowed') || normalizedError.includes('405')) {
15+
return {
16+
success: false,
17+
error: PROMPT_GENERATOR_METHOD_NOT_ALLOWED_MESSAGE,
18+
}
19+
}
20+
21+
return result
22+
}
23+
524
export interface PromptGeneratorChatPrompt {
625
platform: string
726
item_id: string
@@ -59,7 +78,7 @@ export async function generatePromptPersona(
5978
method: 'POST',
6079
body: JSON.stringify(payload),
6180
})
62-
return parseResponse<PromptGeneratorResponse>(response)
81+
return normalizePromptGeneratorError(await parseResponse<PromptGeneratorResponse>(response))
6382
}
6483

6584
export interface PromptGeneratorApplyResponse {

src/emoji_system/emoji_manager.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -490,24 +490,37 @@ def load_emojis_from_db(self) -> None:
490490
statement = select(Images)
491491
results = session.exec(statement).all()
492492
self.emojis = []
493+
removed_record_count = 0
493494
for record in results:
494495
if record.image_type != ImageType.EMOJI:
495496
continue
496497
if not record.is_registered:
497498
continue
498-
if record.no_file_flag:
499-
continue
500499
if record.is_banned:
501500
continue
502501
try:
502+
if record.no_file_flag or _resolve_existing_emoji_path(record.full_path) is None:
503+
logger.warning(
504+
f"[数据库] 已注册表情包缺少实际文件,删除破损注册记录: "
505+
f"id={record.id}, path={record.full_path}"
506+
)
507+
session.delete(record)
508+
removed_record_count += 1
509+
continue
503510
emoji = MaiEmoji.from_db_instance(record)
504511
self.emojis.append(emoji)
505512
except Exception as e:
506513
logger.error(
507-
f"[数据库] 加载表情包记录时出错: {e}\n记录ID: {record.id}, 路径: {record.full_path}"
514+
f"[数据库] 加载表情包记录时出错,将删除异常记录: {e}\n"
515+
f"记录ID: {record.id}, 路径: {record.full_path}"
508516
)
517+
session.delete(record)
518+
removed_record_count += 1
509519
self._emoji_num = len(self.emojis)
510-
logger.info(f"[数据库] 成功加载 {self._emoji_num} 个已注册表情包")
520+
logger.info(
521+
f"[数据库] 成功加载 {self._emoji_num} 个已注册表情包,"
522+
f"清理破损注册记录 {removed_record_count} 条"
523+
)
511524
except Exception as e:
512525
logger.critical(f"[数据库] 加载表情包记录时发生不可恢复错误: {e}")
513526
self.emojis = []
@@ -1069,6 +1082,8 @@ async def periodic_emoji_maintenance(self) -> None:
10691082
with get_db_session() as session:
10701083
statement = select(Images).filter_by(image_type=ImageType.EMOJI)
10711084
for record in session.exec(statement).all():
1085+
if not record.is_registered and not record.is_banned:
1086+
continue
10721087
if record_path := _resolve_existing_emoji_path(record.full_path):
10731088
known_paths.add(record_path)
10741089
logger.info("[emoji_maintenance] Scanning data/emoji for new emojis...")

tests/test_emoji_maintenance.py

Lines changed: 70 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
from pathlib import Path
2+
from types import SimpleNamespace
23
from typing import Any
34

45
import asyncio
5-
import sys
6-
76
import pytest
7+
import sys
88

99
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
1010

@@ -37,38 +37,92 @@ def delete(self, record: Any) -> None:
3737
self.deleted.append(record)
3838

3939

40-
def test_integrity_preserves_unknown_files_and_removes_known_orphans(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
40+
def _build_emoji_record(
41+
record_id: int,
42+
full_path: Path | str,
43+
*,
44+
image_hash: str = "emoji_hash",
45+
is_registered: bool = True,
46+
is_banned: bool = False,
47+
no_file_flag: bool = False,
48+
) -> SimpleNamespace:
49+
return SimpleNamespace(
50+
id=record_id,
51+
image_type=emoji_module.ImageType.EMOJI,
52+
image_hash=image_hash,
53+
description="开心",
54+
full_path=str(full_path),
55+
query_count=0,
56+
is_registered=is_registered,
57+
is_banned=is_banned,
58+
no_file_flag=no_file_flag,
59+
register_time=None,
60+
last_used_time=None,
61+
)
62+
63+
64+
def test_load_removes_registered_records_when_file_missing(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
65+
available_file = tmp_path / "available.png"
66+
missing_file = tmp_path / "missing.png"
67+
available_file.write_bytes(b"available")
68+
69+
available_record = _build_emoji_record(1, available_file, image_hash="available_hash")
70+
missing_record = _build_emoji_record(2, missing_file, image_hash="missing_hash")
71+
session = _Session(records=[available_record, missing_record])
72+
monkeypatch.setattr(emoji_module, "get_db_session", lambda: session)
73+
74+
manager = emoji_module.EmojiManager()
75+
try:
76+
manager.load_emojis_from_db()
77+
78+
assert [emoji.file_hash for emoji in manager.emojis] == ["available_hash"]
79+
assert manager._emoji_num == 1
80+
assert session.deleted == [missing_record]
81+
finally:
82+
manager.shutdown()
83+
84+
85+
def test_integrity_preserves_unknown_files_and_removes_missing_registered_records(
86+
monkeypatch: pytest.MonkeyPatch,
87+
tmp_path: Path,
88+
) -> None:
4189
monkeypatch.setattr(emoji_module, "EMOJI_DIR", tmp_path)
4290
new_file = tmp_path / "new.png"
43-
known_orphan = tmp_path / "known.png"
91+
missing_file = tmp_path / "missing.png"
4492
new_file.write_bytes(b"new")
45-
known_orphan.write_bytes(b"known")
4693

47-
session = _Session(records=[])
94+
missing_record = _build_emoji_record(1, missing_file, image_hash="missing_hash")
95+
session = _Session(records=[missing_record])
4896
monkeypatch.setattr(emoji_module, "get_db_session", lambda: session)
4997

5098
manager = emoji_module.EmojiManager()
5199
try:
52-
manager._known_emoji_file_paths = {known_orphan.absolute().resolve()}
53-
54100
manager.check_emoji_file_integrity()
55101

56102
assert new_file.exists()
57-
assert not known_orphan.exists()
103+
assert session.deleted == [missing_record]
104+
assert manager.emojis == []
58105
finally:
59106
manager.shutdown()
60107

61108

62109
@pytest.mark.asyncio
63-
async def test_periodic_maintenance_scans_unknown_files_before_integrity(
110+
async def test_periodic_maintenance_scans_unregistered_records_before_integrity(
64111
monkeypatch: pytest.MonkeyPatch,
65112
tmp_path: Path,
66113
) -> None:
67114
monkeypatch.setattr(emoji_module, "EMOJI_DIR", tmp_path)
68-
known_file = tmp_path / "known.png"
69-
new_file = tmp_path / "new.png"
70-
known_file.write_bytes(b"known")
71-
new_file.write_bytes(b"new")
115+
registered_file = tmp_path / "registered.png"
116+
unregistered_file = tmp_path / "unregistered.png"
117+
registered_file.write_bytes(b"registered")
118+
unregistered_file.write_bytes(b"unregistered")
119+
session = _Session(
120+
records=[
121+
_build_emoji_record(1, registered_file, image_hash="registered_hash"),
122+
_build_emoji_record(2, unregistered_file, image_hash="unregistered_hash", is_registered=False),
123+
]
124+
)
125+
monkeypatch.setattr(emoji_module, "get_db_session", lambda: session)
72126

73127
monkeypatch.setattr(emoji_module.global_config.emoji, "steal_emoji", True)
74128
monkeypatch.setattr(emoji_module.global_config.emoji, "check_interval", 0)
@@ -79,7 +133,6 @@ async def test_periodic_maintenance_scans_unknown_files_before_integrity(
79133
first_check = asyncio.Event()
80134

81135
manager = emoji_module.EmojiManager()
82-
manager._known_emoji_file_paths = {known_file.absolute().resolve()}
83136

84137
async def _register_emoji_by_filename(path: Path | str) -> emoji_module.EmojiRegisterStatus:
85138
emoji_path = Path(path)
@@ -105,6 +158,6 @@ def _check_emoji_file_integrity() -> None:
105158
await task
106159
manager.shutdown()
107160

108-
assert events[0] == ("scan", "new.png")
161+
assert events[0] == ("scan", "unregistered.png")
109162
assert events[1] == ("check", "")
110-
assert ("scan", "known.png") not in events
163+
assert ("scan", "registered.png") not in events

0 commit comments

Comments
 (0)