diff --git a/.gitmodules b/.gitmodules index 7ff0725..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "api"] - path = mc_status_api - url = https://github.com/Murasame-Dev/McStatus-API.git diff --git a/create_image.py b/create_image.py index a1602a1..f58b152 100644 --- a/create_image.py +++ b/create_image.py @@ -1,8 +1,9 @@ from PIL import Image, ImageDraw, ImageFont, ImageFilter from io import BytesIO -from motd_formatter import foramt_motd from PIL.ImageColor import getrgb +from .motd_formatter import foramt_motd + def create_background(input: bytes, width: int, height: int): background = Image.open(BytesIO(input)) w1, h1, w2, h2 = background.getbbox() @@ -30,9 +31,8 @@ def draw_text_with_shadow(image: Image.Image, text: str, posx: int, posy: int, - font_size: int): + font): draw = ImageDraw.Draw(image) - font = ImageFont.truetype("./MiSans-Bold.ttf", font_size) draw.text((posx + 2, posy + 2), text, font=font, fill='black') draw.text((posx, posy), text, font=font, fill='white') @@ -40,9 +40,8 @@ def draw_motd_text_with_shadow(image: Image.Image, text: str, posx: int, posy: int, - font_size: int): + font): draw = ImageDraw.Draw(image) - font = ImageFont.truetype("./MiSans-Bold.ttf", font_size) w1, _, w2, _ = draw.textbbox((0, 0), text.strip(), font=font) weight = w2 - w1 motd_list = foramt_motd(text.strip(), weight) @@ -55,9 +54,19 @@ def draw_motd_text_with_shadow(image: Image.Image, def create_image(background: bytes, icon: str | None, text_list: list[str], - motd_list: list[str]): + motd_list: list[str], + font_url: str | None, + image_size: list[int] = [0, 0]): # 图片尺寸 - width, height = 1200, 400 + if image_size == [0, 0] or image_size == []: + width = 1200 + height = 400 + elif len(image_size) == 2: + width = image_size[0] + height = image_size[1] + else: + assert ValueError("image_size is invalid") + if (len(text_list) + len(motd_list)) * 20 + 20 > height: height = (len(text_list) + len(motd_list)) * 20 + 20 else: @@ -73,7 +82,6 @@ def create_image(background: bytes, # 添加半透明蒙版层以增强文字可读性 overlay = Image.new('RGBA', (width, height), (0, 0, 0, 80)) # 半透明黑色蒙版 image.paste(overlay, (0, 0), overlay) - if width // 2 > height: small_size = int(height * 0.8) else: @@ -86,6 +94,12 @@ def create_image(background: bytes, image.paste(small_image, (30, height // 2 - small_size // 2)) + # 设置字体 + if font_url == None: + font = ImageFont.load_default(font_size) + else: + font = ImageFont.truetype(font_url, font_size) + text_list_size = len(text_list) motd_list_size = len(motd_list) start_posy = height / 2 - (text_list_size + motd_list_size) / 2 * font_size * 1.2 @@ -94,12 +108,12 @@ def create_image(background: bytes, motd_list[i], width // 2.5, start_posy + font_size * 1.2 * i, - int(font_size * 0.8)) + font) for i in range(text_list_size): draw_text_with_shadow(image, text_list[i], width // 2.5, start_posy + font_size * 1.2 * (i + motd_list_size), - font_size) + font) return image diff --git a/get_icon.py b/get_icon.py new file mode 100644 index 0000000..9da0a44 --- /dev/null +++ b/get_icon.py @@ -0,0 +1,16 @@ +from .get_background import download_image_with_httpx_auto_redirect +import asyncio + +async def get_icon_image(url: str): + if url.startswith("http"): + icon_data = await download_image_with_httpx_auto_redirect(url) + if icon_data: + return icon_data + else: + return None + else: + def read_file(path): + with open(path, "rb") as f: + return f.read() + loop = asyncio.get_event_loop() + return await loop.run_in_executor(None, read_file, url) diff --git a/main.py b/main.py deleted file mode 100644 index f3cc3eb..0000000 --- a/main.py +++ /dev/null @@ -1,113 +0,0 @@ -from get_background import download_image_with_httpx_auto_redirect -from create_image import create_image - -# Java版查询模块 -from mc_status_api.JavaServerStatus import java_status -# 基岩版查询模块 -from mc_status_api.BedrockServerStatus import bedrock_status -# 此API优先解析 srv 记录 -from mc_status_api.dnslookup import dns_lookup -# 格式化文本 -from mc_status_api.FormatData import format_java_data, format_bedrock_data - -import base64 -import asyncio - -BACKGROUND_URL = "https://www.loliapi.com/acg/" -DEFAULT_ICON = "./minecraft-creeper-face.png" - -async def get_icon_image(url: str): - if url.startswith("http"): - icon_data = await download_image_with_httpx_auto_redirect(url) - if icon_data: - return icon_data - else: - return None - else: - def read_file(path): - with open(path, "rb") as f: - return f.read() - loop = asyncio.get_event_loop() - return await loop.run_in_executor(None, read_file, url) - -async def generate_java_status_image(addr: str): - loop = asyncio.get_event_loop() - try: - ip, type = await loop.run_in_executor(None, dns_lookup, addr) - status = await loop.run_in_executor(None, java_status, ip) - data = format_java_data(ip, type, status) - except Exception as e: - print(f"查询服务器时出错: {e}") - return - - background_data = await download_image_with_httpx_auto_redirect(BACKGROUND_URL) - if not background_data: - background_data = None - - icon_data = await get_icon_image(DEFAULT_ICON) - - motd_list = data['motd'].split("\n") - text_list = [ - f"ip: {data['ip']}", - f"type: {data['type']}", - f"version: {data['version']}", - f"latency: {round(data['latency'], 2)} ms", - f"players: {data['players']['online']}/{data['players']['max']}", - ] - - if status.icon: - image = await loop.run_in_executor(None, - create_image, - background_data, - base64.b64decode(status.icon.split(",")[1]), - text_list, - motd_list) - else: - image = await loop.run_in_executor(None, - create_image, - background_data, - icon_data, - text_list, - motd_list) - return image - -async def generate_bedrock_status_image(addr: str): - loop = asyncio.get_event_loop() - try: - ip, type = await loop.run_in_executor(None, dns_lookup, addr) - status = await loop.run_in_executor(None, bedrock_status, ip) - data = format_bedrock_data(ip, status) - except Exception as e: - print(f"查询服务器时出错: {e}") - return - - background_data = await download_image_with_httpx_auto_redirect(BACKGROUND_URL) - if not background_data: - background_data = None - - icon_data = await get_icon_image(DEFAULT_ICON) - - motd_list = data['motd'].split("\n") - text_list = [ - f"ip: {data['ip']}", - f"version: {data['version']}", - f"latency: {round(data['latency'], 2)} ms", - f"players: {data['players']['online']}/{data['players']['max']}", - ] - - image = await loop.run_in_executor(None, - create_image, - background_data, - icon_data, - text_list, - motd_list) - return image - -if __name__ == "__main__": - image = asyncio.run(generate_java_status_image("mc.hypixel.net")) - if image: - image.save("output_image.png") - - image = asyncio.run(generate_bedrock_status_image("play.cubecraft.net")) - if image: - image.save("output_image-be.png") \ No newline at end of file diff --git a/mc_status_api b/mc_status_api deleted file mode 160000 index 7346b1f..0000000 --- a/mc_status_api +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7346b1f7729c7d0884f5ba705420f8a6aeb643b8