| import importlib | |
| import importlib.util | |
| import pkgutil | |
| from pathlib import Path | |
| from typing import 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()) | |