mirror of
https://github.com/MemeMeow-Studio/MemeMeow.git
synced 2026-10-17 04:41:01 +08:00
220 lines
9.3 KiB
Python
220 lines
9.3 KiB
Python
import os
|
|
import json
|
|
import pickle
|
|
import shutil
|
|
from typing import Dict, List, Optional, Tuple
|
|
from PIL import Image, ImageDraw
|
|
import numpy as np
|
|
|
|
from config.settings import Config, ResourcePackConfig
|
|
from services.utils import verify_folder, get_file_hash
|
|
from base import *
|
|
|
|
class ResourcePackManager:
|
|
"""资源包管理器,负责加载、解析和缓存资源包"""
|
|
|
|
def __init__(self):
|
|
"""初始化资源包管理器"""
|
|
self.resource_packs_dir = os.path.join(Config().base_dir, Config().paths.resource_packs_dir)
|
|
verify_folder(self.resource_packs_dir)
|
|
|
|
# 存储所有可用的资源包信息
|
|
self.available_packs: Dict[str, Dict] = {}
|
|
# 存储已启用的资源包信息
|
|
self.enabled_packs: Dict[str, Dict] = {}
|
|
|
|
# 加载所有资源包
|
|
self._load_resource_packs()
|
|
|
|
def _load_resource_packs(self) -> None:
|
|
"""加载所有资源包信息"""
|
|
# 清空当前资源包信息
|
|
self.available_packs = {}
|
|
|
|
# 遍历resource_packs目录,加载所有资源包
|
|
if os.path.exists(self.resource_packs_dir):
|
|
for item in os.listdir(self.resource_packs_dir):
|
|
pack_dir = os.path.join(self.resource_packs_dir, item)
|
|
if os.path.isdir(pack_dir):
|
|
manifest_path = os.path.join(pack_dir, "manifest.json")
|
|
if os.path.exists(manifest_path):
|
|
try:
|
|
with open(manifest_path, "r", encoding="utf-8") as f:
|
|
manifest = json.load(f)
|
|
|
|
# 检查资源包是否有效
|
|
if not self._validate_resource_pack(pack_dir, manifest):
|
|
continue
|
|
|
|
resource_config = Config().resource_packs.get(f'pack_{item}', ResourcePackConfig())
|
|
|
|
|
|
# 获取封面图片路径
|
|
cover_path = None
|
|
if manifest.get("cover") and manifest["cover"].get("filename"):
|
|
cover_file = manifest["cover"]["filename"]
|
|
cover_path = os.path.join(pack_dir, cover_file)
|
|
if not os.path.exists(cover_path):
|
|
cover_path = None
|
|
|
|
# 构建资源包信息
|
|
pack_id = f"pack_{item}"
|
|
|
|
self.available_packs[pack_id] = {
|
|
"name": manifest.get("name", item),
|
|
"version": manifest.get("version", "1.0.0"),
|
|
"author": manifest.get("author", "Unknown"),
|
|
"description": manifest.get("description", ""),
|
|
"path": pack_dir,
|
|
"type": "vv", # 默认类型
|
|
"cache_file": self.get_pack_cache_file(pack_id),
|
|
"enabled": resource_config.enabled, # 默认不启用
|
|
"is_default": False,
|
|
"cover": cover_path,
|
|
"manifest": manifest,
|
|
"pack_dir": pack_dir,
|
|
"url": manifest.get("url", ""),
|
|
}
|
|
if manifest.get('regex') is not None:
|
|
self.available_packs[pack_id]['regex'] = manifest.get('regex')
|
|
if resource_config.enabled:
|
|
self.enabled_packs[pack_id] = self.available_packs[pack_id]
|
|
except Exception as e:
|
|
logger.error(f"加载资源包 {item} 失败: {e}")
|
|
|
|
def _validate_resource_pack(self, pack_dir: str, manifest: Dict) -> bool:
|
|
"""验证资源包是否有效"""
|
|
# 检查必要的字段
|
|
if not manifest.get("name") or not manifest.get("version") or not manifest.get("author"):
|
|
print(f"资源包 {pack_dir} 缺少必要的字段")
|
|
return False
|
|
|
|
# 检查images目录是否存在
|
|
# images_dir = os.path.join(pack_dir, "images")
|
|
# if not os.path.exists(images_dir) or not os.path.isdir(images_dir):
|
|
# print(f"资源包 {pack_dir} 缺少images目录")
|
|
# return False
|
|
#
|
|
# # 检查images目录是否有图片
|
|
# has_images = False
|
|
# for root, _, files in os.walk(images_dir):
|
|
# for file in files:
|
|
# if file.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')):
|
|
# has_images = True
|
|
# break
|
|
# if has_images:
|
|
# break
|
|
#
|
|
# if not has_images:
|
|
# print(f"资源包 {pack_dir} 的images目录中没有图片")
|
|
# return False
|
|
|
|
return True
|
|
|
|
def get_available_packs(self) -> Dict[str, Dict]:
|
|
"""获取所有可用的资源包"""
|
|
return self.available_packs
|
|
|
|
def get_enabled_packs(self) -> Dict[str, Dict]:
|
|
"""获取所有已启用的资源包"""
|
|
return self.enabled_packs
|
|
|
|
def enable_pack(self, pack_id: str) -> bool:
|
|
"""启用指定的资源包"""
|
|
if pack_id in self.available_packs and not self.available_packs[pack_id]["enabled"]:
|
|
self.available_packs[pack_id]["enabled"] = True
|
|
self.enabled_packs[pack_id] = self.available_packs[pack_id]
|
|
|
|
# 更新配置文件
|
|
with Config() as config:
|
|
# if "resource_packs" not in config.__dict__:
|
|
# config.resource_packs = {}
|
|
if pack_id not in config.resource_packs:
|
|
config.resource_packs[pack_id] = ResourcePackConfig(enabled=True)
|
|
else:
|
|
config.resource_packs[pack_id].enabled = True
|
|
|
|
return True
|
|
return False
|
|
|
|
def disable_pack(self, pack_id: str) -> bool:
|
|
"""禁用指定的资源包"""
|
|
if pack_id in self.available_packs and self.available_packs[pack_id]["enabled"]:
|
|
self.available_packs[pack_id]["enabled"] = False
|
|
if pack_id in self.enabled_packs:
|
|
del self.enabled_packs[pack_id]
|
|
|
|
# 更新配置文件
|
|
with Config() as config:
|
|
if "resource_packs" in config.__dict__ and pack_id in config.resource_packs:
|
|
config.resource_packs[pack_id].enabled = False
|
|
|
|
return True
|
|
return False
|
|
|
|
def get_pack_cover(self, pack_id: str, size: Tuple[int, int] = (512, 512)) -> Optional[str]:
|
|
"""获取资源包的封面图片路径,如果没有封面则生成一个默认封面"""
|
|
if pack_id not in self.available_packs:
|
|
return None
|
|
|
|
pack_info = self.available_packs[pack_id]
|
|
|
|
# 如果有封面,直接返回
|
|
if pack_info.get("cover") and os.path.exists(pack_info["cover"]):
|
|
return pack_info["cover"]
|
|
|
|
# 生成默认封面
|
|
cover_cache_dir = Config().get_abs_cover_cache_file()
|
|
verify_folder(cover_cache_dir)
|
|
|
|
default_cover_path = os.path.join(cover_cache_dir, f"{pack_id}_cover.png")
|
|
|
|
# 如果已经生成过默认封面,直接返回
|
|
if os.path.exists(default_cover_path):
|
|
return default_cover_path
|
|
|
|
# 生成一个灰色的封面,并添加资源包名称
|
|
img = Image.new('RGB', size, color=(200, 200, 200))
|
|
draw = ImageDraw.Draw(img)
|
|
|
|
# 添加资源包名称
|
|
pack_name = pack_info.get("name", "未命名资源包")
|
|
text_width = draw.textlength(pack_name, font=None)
|
|
text_position = ((size[0] - text_width) / 2, size[1] / 2)
|
|
draw.text(text_position, pack_name, fill=(0, 0, 0))
|
|
|
|
# 保存封面
|
|
img.save(default_cover_path)
|
|
|
|
return default_cover_path
|
|
|
|
def get_cache_files(self) -> Dict[str, str]:
|
|
"""获取所有启用的资源包的缓存文件路径"""
|
|
cache_files = {}
|
|
for pack_id, pack_info in self.enabled_packs.items():
|
|
cache_file = pack_info["cache_file"]
|
|
cache_files[pack_id] = cache_file
|
|
return cache_files
|
|
|
|
def is_pack_cache_generated(self, pack_id: str, model_name) -> bool:
|
|
"""检查指定资源包的缓存是否已生成"""
|
|
if pack_id not in self.available_packs:
|
|
print(f"资源包 {pack_id} 不存在")
|
|
return False
|
|
|
|
pack_info = self.available_packs[pack_id]
|
|
cache_file = pack_info["cache_file"]
|
|
|
|
# 打印调试信息
|
|
exists = os.path.exists(cache_file)
|
|
print(f"检查缓存文件: {cache_file}, 模型: {model_name}, 存在: {exists}")
|
|
|
|
return exists
|
|
|
|
def get_pack_cache_file(self, pack_id: str, model_name: Optional[str] = None) -> Optional[str]:
|
|
"""获取指定资源包的缓存文件路径"""
|
|
fp = os.path.join(Config().pack_embedding_cache_folder_path, f"{pack_id}.pkl")
|
|
verify_folder(fp)
|
|
return fp
|
|
|
|
RESOURCE_PACK_MANAGER = ResourcePackManager() |