import importlib import importlib.util import pkgutil from pathlib import Path from typing import Dict, List, Optional, Union from .config import meme_config from .exception import NoSuchMeme from .log import logger from .meme import Meme, MemeArgsType, MemeFunction, MemeParamsType _memes: Dict[str, Meme] = {} def path_to_module_name(path: Path) -> str: rel_path = path.resolve().relative_to(Path.cwd().resolve()) if rel_path.stem == "__init__": return ".".join(rel_path.parts[:-1]) else: return ".".join(rel_path.parts[:-1] + (rel_path.stem,)) def load_meme(module_path: Union[str, Path]): module_name = ( path_to_module_name(module_path) if isinstance(module_path, Path) else module_path ) try: importlib.import_module(module_name) except Exception as e: logger.opt(colors=True, exception=e).error(f"Failed to import {module_path}!") def load_memes(dir_path: Union[str, Path]): if isinstance(dir_path, Path): dir_path = str(dir_path.resolve()) for module_info in pkgutil.iter_modules([dir_path]): if module_info.name.startswith("_"): continue if not ( module_spec := module_info.module_finder.find_spec(module_info.name, None) ): continue if not (module_path := module_spec.origin): continue if not (module_loader := module_spec.loader): continue try: module = importlib.util.module_from_spec(module_spec) module_loader.exec_module(module) except Exception as e: logger.opt(colors=True, exception=e).error( f"Failed to import {module_path}!" ) def add_meme( key: str, function: MemeFunction, *, min_images: int = 0, max_images: int = 0, min_texts: int = 0, max_texts: int = 0, default_texts: List[str] = [], args_type: Optional[MemeArgsType] = None, keywords: List[str] = [], patterns: List[str] = [], ): if key in _memes: logger.warning(f'Meme with key "{key}" already exists!') return if key in meme_config.meme.meme_disabled_list: logger.warning(f'The key "{key}" is in the disabled list!') return meme = Meme( key, function, MemeParamsType( min_images, max_images, min_texts, max_texts, default_texts, args_type ), keywords=keywords, patterns=patterns, ) _memes[key] = meme def get_meme(key: str) -> Meme: if key not in _memes: raise NoSuchMeme(key) return _memes[key] def get_memes() -> List[Meme]: return list(_memes.values()) def get_meme_keys() -> List[str]: return list(_memes.keys())