mirror of
https://github.com/Nezumi-2711/astrbot_plugin_qq_group_daily_analysis.git
synced 2026-09-22 05:31:52 +00:00
220 lines
5.8 KiB
Python
220 lines
5.8 KiB
Python
import asyncio
|
|
import os
|
|
import sys
|
|
import types
|
|
from pathlib import Path
|
|
|
|
# ==========================================
|
|
# 1. Environment Setup
|
|
# ==========================================
|
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
plugin_root = os.path.abspath(os.path.join(current_dir, ".."))
|
|
sys.path.insert(0, plugin_root)
|
|
|
|
# Mock astrbot.api
|
|
astrbot_api = types.ModuleType("astrbot.api")
|
|
|
|
|
|
class MockLogger:
|
|
def info(self, msg, *args, **kwargs):
|
|
print(f"[INFO] {msg}")
|
|
|
|
def error(self, msg, *args, **kwargs):
|
|
print(f"[ERROR] {msg}")
|
|
|
|
def warning(self, msg, *args, **kwargs):
|
|
print(f"[WARN] {msg}")
|
|
|
|
def debug(self, msg, *args, **kwargs):
|
|
pass
|
|
|
|
def log(self, level, msg, *args, **kwargs):
|
|
pass
|
|
|
|
def isEnabledFor(self, level):
|
|
return True
|
|
|
|
|
|
astrbot_api.logger = MockLogger()
|
|
astrbot_api.AstrBotConfig = dict
|
|
sys.modules["astrbot.api"] = astrbot_api
|
|
|
|
# Mock astrbot.core.utils.astrbot_path
|
|
astrbot_core_utils = types.ModuleType("astrbot.core.utils")
|
|
astrbot_path = types.ModuleType("astrbot.core.utils.astrbot_path")
|
|
astrbot_path.get_astrbot_data_path = lambda: Path(".")
|
|
sys.modules["astrbot.core.utils"] = astrbot_core_utils
|
|
sys.modules["astrbot.core.utils.astrbot_path"] = astrbot_path
|
|
|
|
from src.domain.models.data_models import ( # noqa: E402
|
|
ActivityVisualization,
|
|
EmojiStatistics,
|
|
GroupStatistics,
|
|
QualityReview,
|
|
TokenUsage,
|
|
)
|
|
from src.infrastructure.reporting.generators import ReportGenerator # noqa: E402
|
|
|
|
|
|
class MockConfigManager:
|
|
def __init__(self, source: str) -> None:
|
|
self.source = source
|
|
|
|
def get_report_template(self) -> str:
|
|
return "simple"
|
|
|
|
def get_max_topics(self) -> int:
|
|
return 5
|
|
|
|
def get_max_user_titles(self) -> int:
|
|
return 5
|
|
|
|
def get_max_golden_quotes(self) -> int:
|
|
return 5
|
|
|
|
def get_html_output_dir(self) -> str:
|
|
return "data/html"
|
|
|
|
def get_html_filename_format(self) -> str:
|
|
return "report.html"
|
|
|
|
def get_enable_user_card(self) -> bool:
|
|
return True
|
|
|
|
def get_t2i_font_source(self) -> str:
|
|
return self.source
|
|
|
|
def get_t2i_google_fonts_mirror(self) -> str:
|
|
return (
|
|
"https://fonts.loli.net"
|
|
if self.source == "Mainland"
|
|
else "https://fonts.googleapis.com"
|
|
)
|
|
|
|
def get_t2i_gstatic_mirror(self) -> str:
|
|
return (
|
|
"https://gstatic.loli.net"
|
|
if self.source == "Mainland"
|
|
else "https://fonts.gstatic.com"
|
|
)
|
|
|
|
def get_t2i_atri_font_mirror(self) -> str:
|
|
return "https://tc.ciallo.ccwu.cc"
|
|
|
|
def get_profile_display_mode(self) -> str:
|
|
return "mbti"
|
|
|
|
def get_profile_image_opacity(self) -> float:
|
|
return 0.2
|
|
|
|
def get_profile_image_size_mode(self) -> str:
|
|
return "contain"
|
|
|
|
def get_profile_mapping_config(self) -> str:
|
|
return ""
|
|
|
|
def get_t2i_max_concurrent(self) -> int:
|
|
return 4
|
|
|
|
def get_llm_max_concurrent(self) -> int:
|
|
return 2
|
|
|
|
def get_t2i_rendering_strategies(self) -> list:
|
|
return []
|
|
|
|
def get_html_base_url(self) -> str:
|
|
return ""
|
|
|
|
|
|
async def mock_get_user_avatar(user_id: str) -> str:
|
|
return f"https://q4.qlogo.cn/headimg_dl?dst_uin={user_id}&spec=640"
|
|
|
|
|
|
async def verify_rendering(source: str):
|
|
print(f"\n--- Verifying {source} Rendering ---")
|
|
config = MockConfigManager(source)
|
|
data_dir = Path("data/test")
|
|
data_dir.mkdir(parents=True, exist_ok=True)
|
|
generator = ReportGenerator(config, data_dir)
|
|
|
|
# Mock avatar cache
|
|
class MockCache(dict):
|
|
def __getitem__(self, key):
|
|
return self.get(key, "")
|
|
|
|
def set(self, key, value, expire=None):
|
|
self[key] = value
|
|
|
|
generator._avatar_cache = MockCache()
|
|
|
|
stats = GroupStatistics(
|
|
message_count=100,
|
|
total_characters=1000,
|
|
participant_count=5,
|
|
most_active_period="12:00",
|
|
golden_quotes=[],
|
|
emoji_count=0,
|
|
emoji_statistics=EmojiStatistics(0, 0),
|
|
activity_visualization=ActivityVisualization({}),
|
|
token_usage=TokenUsage(0, 0, 0),
|
|
chat_quality_review=QualityReview("Test", "Test", [], "Summary"),
|
|
)
|
|
analysis_result = {
|
|
"statistics": stats,
|
|
"topics": [],
|
|
"user_titles": [],
|
|
"user_analysis": {},
|
|
"chat_quality_review": stats.chat_quality_review,
|
|
"analysis_date": "2026-04-25",
|
|
"group_id": "123",
|
|
"group_name": "Test Group",
|
|
}
|
|
|
|
render_payload = await generator._prepare_render_data(
|
|
analysis_result, avatar_url_getter=mock_get_user_avatar
|
|
)
|
|
html = generator.html_templates.render_template(
|
|
"image_template.html", **render_payload
|
|
)
|
|
|
|
filename = f"test_{source.lower()}.html"
|
|
Path(filename).write_text(html, encoding="utf-8")
|
|
|
|
# Verification
|
|
expected_lang = "vi"
|
|
expected_font = (
|
|
"https://fonts.loli.net"
|
|
if source == "Mainland"
|
|
else "https://fonts.googleapis.com"
|
|
)
|
|
expected_gstatic = (
|
|
"https://gstatic.loli.net"
|
|
if source == "Mainland"
|
|
else "https://fonts.gstatic.com"
|
|
)
|
|
|
|
success = True
|
|
if f'lang="{expected_lang}"' not in html:
|
|
print(f'[FAIL] Expected lang="{expected_lang}" not found.')
|
|
success = False
|
|
if expected_font not in html:
|
|
print(f'[FAIL] Expected font mirror "{expected_font}" not found.')
|
|
success = False
|
|
if expected_gstatic not in html:
|
|
print(f'[FAIL] Expected gstatic mirror "{expected_gstatic}" not found.')
|
|
success = False
|
|
|
|
if success:
|
|
print(f"[PASS] {source} rendering verified. Output saved to {filename}")
|
|
|
|
await generator.close()
|
|
|
|
|
|
async def main():
|
|
await verify_rendering("Mainland")
|
|
await verify_rendering("Overseas")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|