修改优化开箱显示图片

This commit is contained in:
HibiKier 2023-04-01 01:50:34 +08:00
parent 4e35090ba6
commit 0c7c7f3987
16 changed files with 202 additions and 106 deletions

View File

@ -331,6 +331,11 @@ PS: **ARM平台** 请使用全量版 同时 **如果你的机器 RAM < 1G 可能
## 更新
### 2023/4/1
* 修复开箱偶尔出现`未抽取到任何皮肤`
* 修改优化开箱显示图片
### 2023/3/28
* 补全注释`SCRIPT`中的sql语句

View File

@ -235,7 +235,7 @@ async def _(event: MessageEvent, arg: Message = CommandArg(), cmd: str = OneComm
await update_case.finish(f"未登录, 已停止更新...")
rand = random.randint(300, 500)
result = f"更新全部{type_}完成"
if i < len(case_list):
if i < len(case_list) - 1:
next_case = case_list[i + 1]
result = f"将在 {rand} 秒后更新下一{type_}: {next_case}"
await update_case.send(f"{info}, {result}")
@ -248,7 +248,9 @@ async def _(event: MessageEvent, arg: Message = CommandArg(), cmd: str = OneComm
else:
await update_case.send(f"开始{cmd}: {msg}, 请稍等")
try:
await update_case.send(await update_skin_data(msg, is_update_case_name), at_sender=True)
await update_case.send(
await update_skin_data(msg, is_update_case_name), at_sender=True
)
except Exception as e:
logger.error(f"{cmd}: {msg}", e=e)
await update_case.send(f"成功{cmd}: {msg} 发生错误: {type(e)}: {e}")

View File

@ -14,6 +14,56 @@ BASE_PATH = IMAGE_PATH / "csgo_cases"
ICON_PATH = IMAGE_PATH / "_icon"
async def draw_card(skin: BuffSkin, rand: str) -> BuildImage:
"""构造抽取图片
Args:
skin (BuffSkin): BuffSkin
rand (str): 磨损
Returns:
BuildImage: BuildImage
"""
name = skin.name + "-" + skin.skin_name + "-" + skin.abrasion
file_path = BASE_PATH / cn2py(skin.case_name.split(",")[0]) / f"{cn2py(name)}.jpg"
if not file_path.exists():
logger.warning(f"皮肤图片: {name} 不存在", "开箱")
skin_bk = BuildImage(
460, 200, color=(25, 25, 25, 100), font_size=25, font="CJGaoDeGuo.otf"
)
if file_path.exists():
skin_image = BuildImage(205, 153, background=file_path)
await skin_bk.apaste(skin_image, (10, 30), alpha=True)
await skin_bk.aline((220, 10, 220, 180))
await skin_bk.atext((10, 10), skin.name, (255, 255, 255))
name_icon = BuildImage(20, 20, background=ICON_PATH / "name_white.png")
await skin_bk.apaste(name_icon, (240, 13), True)
await skin_bk.atext((265, 15), f"名称:", (255, 255, 255), font_size=20)
await skin_bk.atext(
(300, 9),
f"{skin.skin_name + ('(St)' if skin.is_stattrak else '')}",
(255, 255, 255),
)
tone_icon = BuildImage(20, 20, background=ICON_PATH / "tone_white.png")
await skin_bk.apaste(tone_icon, (240, 45), True)
await skin_bk.atext((265, 45), "品质:", (255, 255, 255), font_size=20)
await skin_bk.atext((300, 40), COLOR2NAME[skin.color][:2], COLOR2COLOR[skin.color])
type_icon = BuildImage(20, 20, background=ICON_PATH / "type_white.png")
await skin_bk.apaste(type_icon, (240, 73), True)
await skin_bk.atext((265, 75), "类型:", (255, 255, 255), font_size=20)
await skin_bk.atext((300, 70), skin.weapon_type, (255, 255, 255))
price_icon = BuildImage(20, 20, background=ICON_PATH / "price_white.png")
await skin_bk.apaste(price_icon, (240, 103), True)
await skin_bk.atext((265, 105), "价格:", (255, 255, 255), font_size=20)
await skin_bk.atext((300, 102), str(skin.sell_min_price), (0, 255, 98))
abrasion_icon = BuildImage(20, 20, background=ICON_PATH / "abrasion_white.png")
await skin_bk.apaste(abrasion_icon, (240, 133), True)
await skin_bk.atext((265, 135), "磨损:", (255, 255, 255), font_size=20)
await skin_bk.atext((300, 130), skin.abrasion, (255, 255, 255))
await skin_bk.atext((228, 165), f"({rand})", (255, 255, 255))
return skin_bk
async def generate_skin(skin: BuffSkin, update_count: int) -> Optional[BuildImage]:
"""构造皮肤图片
@ -27,13 +77,13 @@ async def generate_skin(skin: BuffSkin, update_count: int) -> Optional[BuildImag
file_path = BASE_PATH / cn2py(skin.case_name.split(",")[0]) / f"{cn2py(name)}.jpg"
if not file_path.exists():
logger.warning(f"皮肤图片: {name} 不存在", "查看武器箱")
return None
if skin.color == "CASE":
skin_img = BuildImage(200, 200, background=file_path)
case_bk = BuildImage(
700, 200, color=(25, 25, 25, 100), font_size=25, font="CJGaoDeGuo.otf"
)
await case_bk.apaste(skin_img, (10, 10), True)
if file_path.exists():
skin_img = BuildImage(200, 200, background=file_path)
await case_bk.apaste(skin_img, (10, 10), True)
await case_bk.aline((250, 10, 250, 190))
await case_bk.aline((280, 160, 660, 160))
name_icon = BuildImage(30, 30, background=ICON_PATH / "box_white.png")
@ -86,11 +136,12 @@ async def generate_skin(skin: BuffSkin, update_count: int) -> Optional[BuildImag
skin_bk = BuildImage(
235, 250, color=(25, 25, 25, 100), font_size=25, font="CJGaoDeGuo.otf"
)
skin_image = BuildImage(205, 153, background=file_path)
if file_path.exists():
skin_image = BuildImage(205, 153, background=file_path)
await skin_bk.apaste(skin_image, (10, 30), alpha=True)
update_count_icon = BuildImage(
35, 35, background=ICON_PATH / "reload_white.png"
)
await skin_bk.apaste(skin_image, (10, 30), alpha=True)
await skin_bk.aline((10, 180, 220, 180))
await skin_bk.atext((10, 10), skin.name, (255, 255, 255))
await skin_bk.apaste(update_count_icon, (140, 10), True)

View File

@ -72,7 +72,7 @@ class BuffSkin(Model):
) -> List["BuffSkin"]: # type: ignore
query = cls
if case_name:
query = query.filter(case_name=case_name)
query = query.filter(case_name__contains=case_name)
query = query.filter(abrasion=abrasion, is_stattrak=is_stattrak, color=color)
skin_list = await query.annotate(rand=Random()).limit(num) # type:ignore
num_ = num

View File

@ -14,6 +14,7 @@ from utils.image_utils import BuildImage
from utils.message_builder import image
from utils.utils import cn2py
from .build_image import draw_card
from .config import *
from .models.open_cases_log import OpenCasesLog
from .models.open_cases_user import OpenCasesUser
@ -147,14 +148,11 @@ async def open_case(user_qq: int, group_id: int, case_name: str) -> Union[str, M
)
logger.debug(f"添加 1 条开箱日志", "开箱", user_qq, group_id)
over_count = max_count - user.today_open_total
img = await draw_card(skin, rand)
return (
f"开启{case_name}武器箱.\n剩余开箱次数:{over_count}.\n"
+ image(img_path)
+ "\n"
+ f"皮肤:[{COLOR2NAME[skin.color]}]{skin.name}{'StatTrak™' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion})\n"
f"磨损:{rand}\n"
f"价格:{price_result}\n箱子单价:{case_price}\n花费:{17 + case_price:.2f}\n"
f":{ridicule_result}"
+ image(img)
+ f"\n箱子单价:{case_price}\n花费:{17 + case_price:.2f}\n:{ridicule_result}"
)
@ -191,12 +189,7 @@ async def open_multiple_case(
f"今天开箱次数不足{num}次噢,请单抽试试看(也许单抽运气更好?)"
f"\n剩余开箱次数:{max_count - user.today_open_total}"
)
if num < 5:
h = 270
elif num % 5 == 0:
h = 270 * int(num / 5)
else:
h = 270 * int(num / 5) + 270
logger.debug(f"尝试开启武器箱: {case_name}", "开箱", user_qq, group_id)
case = cn2py(case_name)
skin_count = {}
img_list = []
@ -212,32 +205,19 @@ async def open_multiple_case(
case_price = 0
if case_skin := await BuffSkin.get_or_none(case_name=case_name, color="CASE"):
case_price = case_skin.sell_min_price
cnt = 0
img_w, img_h = 0, 0
for skin, rand in skin_list:
img = await draw_card(skin, str(rand)[:11])
img_w, img_h = img.size
total_price += skin.sell_min_price
rand = str(rand)[:11]
add_count(user, skin, case_price)
color_name = COLOR2CN[skin.color]
if skin.is_stattrak:
color_name += "(暗金)"
if not skin_count.get(color_name):
skin_count[color_name] = 0
skin_count[color_name] += 1
name = skin.name + "-" + skin.skin_name + "-" + skin.abrasion
img_path = IMAGE_PATH / "csgo_cases" / case / f"{cn2py(name)}.jpg"
wImg = BuildImage(200, 270, 200, 200)
img = BuildImage(200, 200, background=img_path)
await wImg.apaste(img, (0, 0), True)
await wImg.atext(
(5, 200),
f"{skin.name}{'StatTrak™' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion})",
)
cnt += 1
await wImg.atext((5, 220), f"磨损:{rand}")
await wImg.atext((5, 240), f"价格:{skin.sell_min_price}")
img_list.append(wImg)
add_count(user, skin, case_price)
img_list.append(img)
logger.info(
f"开启{case_name}武器箱获得 {skin.name}{'StatTrak™' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion}) 磨损: [{rand}] 价格: {skin.sell_min_price}",
f"开启{case_name}武器箱获得 {skin.name}{'StatTrak™' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion}) 磨损: [{rand:.11f}] 价格: {skin.sell_min_price}",
"开箱",
user_qq,
group_id,
@ -261,16 +241,26 @@ async def open_multiple_case(
if log_list:
await OpenCasesLog.bulk_create(log_list, 10)
logger.debug(f"添加 {len(log_list)} 条开箱日志", "开箱", user_qq, group_id)
markImg = BuildImage(1000, h, 200, 270)
img_w += 10
img_h += 10
w = img_w * 5
if num < 5:
h = img_h - 10
w = img_w * num
elif not num % 5:
h = img_h * int(num / 5)
else:
h = img_h * int(num / 5) + img_h
markImg = BuildImage(w, h, img_w - 10, img_h - 10, 10)
for img in img_list:
markImg.paste(img)
markImg.paste(img, alpha=True)
over_count = max_count - user.today_open_total
result = ""
for color_name in skin_count:
result += f"[{color_name}:{skin_count[color_name]}] "
return (
f"开启{case_name}武器箱\n剩余开箱次数:{over_count}\n"
+ image(markImg.pic2bs4())
+ image(markImg)
+ "\n"
+ result[:-1]
+ f"\n箱子单价:{case_price}\n总获取金额:{total_price:.2f}\n总花费:{(17 + case_price) * num:.2f}"

View File

@ -45,9 +45,19 @@ class CaseManager:
@classmethod
async def reload(cls):
cls.CURRENT_CASES = (
await BuffSkin.filter(case_name__not="未知武器箱").annotate().distinct().values_list("case_name", flat=True) # type: ignore
cls.CURRENT_CASES = []
case_list = await BuffSkin.filter(color="CASE").values_list(
"case_name", flat=True
)
for case_name in (
await BuffSkin.filter(case_name__not="未知武器箱")
.annotate()
.distinct()
.values_list("case_name", flat=True)
):
for name in case_name.split(","): # type: ignore
if name not in cls.CURRENT_CASES and name in case_list:
cls.CURRENT_CASES.append(name)
async def update_skin_data(name: str, is_update_case_name: bool = False) -> str:

View File

@ -1,4 +1,5 @@
from pydantic.error_wrappers import ValidationError
from services.log import logger
from utils.manager import group_manager
from utils.utils import get_bot
@ -7,8 +8,8 @@ from ..auth import Depends, User, token_to_user
from ..config import *
@app.get("/webui/group")
async def _(user: User = Depends(token_to_user)) -> Result:
@router.get("/group", dependencies=[token_to_user()])
async def _() -> Result:
"""
获取群信息
"""
@ -47,8 +48,8 @@ async def _(user: User = Depends(token_to_user)) -> Result:
return Result(code=200, data=group_list_result)
@app.post("/webui/group")
async def _(group: GroupResult, user: User = Depends(token_to_user)) -> Result:
@router.post("/group", dependencies=[token_to_user()])
async def _(group: GroupResult) -> Result:
"""
修改群信息
"""
@ -58,4 +59,4 @@ async def _(group: GroupResult, user: User = Depends(token_to_user)) -> Result:
group_manager.turn_on_group_bot_status(group_id)
else:
group_manager.shutdown_group_bot_status(group_id)
return Result(code=200, data="修改成功!")
return Result(data="修改成功!")

View File

@ -1,9 +1,14 @@
from pydantic import ValidationError
from configs.config import Config
from services.log import logger
from utils.manager import (plugins2block_manager, plugins2cd_manager,
plugins2count_manager, plugins2settings_manager,
plugins_manager)
from utils.manager import (
plugins2block_manager,
plugins2cd_manager,
plugins2count_manager,
plugins2settings_manager,
plugins_manager,
)
from utils.utils import get_matchers
from ..auth import Depends, User, token_to_user
@ -12,8 +17,8 @@ from ..config import *
plugin_name_list = None
@app.get("/webui/plugins")
def _(type_: Optional[str], user: User = Depends(token_to_user)) -> Result:
@router.get("/plugins", dependencies=[token_to_user()])
def _(type_: Optional[str]) -> Result:
"""
获取插件列表
:param type_: 类型 normal, superuser, hidden, admin
@ -101,7 +106,7 @@ def _(type_: Optional[str], user: User = Depends(token_to_user)) -> Result:
return Result(code=200, data=plugin_list)
@app.post("/webui/plugins")
@router.post("/plugins", dependencies=[token_to_user()])
def _(plugin: Plugin, user: User = Depends(token_to_user)) -> Result:
"""
修改插件信息
@ -126,7 +131,9 @@ def _(plugin: Plugin, user: User = Depends(token_to_user)) -> Result:
) or isinstance(c.default_value, float):
c.value = float(c.value)
elif isinstance(c.value, str) and (
isinstance(Config.get_config(plugin.model, c.key, c.value), (list, tuple))
isinstance(
Config.get_config(plugin.model, c.key, c.value), (list, tuple)
)
or isinstance(c.default_value, (list, tuple))
):
default_value = Config.get_config(plugin.model, c.key, c.value)
@ -161,7 +168,9 @@ def _(plugin: Plugin, user: User = Depends(token_to_user)) -> Result:
)
for key in plugins2settings_manager.keys():
if isinstance(plugins2settings_manager[key].cmd, str):
plugins2settings_manager[key].cmd = plugins2settings_manager[key].cmd.split(',')
plugins2settings_manager[key].cmd = plugins2settings_manager[key].cmd.split(
","
)
plugins2settings_manager.save()
plugins_manager.save()
return Result(code=200, data="修改成功!")

View File

@ -6,8 +6,8 @@ from ..auth import Depends, User, token_to_user
from ..config import *
@app.get("/webui/request")
def _(type_: Optional[str], user: User = Depends(token_to_user)) -> Result:
@router.get("/webui/request", dependencies=[token_to_user()])
def _(type_: Optional[str]) -> Result:
req_data = requests_manager.get_data()
req_list = []
if type_ in ["group", "private"]:
@ -19,8 +19,8 @@ def _(type_: Optional[str], user: User = Depends(token_to_user)) -> Result:
return Result(code=200, data=req_list)
@app.delete("/webui/request")
def _(type_: Optional[str], user: User = Depends(token_to_user)) -> Result:
@router.delete("/webui/request", dependencies=[token_to_user()])
def _(type_: Optional[str]) -> Result:
"""
清空请求
:param type_: 类型
@ -29,8 +29,8 @@ def _(type_: Optional[str], user: User = Depends(token_to_user)) -> Result:
return Result(code=200)
@app.post("/webui/request")
async def _(parma: RequestParma, user: User = Depends(token_to_user)) -> Result:
@router.post("/webui/request", dependencies=[token_to_user()])
async def _(parma: RequestParma) -> Result:
"""
操作请求
:param parma: 参数

View File

@ -4,6 +4,7 @@ from pathlib import Path
import psutil
import ujson as json
from configs.path_config import (
DATA_PATH,
FONT_PATH,
@ -28,21 +29,21 @@ memory_data = {"data": []}
disk_data = {"data": []}
@app.get("/webui/system")
@router.get("/system", dependencies=[token_to_user()])
async def _() -> Result:
return await get_system_data()
@app.get("/webui/system/status")
async def _(user: User = Depends(token_to_user)) -> Result:
@router.get("/webui/system/status", dependencies=[token_to_user()])
async def _() -> Result:
return Result(
code=200,
data=await asyncio.get_event_loop().run_in_executor(None, _get_system_status),
)
@app.get("/webui/system/disk")
async def _(type_: Optional[str] = None, user: User = Depends(token_to_user)) -> Result:
@router.get("/webui/system/disk", dependencies=[token_to_user()])
async def _(type_: Optional[str] = None) -> Result:
return Result(
code=200,
data=await asyncio.get_event_loop().run_in_executor(
@ -51,8 +52,8 @@ async def _(type_: Optional[str] = None, user: User = Depends(token_to_user)) ->
)
@app.get("/webui/system/statusList")
async def _(user: User = Depends(token_to_user)) -> Result:
@router.get("/webui/system/statusList", dependencies=[token_to_user()])
async def _() -> Result:
global cpu_data, memory_data, disk_data
await asyncio.get_event_loop().run_in_executor(None, _get_system_status)
cpu_rst = cpu_data["data"][-10:] if len(cpu_data["data"]) > 10 else cpu_data["data"]
@ -74,7 +75,7 @@ async def _(user: User = Depends(token_to_user)) -> Result:
)
async def get_system_data(user: User = Depends(token_to_user)):
async def get_system_data():
"""
说明:
获取系统信息资源文件大小网络状态等
@ -105,7 +106,7 @@ async def get_system_data(user: User = Depends(token_to_user)):
)
def _get_system_status(user: User = Depends(token_to_user)) -> SystemStatus:
def _get_system_status() -> SystemStatus:
"""
说明:
获取系统信息等
@ -123,7 +124,7 @@ def _get_system_status(user: User = Depends(token_to_user)) -> SystemStatus:
def _get_system_disk(
type_: Optional[str], user: User = Depends(token_to_user)
type_: Optional[str],
) -> Union[SystemFolderSize, Dict[str, Union[float, datetime]]]:
"""
说明:

View File

@ -1,16 +1,18 @@
import json
from datetime import datetime, timedelta
from configs.path_config import DATA_PATH
from typing import Optional
from starlette import status
import nonebot
from fastapi import Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from pydantic import BaseModel
from configs.config import Config
from jose import JWTError, jwt
import nonebot
from pydantic import BaseModel
from starlette import status
from ..config import Result
from configs.config import Config
from configs.path_config import DATA_PATH
from ..config import Result, router
app = nonebot.get_app()
@ -19,14 +21,14 @@ SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="webui/login")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="api/login")
token_file = DATA_PATH / "web_ui" / "token.json"
token_file.parent.mkdir(parents=True, exist_ok=True)
token_data = {"token": []}
if token_file.exists():
token_data = json.load(open(token_file, 'r', encoding='utf8'))
token_data = json.load(open(token_file, "r", encoding="utf8"))
class User(BaseModel):
@ -39,11 +41,6 @@ class Token(BaseModel):
token_type: str
# USER_LIST = [
# User(username="admin", password="123")
# ]
def get_user(uname: str) -> Optional[User]:
username = Config.get_config("web-ui", "username")
password = Config.get_config("web-ui", "password")
@ -59,24 +56,26 @@ form_exception = HTTPException(
def create_token(user: User, expires_delta: Optional[timedelta] = None):
expire = datetime.utcnow() + expires_delta or timedelta(minutes=15)
expire = datetime.utcnow() + (expires_delta or timedelta(minutes=15))
return jwt.encode(
claims={"sub": user.username, "exp": expire},
key=SECRET_KEY,
algorithm=ALGORITHM
algorithm=ALGORITHM,
)
@app.post("/webui/login")
@router.post("/login")
async def login_get_token(form_data: OAuth2PasswordRequestForm = Depends()):
user: User = get_user(form_data.username)
user = get_user(form_data.username)
if not user or user.password != form_data.password:
raise form_exception
access_token = create_token(user=user, expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES))
access_token = create_token(
user=user, expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
)
token_data["token"].append(access_token)
if len(token_data["token"]) > 3:
token_data["token"] = token_data["token"][1:]
with open(token_file, 'w', encoding="utf8") as f:
with open(token_file, "w", encoding="utf8") as f:
json.dump(token_data, f, ensure_ascii=False, indent=4)
return {"access_token": access_token, "token_type": "bearer"}
@ -88,20 +87,21 @@ credentials_exception = HTTPException(
)
@app.post("/webui/auth")
@app.post("/auth")
def token_to_user(token: str = Depends(oauth2_scheme)):
if token not in token_data["token"]:
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username, expire = payload.get("sub"), payload.get("exp")
user = get_user(username)
user = get_user(username) # type: ignore
if user is None:
raise JWTError
except JWTError:
return Result(code=401)
return Result(code=200, data="ok")
return Result(code=200, info="登录成功")
if __name__ == '__main__':
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8080)

View File

@ -1,9 +1,10 @@
from typing import Optional, List, Any, Union, Dict
from pydantic import BaseModel
from fastapi.middleware.cors import CORSMiddleware
from datetime import datetime
import nonebot
from typing import Any, Dict, List, Optional, Union
import nonebot
from fastapi import APIRouter
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
app = nonebot.get_app()
@ -17,11 +18,14 @@ app.add_middleware(
allow_headers=["*"],
)
router = APIRouter(tags=["api"])
class CdLimit(BaseModel):
"""
Cd 限制
"""
cd: int
status: bool
check_type: str
@ -33,6 +37,7 @@ class BlockLimit(BaseModel):
"""
Block限制
"""
status: bool
check_type: str
limit_type: str
@ -43,6 +48,7 @@ class CountLimit(BaseModel):
"""
Count限制
"""
max_count: int
status: bool
limit_type: str
@ -53,6 +59,7 @@ class PluginManager(BaseModel):
"""
插件信息
"""
plugin_name: str # 插件名称
status: Optional[bool] # 插件状态
error: Optional[bool] # 加载状态
@ -65,6 +72,7 @@ class PluginSettings(BaseModel):
"""
插件基本设置
"""
level: Optional[int] # 群权限等级
default_status: Optional[bool] # 默认开关
limit_superuser: Optional[bool] # 是否限制超级用户
@ -77,6 +85,7 @@ class PluginConfig(BaseModel):
"""
插件配置项
"""
id: int
key: str
value: Optional[Any]
@ -88,6 +97,7 @@ class Plugin(BaseModel):
"""
插件
"""
model: str # 模块
plugin_settings: Optional[PluginSettings]
plugin_manager: Optional[PluginManager]
@ -101,6 +111,7 @@ class Group(BaseModel):
"""
群组信息
"""
group_id: int
group_name: str
member_count: int
@ -111,6 +122,7 @@ class Task(BaseModel):
"""
被动技能
"""
name: str
nameZh: str
status: bool
@ -120,6 +132,7 @@ class GroupResult(BaseModel):
"""
群组返回数据
"""
group: Group
level: int
status: bool
@ -131,6 +144,7 @@ class RequestResult(BaseModel):
"""
好友/群组请求管理
"""
oid: str
id: int
flag: str
@ -148,6 +162,7 @@ class RequestParma(BaseModel):
"""
操作请求接收数据
"""
id: int
handle: str
type: str
@ -157,6 +172,7 @@ class SystemStatus(BaseModel):
"""
系统状态
"""
cpu: int
memory: int
disk: int
@ -167,6 +183,7 @@ class SystemNetwork(BaseModel):
"""
系统网络状态
"""
baidu: int
google: int
@ -175,6 +192,7 @@ class SystemFolderSize(BaseModel):
"""
资源文件占比
"""
font_dir_size: float
image_dir_size: float
text_dir_size: float
@ -189,6 +207,7 @@ class SystemStatusList(BaseModel):
"""
状态记录
"""
cpu_data: List[Dict[str, Union[float, str]]]
memory_data: List[Dict[str, Union[float, str]]]
disk_data: List[Dict[str, Union[float, str]]]
@ -198,6 +217,7 @@ class SystemResult(BaseModel):
"""
系统api返回
"""
status: SystemStatus
network: SystemNetwork
disk: SystemFolderSize
@ -208,5 +228,7 @@ class Result(BaseModel):
"""
总体返回
"""
code: int
data: Any
code: int = 200
info: str = "操作成功"
data: Any = None

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@ -160,6 +160,7 @@ class BuildImage:
h: int,
paste_image_width: int = 0,
paste_image_height: int = 0,
paste_space: int = 0,
color: Union[str, Tuple[int, int, int], Tuple[int, int, int, int]] = None,
image_mode: ModeType = "RGBA",
font_size: int = 10,
@ -177,6 +178,7 @@ class BuildImage:
:param h: 自定义图片的高度h=0时为图片原本高度
:param paste_image_width: 当图片做为背景图时设置贴图的宽度用于贴图自动换行
:param paste_image_height: 当图片做为背景图时设置贴图的高度用于贴图自动换行
:param paste_space: 自动贴图间隔
:param color: 生成图片的颜色
:param image_mode: 图片的类型
:param font_size: 文字大小
@ -190,6 +192,7 @@ class BuildImage:
self.h = int(h)
self.paste_image_width = int(paste_image_width)
self.paste_image_height = int(paste_image_height)
self.paste_space = int(paste_space)
self._current_w = 0
self._current_h = 0
self.uid = uuid.uuid1()
@ -277,7 +280,9 @@ class BuildImage:
:param center_type: 居中类型可能的值 center: 完全居中by_width: 水平居中by_height: 垂直居中
:param allow_negative: 允许使用负数作为坐标且不超出图片范围从右侧开始计算
"""
await self.loop.run_in_executor(None, self.paste, img, pos, alpha, center_type, allow_negative)
await self.loop.run_in_executor(
None, self.paste, img, pos, alpha, center_type, allow_negative
)
def paste(
self,
@ -324,7 +329,7 @@ class BuildImage:
img = img.markImg
if self._current_w >= self.w:
self._current_w = 0
self._current_h += self.paste_image_height
self._current_h += self.paste_image_height + self.paste_space
if not pos:
pos = (self._current_w, self._current_h)
if alpha:
@ -335,7 +340,7 @@ class BuildImage:
self.markImg.paste(img, pos, img)
else:
self.markImg.paste(img, pos)
self._current_w += self.paste_image_width
self._current_w += self.paste_image_width + self.paste_space
@classmethod
def get_text_size(cls, msg: str, font: str, font_size: int) -> Tuple[int, int]:
@ -469,7 +474,7 @@ class BuildImage:
"center_type must be 'center', 'by_width' or 'by_height'"
)
w, h = self.w, self.h
longgest_text = ''
longgest_text = ""
sentence = text.split("\n")
for x in sentence:
longgest_text = x if len(x) > len(longgest_text) else longgest_text