CikeyQi's picture
Upload 964 files (#1)
346533a
raw
history blame
6.57 kB
import asyncio
import copy
from argparse import ArgumentParser
from pathlib import Path
from typing import Any, Dict, List
import filetype
from meme_generator.app import run_server
from meme_generator.config import meme_config
from meme_generator.download import check_resources
from meme_generator.exception import MemeGeneratorException, NoSuchMeme
from meme_generator.log import setup_logger
from meme_generator.manager import get_meme, get_memes
parser = ArgumentParser("meme")
subparsers = parser.add_subparsers(dest="handle")
list_parser = subparsers.add_parser("list", aliases=["ls"], help="查看表情列表")
show_parser = subparsers.add_parser("info", aliases=["show"], help="查看表情详情")
show_parser.add_argument("key", type=str, help="表情名")
preview_parser = subparsers.add_parser("preview", help="生成表情预览")
preview_parser.add_argument("key", type=str, help="表情名")
generate_parser = subparsers.add_parser("generate", aliases=["make"], help="制作表情")
memes_subparsers = generate_parser.add_subparsers(dest="key", help="表情名")
run_parser = subparsers.add_parser("run", aliases=["start"], help="启动 web server")
download_parser = subparsers.add_parser("download", help="下载内置表情图片")
download_parser.add_argument(
"--url", type=str, help="指定资源链接", default=meme_config.resource.resource_url
)
def add_parsers():
for meme in get_memes():
meme_parser = (
copy.deepcopy(meme.params_type.args_type.parser)
if meme.params_type.args_type
else ArgumentParser()
)
meme_parser.add_argument("--images", nargs="+", default=[], help="输入图片路径")
meme_parser.add_argument("--texts", nargs="+", default=[], help="输入文字")
memes_subparsers.add_parser(
meme.key,
parents=[meme_parser],
add_help=False,
prefix_chars=meme_parser.prefix_chars,
)
def list_memes() -> str:
memes = sorted(get_memes(), key=lambda meme: meme.key)
return "\n".join(
f"{i}. {meme.key} ({'/'.join(meme.keywords)})"
for i, meme in enumerate(memes, start=1)
)
def meme_info(key: str) -> str:
try:
meme = get_meme(key)
except NoSuchMeme:
return f'表情 "{key}" 不存在!'
keywords = "、".join([f'"{keyword}"' for keyword in meme.keywords])
patterns = "、".join([f'"{pattern}"' for pattern in meme.patterns])
image_num = f"{meme.params_type.min_images}"
if meme.params_type.max_images > meme.params_type.min_images:
image_num += f" ~ {meme.params_type.max_images}"
text_num = f"{meme.params_type.min_texts}"
if meme.params_type.max_texts > meme.params_type.min_texts:
text_num += f" ~ {meme.params_type.max_texts}"
default_texts = ", ".join([f'"{text}"' for text in meme.params_type.default_texts])
def arg_info(name: str, info: Dict[str, Any]) -> str:
text = (
f' "{name}"\n'
f" 描述:{info.get('description', '')}\n"
f" 类型:`{info.get('type', '')}`\n"
f" 默认值:`{info.get('default', '')}`"
)
if enum := info.get("enum", []):
assert isinstance(enum, list)
text += "\n 可选值:" + "、".join([f'"{e}"' for e in enum])
return text
if args := meme.params_type.args_type:
model = args.model
properties: Dict[str, Dict[str, Any]] = model.schema().get("properties", {})
properties.pop("user_infos")
args_info = "\n" + "\n".join(
[arg_info(name, info) for name, info in properties.items()]
)
else:
args_info = ""
return (
f"表情名:{meme.key}\n"
+ f"关键词:{keywords}\n"
+ (f"正则表达式:{patterns}\n" if patterns else "")
+ "参数:\n"
+ f" 需要图片数目:{image_num}\n"
+ f" 需要文字数目:{text_num}\n"
+ (f" 默认文字:[{default_texts}]\n" if default_texts else "")
+ (f" 其他参数:{args_info}\n" if args_info else "")
)
def generate_meme_preview(key: str) -> str:
try:
meme = get_meme(key)
except NoSuchMeme:
return f'表情 "{key}" 不存在!'
try:
loop = asyncio.new_event_loop()
result = loop.run_until_complete(meme.generate_preview())
content = result.getvalue()
ext = filetype.guess_extension(content)
filename = f"result.{ext}"
with open(filename, "wb") as f:
f.write(content)
return f'表情制作成功!生成的表情文件为 "{filename}"'
except MemeGeneratorException as e:
return str(e)
def generate_meme(
key: str, images: List[str], texts: List[str], args: Dict[str, Any]
) -> str:
try:
meme = get_meme(key)
except NoSuchMeme:
return f'表情 "{key}" 不存在!'
for image in images:
if not Path(image).exists():
return f'图片路径 "{image}" 不存在!'
try:
loop = asyncio.new_event_loop()
result = loop.run_until_complete(meme(images=images, texts=texts, args=args))
content = result.getvalue()
ext = filetype.guess_extension(content)
filename = f"result.{ext}"
with open(filename, "wb") as f:
f.write(content)
return f'表情制作成功!生成的表情文件为 "{filename}"'
except MemeGeneratorException as e:
return str(e)
def main():
setup_logger()
add_parsers()
args = parser.parse_args()
handle = str(args.handle)
if handle in ["list", "ls"]:
print(list_memes())
elif handle in ["info", "show"]:
key = str(args.key)
print(meme_info(key))
elif handle in ["preview"]:
key = str(args.key)
print(generate_meme_preview(key))
elif handle in ["generate", "make"]:
kwargs = vars(args)
kwargs.pop("handle")
key: str = kwargs.pop("key")
images: List[str] = kwargs.pop("images")
texts: List[str] = kwargs.pop("texts")
print(generate_meme(key, images, texts, kwargs))
elif handle in ["run", "start"]:
run_server()
elif handle in ["download"]:
meme_config.resource.resource_url = args.url
loop = asyncio.new_event_loop()
loop.run_until_complete(check_resources())
else:
print(parser.format_help())
if __name__ == "__main__":
main()