🎨 使用Python包管理和模块访问

🎨 重构数据库结构, 使用集中式服务定位器与数据库交互
🎨 更改部分代码逻辑, 减小内存消耗
This commit is contained in:
2025-11-30 16:45:13 +08:00
parent b4d3baebe6
commit a6691595e5
29 changed files with 1356 additions and 885 deletions
+15 -14
View File
@@ -7,17 +7,18 @@ from zhenxun.services.log import logger
from zhenxun.utils.message import MessageUtils
from .command import diuse_farm, diuse_register, reclamation
from .core.activity.sign_in import g_pSignInManager
from .core.database.database import g_pSqlManager
from .core import (
CHelpManager,
CShopManager,
g_pDBlocator,
g_pSqlManager,
g_pUserPool,
getFarmManager,
getSignInManager,
)
from .core.dbService import g_pDBService
from .core.farm import g_pFarmManager
from .core.help import g_pHelpManager
from .core.player.playerPool import g_pUserPool
from .core.shop import g_pShopManager
from .event.event import g_pEventManager
from .utils.config import g_sResourcePath, g_sTranslation
from .utils.json import g_pJsonManager
from .utils.request import g_pRequestManager
from .event import g_pEventManager
from .utils import config, getJsonManager, getRequestManager
__plugin_meta__ = PluginMetadata(
name="真寻农场",
@@ -102,9 +103,9 @@ async def start():
await g_pDBService.init()
# 检查作物文件是否缺失 or 更新
await g_pRequestManager.initPlantDBFile()
await getRequestManager().initPlantDBFile()
await g_pHelpManager.createHelpImage()
await CHelpManager.createHelpImage()
# todayRewards = [
# {
@@ -141,7 +142,7 @@ async def shutdown():
@scheduler.scheduled_job(trigger="cron", hour=4, minute=30, id="signInFile")
async def signInFile():
try:
await g_pJsonManager.initSignInFile()
await g_pRequestManager.initPlantDBFile()
await getJsonManager().initSignInFile()
await getRequestManager().initPlantDBFile()
except Exception as e:
logger.error("农场定时检查出错", e=e)
+118 -116
View File
@@ -24,12 +24,8 @@ from zhenxun.services.log import logger
from zhenxun.utils._build_image import BuildImage
from zhenxun.utils.message import MessageUtils
from .core.activity.sign_in import g_pSignInManager
from .core.dbService import g_pDBService
from .core.farm import g_pFarmManager
from .core.shop import g_pShopManager
from .utils.config import g_bSignStatus, g_sTranslation
from .utils.tool import g_pToolManager
from .core import CShopManager, g_pDBlocator, getFarmManager, getSignInManager
from .utils import config, getDrawFarm, getToolManager
diuse_register = on_alconna(
Alconna("开通农场"),
@@ -43,30 +39,30 @@ diuse_register = on_alconna(
@diuse_register.handle()
async def handle_register(session: Uninfo):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is not None and await player.isRegistered():
await MessageUtils.build_message(g_sTranslation["register"]["repeat"]).send(
reply_to=True
)
await MessageUtils.build_message(
config.g_sTranslation["register"]["repeat"]
).send(reply_to=True)
return
try:
raw_name = str(session.user.name)
safe_name = g_pToolManager.sanitize_username(raw_name)
safe_name = getToolManager().sanitize_username(raw_name)
success = await g_pDBService.user.initUserInfo(uid, safe_name)
success = await g_pDBlocator.getUserManager().initUserInfo(uid, safe_name)
logger.info(f"用户 {uid} 选择的农场名称为: {raw_name} | 过滤后为: {safe_name}")
msg = (
g_sTranslation["register"]["success"].format(point=500)
config.g_sTranslation["register"]["success"].format(point=500)
if success
else g_sTranslation["register"]["error"]
else config.g_sTranslation["register"]["error"]
)
logger.info(f"用户注册 {'成功' if success else '失败'}:{uid}")
except Exception as e:
msg = g_sTranslation["register"]["error"]
msg = config.g_sTranslation["register"]["error"]
logger.error(f"注册异常 | UID:{uid} | 错误:{e}")
await MessageUtils.build_message(msg).send(reply_to=True)
@@ -108,12 +104,12 @@ diuse_farm = on_alconna(
@diuse_farm.assign("$main")
async def _(session: Uninfo):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
image = await g_pFarmManager.drawFarmByUid(uid)
image = await getDrawFarm().drawFarmByUid(uid)
await MessageUtils.build_message(image).send(reply_to=True)
@@ -128,12 +124,12 @@ diuse_farm.shortcut(
@diuse_farm.assign("detail")
async def _(session: Uninfo):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
info = await g_pFarmManager.drawDetailFarmByUid(uid)
info = await getDrawFarm().drawDetailFarmByUid(uid)
await MessageUtils.alc_forward_msg(
[info], session.self_id, BotConfig.self_nickname
@@ -151,19 +147,21 @@ diuse_farm.shortcut(
@diuse_farm.assign("my-point")
async def _(session: Uninfo):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
point = player.user["point"]
if point < 0:
await MessageUtils.build_message(g_sTranslation["basic"]["notFarm"]).send()
await MessageUtils.build_message(
config.g_sTranslation["basic"]["notFarm"]
).send()
return False
await MessageUtils.build_message(
g_sTranslation["basic"]["point"].format(point=point)
config.g_sTranslation["basic"]["point"].format(point=point)
).send(reply_to=True)
@@ -178,10 +176,10 @@ diuse_farm.shortcut(
@diuse_farm.assign("seed-shop")
async def _(session: Uninfo, res: Match[tuple[str, ...]]):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
if res.result is inspect._empty:
@@ -208,9 +206,9 @@ async def _(session: Uninfo, res: Match[tuple[str, ...]]):
page = int(raw[1])
if filterKey is None:
image = await g_pShopManager.getSeedShopImage(page, 0, 0)
image = await CShopManager.getSeedShopImage(page, 0, 0)
else:
image = await g_pShopManager.getSeedShopImage(filterKey, page, 0)
image = await CShopManager.getSeedShopImage(filterKey, page, 0)
await MessageUtils.build_message(image).send()
@@ -228,17 +226,17 @@ async def _(
session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", 1)
):
if not name.available:
await MessageUtils.build_message(g_sTranslation["buySeed"]["notSeed"]).finish(
reply_to=True
)
await MessageUtils.build_message(
config.g_sTranslation["buySeed"]["notSeed"]
).finish(reply_to=True)
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
result = await g_pShopManager.buySeed(uid, name.result, num.result)
result = await CShopManager.buySeed(uid, name.result, num.result)
await MessageUtils.build_message(result).send(reply_to=True)
@@ -253,12 +251,12 @@ diuse_farm.shortcut(
@diuse_farm.assign("my-seed")
async def _(session: Uninfo):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
result = await g_pFarmManager.getUserSeedByUid(uid)
result = await getFarmManager().getUserSeedByUid(uid)
await MessageUtils.build_message(result).send(reply_to=True)
@@ -275,17 +273,17 @@ async def _(
session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1)
):
if not name.available:
await MessageUtils.build_message(g_sTranslation["sowing"]["notSeed"]).finish(
reply_to=True
)
await MessageUtils.build_message(
config.g_sTranslation["sowing"]["notSeed"]
).finish(reply_to=True)
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
result = await g_pFarmManager.sowing(uid, name.result, num.result)
result = await getFarmManager().sowing(uid, name.result, num.result)
await MessageUtils.build_message(result).send(reply_to=True)
@@ -300,12 +298,12 @@ diuse_farm.shortcut(
@diuse_farm.assign("harvest")
async def _(session: Uninfo):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
result = await g_pFarmManager.harvest(uid)
result = await getFarmManager().harvest(uid)
await MessageUtils.build_message(result).send(reply_to=True)
@@ -320,12 +318,12 @@ diuse_farm.shortcut(
@diuse_farm.assign("eradicate")
async def _(session: Uninfo):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
result = await g_pFarmManager.eradicate(uid)
result = await getFarmManager().eradicate(uid)
await MessageUtils.build_message(result).send(reply_to=True)
@@ -340,12 +338,12 @@ diuse_farm.shortcut(
@diuse_farm.assign("my-plant")
async def _(session: Uninfo):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
result = await g_pFarmManager.getUserPlantByUid(uid)
result = await getFarmManager().getUserPlantByUid(uid)
await MessageUtils.build_message(result).send(reply_to=True)
@@ -360,12 +358,12 @@ diuse_farm.shortcut(
@diuse_farm.assign("lock-plant")
async def _(session: Uninfo, name: Match[str]):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
result = await g_pFarmManager.lockUserPlantByUid(uid, name.result, 1)
result = await getFarmManager().lockUserPlantByUid(uid, name.result, 1)
await MessageUtils.build_message(result).send(reply_to=True)
@@ -380,12 +378,12 @@ diuse_farm.shortcut(
@diuse_farm.assign("unlock-plant")
async def _(session: Uninfo, name: Match[str]):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
result = await g_pFarmManager.lockUserPlantByUid(uid, name.result, 0)
result = await getFarmManager().lockUserPlantByUid(uid, name.result, 0)
await MessageUtils.build_message(result).send(reply_to=True)
@@ -402,12 +400,12 @@ async def _(
session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1)
):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
result = await g_pShopManager.sellPlantByUid(uid, name.result, num.result)
result = await CShopManager.sellPlantByUid(uid, name.result, num.result)
await MessageUtils.build_message(result).send(reply_to=True)
@@ -422,13 +420,13 @@ reclamation = on_alconna(
@reclamation.handle()
async def _(session: Uninfo):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
condition = await g_pFarmManager.reclamationCondition(uid)
condition += f"\n{g_sTranslation['reclamation']['confirm']}"
condition = await getFarmManager().reclamationCondition(uid)
condition += f"\n{config.g_sTranslation['reclamation']['confirm']}"
await MessageUtils.build_message(condition).send(reply_to=True)
@waiter(waits=["message"], keep_session=True)
@@ -437,14 +435,14 @@ async def _(session: Uninfo):
resp = await check.wait(timeout=60)
if resp is None:
await MessageUtils.build_message(g_sTranslation["reclamation"]["timeOut"]).send(
reply_to=True
)
await MessageUtils.build_message(
config.g_sTranslation["reclamation"]["timeOut"]
).send(reply_to=True)
return
if not resp == "是":
return
res = await g_pFarmManager.reclamation(uid)
res = await getFarmManager().reclamation(uid)
await MessageUtils.build_message(res).send(reply_to=True)
@@ -459,26 +457,26 @@ diuse_farm.shortcut(
@diuse_farm.assign("stealing")
async def _(session: Uninfo, target: Match[At]):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
if not target.available:
await MessageUtils.build_message(g_sTranslation["stealing"]["noTarget"]).finish(
reply_to=True
)
await MessageUtils.build_message(
config.g_sTranslation["stealing"]["noTarget"]
).finish(reply_to=True)
tar = target.result
result = await g_pDBService.user.isRegistered(tar.target)
result = await g_pDBlocator.getUserManager().isRegistered(tar.target)
if not result:
await MessageUtils.build_message(
g_sTranslation["stealing"]["targetNotFarm"]
config.g_sTranslation["stealing"]["targetNotFarm"]
).send()
return None
result = await g_pFarmManager.stealing(uid, tar.target)
result = await getFarmManager().stealing(uid, tar.target)
await MessageUtils.build_message(result).send(reply_to=True)
@@ -498,12 +496,12 @@ async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 0)):
)
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
result = await g_pFarmManager.buyPointByUid(uid, num.result)
result = await getFarmManager().buyPointByUid(uid, num.result)
await MessageUtils.build_message(result).send(reply_to=True)
@@ -518,25 +516,25 @@ diuse_farm.shortcut(
@diuse_farm.assign("change-name")
async def _(session: Uninfo, name: Match[str]):
if not name.available:
await MessageUtils.build_message(g_sTranslation["changeName"]["noName"]).finish(
reply_to=True
)
await MessageUtils.build_message(
config.g_sTranslation["changeName"]["noName"]
).finish(reply_to=True)
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None:
await MessageUtils.build_message(g_sTranslation["changeName"]["error1"]).send(
reply_to=True
)
await MessageUtils.build_message(
config.g_sTranslation["changeName"]["error1"]
).send(reply_to=True)
return
result = await player.updateName(name.result)
await MessageUtils.build_message(g_sTranslation["changeName"][result]).send(
await MessageUtils.build_message(config.g_sTranslation["changeName"][result]).send(
reply_to=True
)
@@ -552,17 +550,19 @@ diuse_farm.shortcut(
@diuse_farm.assign("sign-in")
async def _(session: Uninfo):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
# 判断签到是否正常加载
if not g_bSignStatus:
await MessageUtils.build_message(g_sTranslation["signIn"]["error"]).send()
if not config.g_bSignStatus:
await MessageUtils.build_message(
config.g_sTranslation["signIn"]["error"]
).send()
return
message = await g_pSignInManager.signInByUid(uid)
message = await getSignInManager().signInByUid(uid)
await MessageUtils.build_message(message).send()
@@ -577,12 +577,12 @@ soil_upgrade = on_alconna(
@soil_upgrade.handle()
async def _(session: Uninfo, index: Query[int] = AlconnaQuery("index", 1)):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
condition = await g_pFarmManager.soilUpgradeCondition(uid, index.result)
condition = await getFarmManager().soilUpgradeCondition(uid, index.result)
await MessageUtils.build_message(condition).send(reply_to=True)
@@ -595,14 +595,14 @@ async def _(session: Uninfo, index: Query[int] = AlconnaQuery("index", 1)):
resp = await check.wait(timeout=60)
if resp is None:
await MessageUtils.build_message(g_sTranslation["soilInfo"]["timeOut"]).send(
reply_to=True
)
await MessageUtils.build_message(
config.g_sTranslation["soilInfo"]["timeOut"]
).send(reply_to=True)
return
if not resp == "是":
return
res = await g_pFarmManager.soilUpgrade(uid, index.result)
res = await getFarmManager().soilUpgrade(uid, index.result)
await MessageUtils.build_message(res).send(reply_to=True)
@@ -617,12 +617,12 @@ diuse_farm.shortcut(
@diuse_farm.assign("admin-up")
async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 0)):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
await g_pDBService.userSoil.nextPhase(uid, num.result)
await g_pDBlocator.getUserSoilManager().nextPhase(uid, num.result)
diuse_farm.shortcut(
@@ -641,12 +641,12 @@ async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 0)):
)
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
result = await g_pFarmManager.pointToVipPointByUid(uid, num.result)
result = await getFarmManager().pointToVipPointByUid(uid, num.result)
await MessageUtils.build_message(result).send(reply_to=True)
@@ -661,13 +661,15 @@ diuse_farm.shortcut(
@diuse_farm.assign("my-vipPoint")
async def _(session: Uninfo):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
await MessageUtils.build_message(
g_sTranslation["basic"]["vipPoint"].format(vipPoint=player.user["vipPoint"])
config.g_sTranslation["basic"]["vipPoint"].format(
vipPoint=player.user["vipPoint"]
)
).send(reply_to=True)
@@ -699,9 +701,9 @@ diuse_farm.shortcut(
@diuse_farm.assign("vipSeed-shop")
async def _(session: Uninfo, res: Match[tuple[str, ...]]):
uid = str(session.user.id)
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if player is None or not await player.isRegistered():
await g_pToolManager.repeat()
await getToolManager().repeat()
return
if res.result is inspect._empty:
@@ -728,8 +730,8 @@ async def _(session: Uninfo, res: Match[tuple[str, ...]]):
page = int(raw[1])
if filterKey is None:
image = await g_pShopManager.getSeedShopImage(page, 0, 1)
image = await CShopManager.getSeedShopImage(page, 0, 1)
else:
image = await g_pShopManager.getSeedShopImage(filterKey, page, 1)
image = await CShopManager.getSeedShopImage(filterKey, page, 1)
await MessageUtils.build_message(image).send()
+29
View File
@@ -0,0 +1,29 @@
from .database import g_pDBlocator, g_pSqlManager
from .help import CHelpManager
from .player.player import CPlayer
from .player.playerPool import g_pUserPool
from .shop import CShopManager
def getFarmManager():
from .farm import CFarmManager
return CFarmManager()
def getSignInManager():
from .activity.sign_in import CSignInManager
return CSignInManager()
__all__ = [
"CHelpManager",
"CPlayer",
"CShopManager",
"g_pDBlocator",
"g_pSqlManager",
"g_pUserPool",
"getFarmManager",
"getSignInManager",
]
+23 -25
View File
@@ -4,15 +4,14 @@ from typing import Any
from zhenxun.configs.config import Config
from zhenxun.services.log import logger
from ...utils.config import DATA_PATH, g_sResourcePath, g_sTranslation
from ...utils.json import g_pJsonManager
from ...utils.tool import g_pToolManager
from ...utils import config, getJsonManager, getToolManager
from ..dbService import g_pDBService
class CSignInManager:
async def signInByUid(self, uid: str) -> str:
toDay = g_pToolManager.dateTime().date().today()
@classmethod
async def signInByUid(cls, uid: str) -> str:
toDay = getToolManager().dateTime().date().today()
message = ""
status = await g_pDBService.userSign.sign(uid, toDay.strftime("%Y-%m-%d"))
@@ -26,11 +25,11 @@ class CSignInManager:
uid, toDay.strftime("%Y-%m-%d")
)
message += g_sTranslation["signIn"]["success"].format(
message += config.g_sTranslation["signIn"]["success"].format(
day=signDay, exp=exp, num=point
)
jSign = await g_pJsonManager.getSign()
jSign = await getJsonManager().getSign()
reward = jSign["continuou"].get(f"{signDay}", None)
signType = Config.get_config("zhenxun_plugin_farm", "签到图片样式")
@@ -41,30 +40,31 @@ class CSignInManager:
plant = reward.get("plant", {})
message += g_sTranslation["signIn"]["grandTotal"].format(
message += config.g_sTranslation["signIn"]["grandTotal"].format(
exp=extraExp, num=extraPoint
)
vipPoint = reward.get("vipPoint", 0)
if vipPoint > 0:
message += g_sTranslation["signIn"]["grandTotal1"].format(
message += config.g_sTranslation["signIn"]["grandTotal1"].format(
num=vipPoint
)
if plant:
for key, value in plant.items():
message += g_sTranslation["signIn"]["grandTotal2"].format(
name=key, num=value
)
message += config.g_sTranslation["signIn"][
"grandTotal2"
].format(name=key, num=value)
else:
message = g_sTranslation["signIn"]["error1"]
message = config.g_sTranslation["signIn"]["error1"]
pass
return message
@classmethod
def generateSignData(
self,
cls,
todayRewards: list[dict[str, Any]],
cumulativeRewards: list[dict[str, Any]],
currentProgress: int,
@@ -104,8 +104,9 @@ class CSignInManager:
"consecutiveDays": consecutiveDays,
}
@classmethod
async def createSignImage(
self,
cls,
todayRewards: list[dict[str, Any]],
cumulativeRewards: list[dict[str, Any]],
currentProgress: int,
@@ -122,12 +123,12 @@ class CSignInManager:
consecutiveDays (int, optional): 连续签到天数
"""
try:
templatePath = g_sResourcePath / "html/sign_in.html"
outputPath = g_sResourcePath / "temp_html/sign_in.html"
savePath = DATA_PATH / "farm_res/html/sign_in.png"
templatePath = config.g_sResourcePath / "html/sign_in.html"
outputPath = config.g_sResourcePath / "temp_html/sign_in.html"
savePath = config.DATA_PATH / "farm_res/html/sign_in.png"
# 1. 生成渲染数据
context = self.generateSignData(
context = cls.generateSignData(
todayRewards=todayRewards,
cumulativeRewards=cumulativeRewards,
currentProgress=currentProgress,
@@ -136,19 +137,16 @@ class CSignInManager:
)
# 2. 渲染HTML文件
g_pToolManager.renderHtmlToFile(templatePath, context, outputPath)
getToolManager().renderHtmlToFile(templatePath, context, outputPath)
# 3. 生成图片字节数据
# imageBytes = await g_pToolManager.screenshotHtmlToBytes(outputPath)
# imageBytes = await getToolManager().screenshotHtmlToBytes(outputPath)
# 4. 保存图片文件
await g_pToolManager.screenshotSave(
await getToolManager().screenshotSave(
str(outputPath), str(savePath), 600, 800
)
except Exception as e:
logger.error(f"❌ 生成签到图片时出错: {e}")
raise
g_pSignInManager = CSignInManager()
+25
View File
@@ -0,0 +1,25 @@
from .database import g_pSqlManager
from .dbServiceLocator import g_pDBlocator
from .plant import CPlantManager
from .user import CUserDB
from .userItem import CUserItemDB
from .userPlant import CUserPlantDB
from .userPlantCount import CUserPlantCountDB
from .userSeed import CUserSeedDB
from .userSign import CUserSignDB
from .userSoil import CUserSoilDB
from .userSteal import CUserStealDB
__all__ = [
"CPlantManager",
"CUserDB",
"CUserItemDB",
"CUserPlantCountDB",
"CUserPlantDB",
"CUserSeedDB",
"CUserSignDB",
"CUserSoilDB",
"CUserStealDB",
"g_pDBlocator",
"g_pSqlManager",
]
+171 -57
View File
@@ -1,60 +1,188 @@
from abc import ABC
from contextlib import asynccontextmanager
import os
from pathlib import Path
import re
from typing import Any
from typing import Any, ClassVar
import aiosqlite
from zhenxun.services.log import logger
from ...utils.config import g_sDBFilePath, g_sDBPath
from ...utils import config
from .dbServiceLocator import g_pDBlocator
class CSqlManager:
class CSqlManager(ABC):
"""
数据库管理器基类
所有具体的数据管理器都应该继承这个类
"""
m_pDB: ClassVar[aiosqlite.Connection | None] = None
def __init__(self):
dbPath = Path(g_sDBPath)
if dbPath and not dbPath.exists():
os.makedirs(dbPath, exist_ok=True)
self.m_sTableName: str | None = None
self.m_bInitialized: bool = False
@classmethod
async def cleanup(cls):
if hasattr(cls, "m_pDB") and cls.m_pDB:
await cls.m_pDB.close()
self.m_pDBPath = Path(config.g_sDBPath)
if self.m_pDBPath and not self.m_pDBPath.exists():
os.makedirs(self.m_pDBPath, exist_ok=True)
@classmethod
async def init(cls) -> bool:
try:
cls.m_pDB = await aiosqlite.connect(g_sDBFilePath)
cls.m_pDB.row_factory = aiosqlite.Row
return True
if cls.m_pDB is None:
cls.m_pDB = await aiosqlite.connect(config.g_sDBFilePath)
cls.m_pDB.row_factory = aiosqlite.Row
logger.info("真寻农场数据库连接初始化成功")
return True
else:
logger.info("真寻农场数据库连接已存在,跳过初始化")
return True
except Exception as e:
logger.debug("真寻农场初始化总数据库失败", e=e)
logger.error(f"真寻农场数据库连接初始化失败: {e}")
return False
@classmethod
async def cleanup(cls):
if cls.m_pDB:
await cls.m_pDB.close()
cls.m_pDB = None
logger.info("真寻农场数据库连接已关闭")
@classmethod
def getDB(cls) -> aiosqlite.Connection:
if cls.m_pDB is None:
raise RuntimeError("数据库连接未初始化,请先调用 init_global_db()")
return cls.m_pDB
@classmethod
def getPlantManager(cls) -> Any:
return g_pDBlocator.getPlantManager()
@classmethod
def getUserManager(cls) -> Any:
return g_pDBlocator.getUserManager()
@classmethod
def getUserSoilManager(cls) -> Any:
return g_pDBlocator.getUserSoilManager()
@classmethod
def getUserSeedManager(cls) -> Any:
return g_pDBlocator.getUserSeedManager()
@classmethod
def getUserItemManager(cls) -> Any:
return g_pDBlocator.getUserItemManager()
@classmethod
def getUserStealManager(cls) -> Any:
return g_pDBlocator.getUserStealManager()
@classmethod
def getUserSignManager(cls) -> Any:
return g_pDBlocator.getUserSignManager()
@classmethod
def getUserPlantCountManager(cls) -> Any:
return g_pDBlocator.getUserPlantCountManager()
def isInitialized(self) -> bool:
"""检查是否已初始化"""
return self.m_bInitialized
def setInitialized(self) -> None:
"""标记为已初始化"""
self.m_bInitialized = True
@classmethod
@asynccontextmanager
async def _transaction(cls):
await cls.m_pDB.execute("BEGIN;")
await cls.getDB().execute("BEGIN;")
try:
yield
except:
await cls.m_pDB.execute("ROLLBACK;")
await cls.getDB().execute("ROLLBACK;")
raise
else:
await cls.m_pDB.execute("COMMIT;")
await cls.getDB().execute("COMMIT;")
@classmethod
async def getTableInfo(cls, tableName: str) -> list:
if not re.match(r"^[A-Za-z_][A-Za-z0-9_]*$", tableName):
raise ValueError(f"Illegal table name: {tableName}")
try:
cursor = await cls.m_pDB.execute(f'PRAGMA table_info("{tableName}")')
cursor = await cls.getDB().execute(f'PRAGMA table_info("{tableName}")')
rows = await cursor.fetchall()
return [{"name": row[1], "type": row[2]} for row in rows]
except aiosqlite.Error:
return []
# @classmethod
# async def ensureTableSchema(cls, tableName: str, columns: dict) -> bool:
# """由AI生成
# 创建表或为已存在表添加缺失字段。
# 返回 True 表示有变更(创建或新增列),False 则无操作
# Args:
# tableName (str): 表名
# columns (dict): 字典
# Returns:
# bool:
# """
# info = await cls.getTableInfo(tableName)
# existing = {col["name"]: col["type"].upper() for col in info}
# desired = {k: v.upper() for k, v in columns.items() if k != "PRIMARY KEY"}
# primaryKey = columns.get("PRIMARY KEY", "")
# if not existing:
# colsDef = ", ".join(f'"{k}" {v}' for k, v in desired.items())
# if primaryKey:
# colsDef += f", PRIMARY KEY {primaryKey}"
# await cls.getDB().execute(f'CREATE TABLE "{tableName}" ({colsDef});')
# return True
# toAdd = [k for k in desired if k not in existing]
# toRemove = [k for k in existing if k not in desired]
# typeMismatch = [
# k for k in desired if k in existing and existing[k] != desired[k]
# ]
# if toAdd and not toRemove and not typeMismatch:
# for col in toAdd:
# await cls.getDB().execute(
# f'ALTER TABLE "{tableName}" ADD COLUMN "{col}" {columns[col]}'
# )
# return True
# async with cls._transaction():
# tmpTable = f"{tableName}_new"
# colsDef = ", ".join(f'"{k}" {v}' for k, v in desired.items())
# if primaryKey:
# colsDef += f", PRIMARY KEY {primaryKey}"
# await cls.getDB().execute(f'CREATE TABLE "{tmpTable}" ({colsDef});')
# commonCols = [k for k in desired if k in existing]
# if commonCols:
# colsStr = ", ".join(f'"{c}"' for c in commonCols)
# sql = (
# f'INSERT INTO "{tmpTable}" ({colsStr}) '
# f"SELECT {colsStr} "
# f'FROM "{tableName}";'
# )
# await cls.getDB().execute(sql)
# await cls.getDB().execute(f'DROP TABLE "{tableName}";')
# await cls.getDB().execute(
# f'ALTER TABLE "{tmpTable}" RENAME TO "{tableName}";'
# )
# return True
@classmethod
async def ensureTableSchema(cls, tableName: str, columns: dict) -> bool:
"""由AI生成
@@ -62,13 +190,12 @@ class CSqlManager:
返回 True 表示有变更(创建或新增列),False 则无操作
Args:
tableName (_type_): 表名
columns (_type_): 字典
tableName (str): 表名
columns (dict): 字典
Returns:
_type_: _description_
bool:
"""
info = await cls.getTableInfo(tableName)
existing = {col["name"]: col["type"].upper() for col in info}
desired = {k: v.upper() for k, v in columns.items() if k != "PRIMARY KEY"}
@@ -78,7 +205,7 @@ class CSqlManager:
colsDef = ", ".join(f'"{k}" {v}' for k, v in desired.items())
if primaryKey:
colsDef += f", PRIMARY KEY {primaryKey}"
await cls.m_pDB.execute(f'CREATE TABLE "{tableName}" ({colsDef});')
await cls.getDB().execute(f'CREATE TABLE "{tableName}" ({colsDef});')
return True
toAdd = [k for k in desired if k not in existing]
@@ -87,36 +214,23 @@ class CSqlManager:
k for k in desired if k in existing and existing[k] != desired[k]
]
if toAdd and not toRemove and not typeMismatch:
if toRemove or typeMismatch:
return False
if toAdd:
for col in toAdd:
await cls.m_pDB.execute(
f'ALTER TABLE "{tableName}" ADD COLUMN "{col}" {columns[col]}'
)
try:
await cls.getDB().execute(
f'ALTER TABLE "{tableName}" ADD COLUMN "{col}" {columns[col]}'
)
except aiosqlite.OperationalError as e:
if "duplicate column name" in str(e).lower():
continue
else:
raise
return True
async with cls._transaction():
tmpTable = f"{tableName}_new"
colsDef = ", ".join(f'"{k}" {v}' for k, v in desired.items())
if primaryKey:
colsDef += f", PRIMARY KEY {primaryKey}"
await cls.m_pDB.execute(f'CREATE TABLE "{tmpTable}" ({colsDef});')
commonCols = [k for k in desired if k in existing]
if commonCols:
colsStr = ", ".join(f'"{c}"' for c in commonCols)
sql = (
f'INSERT INTO "{tmpTable}" ({colsStr}) '
f"SELECT {colsStr} "
f'FROM "{tableName}";'
)
await cls.m_pDB.execute(sql)
await cls.m_pDB.execute(f'DROP TABLE "{tableName}";')
await cls.m_pDB.execute(
f'ALTER TABLE "{tmpTable}" RENAME TO "{tableName}";'
)
return True
return False
@classmethod
async def executeDB(cls, command: str) -> bool:
@@ -133,7 +247,7 @@ class CSqlManager:
try:
async with cls._transaction():
await cls.m_pDB.execute(command)
await cls.getDB().execute(command)
return True
except Exception:
return False
@@ -162,7 +276,7 @@ class CSqlManager:
sql = f'INSERT INTO "{tableName}" ({columns}) VALUES ({placeholders})'
async with cls._transaction():
await cls.m_pDB.execute(sql, values)
await cls.getDB().execute(sql, values)
return True
except Exception as e:
logger.debug("真寻农场插入数据失败!", e=e)
@@ -191,7 +305,7 @@ class CSqlManager:
sql = f'INSERT INTO "{tableName}" ({columns}) VALUES ({placeholders})'
async with cls._transaction():
await cls.m_pDB.executemany(
await cls.getDB().executemany(
sql, [list(data.values()) for data in data_list]
)
return True
@@ -255,7 +369,7 @@ class CSqlManager:
if limit:
sql += f" LIMIT {limit}"
cursor = await cls.m_pDB.execute(sql, params)
cursor = await cls.getDB().execute(sql, params)
rows = await cursor.fetchall()
# 转换为字典列表
@@ -304,7 +418,7 @@ class CSqlManager:
sql = f'UPDATE "{tableName}" SET {", ".join(set_conditions)} WHERE {" AND ".join(where_conditions)}'
async with cls._transaction():
cursor = await cls.m_pDB.execute(sql, params)
cursor = await cls.getDB().execute(sql, params)
# 检查是否影响了行
return cursor.rowcount > 0
except Exception as e:
@@ -337,7 +451,7 @@ class CSqlManager:
sql = f'DELETE FROM "{tableName}" WHERE {" AND ".join(where_conditions)}'
async with cls._transaction():
cursor = await cls.m_pDB.execute(sql, params)
cursor = await cls.getDB().execute(sql, params)
# 检查是否影响了行
return cursor.rowcount > 0
except Exception as e:
@@ -388,7 +502,7 @@ class CSqlManager:
sql += " WHERE " + " AND ".join(where_conditions)
cursor = await cls.m_pDB.execute(sql, params)
cursor = await cls.getDB().execute(sql, params)
row = await cursor.fetchone()
return row["count"] if row else 0
except Exception as e:
+85
View File
@@ -0,0 +1,85 @@
from typing import Any, Optional
from zhenxun.services.log import logger
class CDBServiceLocator:
"""
数据库服务定位器
负责管理所有数据库服务实例,提供统一的访问接口
"""
m_pInstance: Optional["CDBServiceLocator"] = None
def __init__(self):
self.m_pServices: dict[str, Any] = {}
self.m_bInitialized = False
@classmethod
def getInstance(cls) -> "CDBServiceLocator":
"""
获取单例实例
"""
if cls.m_pInstance is None:
cls.m_pInstance = cls()
return cls.m_pInstance
def register(self, name: str, service: Any) -> None:
"""
注册服务实例
"""
if name in self.m_pServices:
logger.error(f"真寻农场服务 {name} 已经注册")
self.m_pServices[name] = service
def get(self, name: str) -> Any:
"""
获取服务实例
"""
if name not in self.m_pServices:
raise KeyError(f"服务 {name} 未注册")
return self.m_pServices[name]
def getPlantManager(self):
return self.get("plant")
def getUserManager(self):
return self.get("user")
def getUserSoilManager(self):
return self.get("userSoil")
def getUserPlantManager(self):
return self.get("userPlant")
def getUserSeedManager(self):
return self.get("userSeed")
def getUserItemManager(self):
return self.get("userItem")
def getUserStealManager(self):
return self.get("userSteal")
def getUserSignManager(self):
return self.get("userSign")
def getUserPlantCountManager(self):
return self.get("userPlantCount")
def markInitialized(self):
"""
标记初始化完成
"""
self.m_bInitialized = True
@property
def initialized(self) -> bool:
"""
检查是否已初始化
"""
return self.m_bInitialized
# 全局服务定位器实例
g_pDBlocator = CDBServiceLocator.getInstance()
+19 -10
View File
@@ -6,14 +6,16 @@ import aiosqlite
from zhenxun.configs.config import Config
from zhenxun.services.log import logger
from ...utils.config import g_bIsDebug, g_sPlantPath, g_sResourcePath
from ...utils.request import g_pRequestManager
from ...utils import config, getRequestManager
class CPlantManager:
def __init__(self):
self.m_sTableName = "plant"
self.m_bInitialized = False
try:
os.mkdir(g_sPlantPath)
os.mkdir(config.g_sPlantPath)
except FileExistsError:
pass
@@ -23,14 +25,14 @@ class CPlantManager:
async def init(self) -> bool:
try:
_ = os.path.exists(g_sPlantPath)
_ = os.path.exists(config.g_sPlantPath)
if g_bIsDebug:
if config.g_bIsDebug:
self.m_pDB = await aiosqlite.connect(
str(g_sPlantPath.parent / "plant-test.db")
str(config.g_sPlantPath.parent / "plant-test.db")
)
else:
self.m_pDB = await aiosqlite.connect(str(g_sPlantPath))
self.m_pDB = await aiosqlite.connect(str(config.g_sPlantPath))
self.m_pDB.row_factory = aiosqlite.Row
return True
@@ -38,6 +40,9 @@ class CPlantManager:
logger.warning("初始化植物数据库失败", e=e)
return False
async def initDB(self):
self.m_bInitialized = True
@asynccontextmanager
async def _transaction(self):
await self.m_pDB.execute("BEGIN;")
@@ -254,7 +259,7 @@ class CPlantManager:
for plant in plants:
name = plant["name"]
phaseCount = await self.getPlantPhaseNumberByName(name)
saveDir = os.path.join(g_sResourcePath, "plant", name)
saveDir = os.path.join(config.g_sResourcePath, "plant", name)
begin = 0 if plant["general"] == 0 else 1
for idx in range(begin, phaseCount + 1):
@@ -265,14 +270,18 @@ class CPlantManager:
continue
url = f"{baseUrl}/{name}/{idx}.png"
if not await g_pRequestManager.download(url, saveDir, f"{idx}.png"):
if not await getRequestManager().download(
url, saveDir, f"{idx}.png"
):
success = False
iconName = "icon.png"
iconPath = os.path.join(saveDir, iconName)
if not os.path.exists(iconPath):
iconUrl = f"{baseUrl}/{name}/{iconName}"
if not await g_pRequestManager.download(iconUrl, saveDir, iconName):
if not await getRequestManager().download(
iconUrl, saveDir, iconName
):
success = False
return success
+6 -3
View File
@@ -1,11 +1,13 @@
import math
from ...utils.tool import g_pToolManager
from ...utils import getToolManager
from .database import CSqlManager
class CUserDB(CSqlManager):
def __init__(self):
super().__init__()
self.m_sTableName = "user"
self.currencies: list[str] = ["point", "vipPoint"]
async def initDB(self):
@@ -21,6 +23,7 @@ class CUserDB(CSqlManager):
}
await self.ensureTableSchema("user", userInfo)
self.setInitialized()
async def initUserInfo(self, uid: str, name: str) -> bool:
"""初始化用户信息
@@ -32,7 +35,7 @@ class CUserDB(CSqlManager):
Returns:
bool: 是否成功初始化用户信息
"""
nowStr = g_pToolManager.dateTime().date().today().strftime("%Y-%m-%d")
nowStr = getToolManager().dateTime().date().today().strftime("%Y-%m-%d")
result = await self.insert(
"user",
@@ -125,7 +128,7 @@ class CUserDB(CSqlManager):
Returns:
bool: 是否成功更新农场名称
"""
safeName = g_pToolManager.sanitize_username(name)
safeName = getToolManager().sanitize_username(name)
if safeName == "神秘农夫":
return "error"
+16 -12
View File
@@ -4,8 +4,11 @@ from .database import CSqlManager
class CUserItemDB(CSqlManager):
@classmethod
async def initDB(cls):
def __init__(self):
super().__init__()
self.m_sTableName = "userItem"
async def initDB(self):
userItem = {
"uid": "TEXT NOT NULL", # 用户Uid
"item": "TEXT NOT NULL", # 物品名称
@@ -13,7 +16,8 @@ class CUserItemDB(CSqlManager):
"PRIMARY KEY": "(uid, item)",
}
await cls.ensureTableSchema("userItem", userItem)
await self.ensureTableSchema("userItem", userItem)
self.setInitialized()
@classmethod
async def getUserItemByName(cls, uid: str, item: str) -> int | None:
@@ -29,7 +33,7 @@ class CUserItemDB(CSqlManager):
if not uid or not item:
return None
try:
async with cls.m_pDB.execute(
async with cls.getDB().execute(
"SELECT count FROM userItem WHERE uid = ? AND item = ?", (uid, item)
) as cursor:
row = await cursor.fetchone()
@@ -51,7 +55,7 @@ class CUserItemDB(CSqlManager):
if not uid:
return {}
try:
cursor = await cls.m_pDB.execute(
cursor = await cls.getDB().execute(
"SELECT item, count FROM userItem WHERE uid = ?", (uid,)
)
rows = await cursor.fetchall()
@@ -75,7 +79,7 @@ class CUserItemDB(CSqlManager):
return False
try:
async with cls._transaction():
await cls.m_pDB.execute(
await cls.getDB().execute(
"DELETE FROM userItem WHERE uid = ? AND item = ?", (uid, item)
)
return True
@@ -100,11 +104,11 @@ class CUserItemDB(CSqlManager):
try:
async with cls._transaction():
if count <= 0:
await cls.m_pDB.execute(
await cls.getDB().execute(
"DELETE FROM userItem WHERE uid = ? AND item = ?", (uid, item)
)
else:
await cls.m_pDB.execute(
await cls.getDB().execute(
"UPDATE userItem SET count = ? WHERE uid = ? AND item = ?",
(count, uid, item),
)
@@ -129,7 +133,7 @@ class CUserItemDB(CSqlManager):
return False
try:
async with cls._transaction():
async with cls.m_pDB.execute(
async with cls.getDB().execute(
"SELECT count FROM userItem WHERE uid = ? AND item = ?", (uid, item)
) as cursor:
row = await cursor.fetchone()
@@ -137,18 +141,18 @@ class CUserItemDB(CSqlManager):
if row:
newCount = row[0] + count
if newCount <= 0:
await cls.m_pDB.execute(
await cls.getDB().execute(
"DELETE FROM userItem WHERE uid = ? AND item = ?",
(uid, item),
)
else:
await cls.m_pDB.execute(
await cls.getDB().execute(
"UPDATE userItem SET count = ? WHERE uid = ? AND item = ?",
(newCount, uid, item),
)
else:
if count > 0:
await cls.m_pDB.execute(
await cls.getDB().execute(
"INSERT INTO userItem (uid, item, count) VALUES (?, ?, ?)",
(uid, item, count),
)
+17 -13
View File
@@ -4,8 +4,11 @@ from .database import CSqlManager
class CUserPlantDB(CSqlManager):
@classmethod
async def initDB(cls):
def __init__(self):
super().__init__()
self.m_sTableName = "userPlant"
async def initDB(self):
userPlant = {
"uid": "TEXT NOT NULL", # 用户Uid
"plant": "TEXT NOT NULL", # 作物名称
@@ -14,7 +17,8 @@ class CUserPlantDB(CSqlManager):
"PRIMARY KEY": "(uid, plant)",
}
await cls.ensureTableSchema("userPlant", userPlant)
await self.ensureTableSchema("userPlant", userPlant)
self.setInitialized()
@classmethod
async def addUserPlantByUid(cls, uid: str, plant: str, count: int = 1) -> bool:
@@ -31,7 +35,7 @@ class CUserPlantDB(CSqlManager):
try:
async with cls._transaction():
# 检查是否已存在该作物
async with cls.m_pDB.execute(
async with cls.getDB().execute(
"SELECT count FROM userPlant WHERE uid = ? AND plant = ?",
(uid, plant),
) as cursor:
@@ -40,13 +44,13 @@ class CUserPlantDB(CSqlManager):
if row:
# 如果作物已存在,则更新数量
new_count = row[0] + count
await cls.m_pDB.execute(
await cls.getDB().execute(
"UPDATE userPlant SET count = ? WHERE uid = ? AND plant = ?",
(new_count, uid, plant),
)
else:
# 如果作物不存在,则插入新记录
await cls.m_pDB.execute(
await cls.getDB().execute(
"INSERT INTO userPlant (uid, plant, count) VALUES (?, ?, ?)",
(uid, plant, count),
)
@@ -65,7 +69,7 @@ class CUserPlantDB(CSqlManager):
Returns:
Dict[str, int]: 作物名称和数量
"""
cursor = await cls.m_pDB.execute(
cursor = await cls.getDB().execute(
"SELECT plant, count FROM userPlant WHERE uid=?", (uid,)
)
rows = await cursor.fetchall()
@@ -83,7 +87,7 @@ class CUserPlantDB(CSqlManager):
Optional[int]: 作物数量
"""
try:
async with cls.m_pDB.execute(
async with cls.getDB().execute(
"SELECT count FROM userPlant WHERE uid = ? AND plant = ?", (uid, plant)
) as cursor:
row = await cursor.fetchone()
@@ -104,7 +108,7 @@ class CUserPlantDB(CSqlManager):
bool: 是否存在
"""
try:
async with cls.m_pDB.execute(
async with cls.getDB().execute(
"SELECT * FROM userPlant WHERE uid = ? AND plant = ?", (uid, plant)
) as cursor:
row = await cursor.fetchone()
@@ -130,7 +134,7 @@ class CUserPlantDB(CSqlManager):
return await cls.deleteUserPlantByName(uid, plant)
async with cls._transaction():
await cls.m_pDB.execute(
await cls.getDB().execute(
"UPDATE userPlant SET count = ? WHERE uid = ? AND plant = ?",
(count, uid, plant),
)
@@ -153,7 +157,7 @@ class CUserPlantDB(CSqlManager):
"""
try:
async with cls._transaction():
await cls.m_pDB.execute(
await cls.getDB().execute(
"UPDATE userPlant SET isLock = ? WHERE uid = ? AND plant = ?",
(lock, uid, plant),
)
@@ -174,7 +178,7 @@ class CUserPlantDB(CSqlManager):
bool: 是否加锁
"""
try:
async with cls.m_pDB.execute(
async with cls.getDB().execute(
"SELECT isLock FROM userPlant WHERE uid = ? AND plant = ?", (uid, plant)
) as cursor:
row = await cursor.fetchone()
@@ -196,7 +200,7 @@ class CUserPlantDB(CSqlManager):
"""
try:
async with cls._transaction():
await cls.m_pDB.execute(
await cls.getDB().execute(
"DELETE FROM userPlant WHERE uid = ? AND plant = ?", (uid, plant)
)
return True
+15 -11
View File
@@ -4,8 +4,11 @@ from .database import CSqlManager
class CUserPlantCountDB(CSqlManager):
@classmethod
async def initDB(cls):
def __init__(self):
super().__init__()
self.m_sTableName = "userPlantCount"
async def initDB(self):
userPlantCount = {
"uid": "TEXT NOT NULL", # 用户Uid
"plant": "TEXT NOT NULL", # 植物名称
@@ -13,7 +16,8 @@ class CUserPlantCountDB(CSqlManager):
"PRIMARY KEY": "(uid, plant)",
}
await cls.ensureTableSchema("userPlantCount", userPlantCount)
await self.ensureTableSchema("userPlantCount", userPlantCount)
self.setInitialized()
@classmethod
async def addUserPlantCountByUid(cls, uid: str, plant: str, count: int = 1) -> bool:
@@ -29,7 +33,7 @@ class CUserPlantCountDB(CSqlManager):
"""
try:
async with cls._transaction():
async with cls.m_pDB.execute(
async with cls.getDB().execute(
"SELECT count FROM userPlantCount WHERE uid = ? AND plant = ?",
(uid, plant),
) as cursor:
@@ -37,19 +41,19 @@ class CUserPlantCountDB(CSqlManager):
if row:
newCount = row[0] + count
await cls.m_pDB.execute(
await cls.getDB().execute(
"UPDATE userPlantCount SET count = ? WHERE uid = ? AND plant = ?",
(newCount, uid, plant),
)
else:
newCount = count
await cls.m_pDB.execute(
await cls.getDB().execute(
"INSERT INTO userPlantCount (uid, plant, count) VALUES (?, ?, ?)",
(uid, plant, count),
)
if newCount <= 0:
await cls.m_pDB.execute(
await cls.getDB().execute(
"DELETE FROM userPlantCount WHERE uid = ? AND plant = ?",
(uid, plant),
)
@@ -69,7 +73,7 @@ class CUserPlantCountDB(CSqlManager):
dict: 植物信息
"""
cursor = await cls.m_pDB.execute(
cursor = await cls.getDB().execute(
"SELECT plant, count FROM userPlantCount WHERE uid=?", (uid,)
)
rows = await cursor.fetchall()
@@ -86,7 +90,7 @@ class CUserPlantCountDB(CSqlManager):
Returns:
int: 收获次数
"""
cursor = await cls.m_pDB.execute(
cursor = await cls.getDB().execute(
"SELECT count FROM userPlantCount WHERE uid = ? AND plant = ?",
(uid, plant),
)
@@ -110,7 +114,7 @@ class CUserPlantCountDB(CSqlManager):
return await cls.deleteUserPlantCountByName(uid, plant)
async with cls._transaction():
await cls.m_pDB.execute(
await cls.getDB().execute(
"UPDATE userPlantCount SET count = ? WHERE uid = ? AND plant = ?",
(count, uid, plant),
)
@@ -132,7 +136,7 @@ class CUserPlantCountDB(CSqlManager):
"""
try:
async with cls._transaction():
await cls.m_pDB.execute(
await cls.getDB().execute(
"DELETE FROM userPlantCount WHERE uid = ? AND plant = ?",
(uid, plant),
)
+18 -14
View File
@@ -4,8 +4,11 @@ from .database import CSqlManager
class CUserSeedDB(CSqlManager):
@classmethod
async def initDB(cls):
def __init__(self):
super().__init__()
self.m_sTableName = "userSeed"
async def initDB(self):
userSeed = {
"uid": "TEXT NOT NULL", # 用户Uid
"seed": "TEXT NOT NULL", # 种子名称
@@ -13,7 +16,8 @@ class CUserSeedDB(CSqlManager):
"PRIMARY KEY": "(uid, seed)",
}
await cls.ensureTableSchema("userSeed", userSeed)
await self.ensureTableSchema("userSeed", userSeed)
self.setInitialized()
@classmethod
async def addUserSeedByUid(cls, uid: str, seed: str, count: int = 1) -> bool:
@@ -29,26 +33,26 @@ class CUserSeedDB(CSqlManager):
"""
try:
async with cls._transaction():
async with cls.m_pDB.execute(
async with cls.getDB().execute(
"SELECT count FROM userSeed WHERE uid = ? AND seed = ?", (uid, seed)
) as cursor:
row = await cursor.fetchone()
if row:
newCount = row[0] + count
await cls.m_pDB.execute(
await cls.getDB().execute(
"UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?",
(newCount, uid, seed),
)
else:
newCount = count
await cls.m_pDB.execute(
await cls.getDB().execute(
"INSERT INTO userSeed (uid, seed, count) VALUES (?, ?, ?)",
(uid, seed, count),
)
if newCount <= 0:
await cls.m_pDB.execute(
await cls.getDB().execute(
"DELETE FROM userSeed WHERE uid = ? AND seed = ?", (uid, seed)
)
return True
@@ -66,7 +70,7 @@ class CUserSeedDB(CSqlManager):
if existing is not None:
await cls._updateUserSeedByName(uid, seed, newCount)
else:
await cls.m_pDB.execute(
await cls.getDB().execute(
"INSERT INTO userSeed (uid, seed, count) VALUES (?, ?, ?)",
(uid, seed, newCount),
)
@@ -92,7 +96,7 @@ class CUserSeedDB(CSqlManager):
"""
try:
async with cls.m_pDB.execute(
async with cls.getDB().execute(
"SELECT count FROM userSeed WHERE uid = ? AND seed = ?", (uid, seed)
) as cursor:
row = await cursor.fetchone()
@@ -112,7 +116,7 @@ class CUserSeedDB(CSqlManager):
dict: 种子信息
"""
cursor = await cls.m_pDB.execute(
cursor = await cls.getDB().execute(
"SELECT seed, count FROM userSeed WHERE uid=?", (uid,)
)
rows = await cursor.fetchall()
@@ -135,7 +139,7 @@ class CUserSeedDB(CSqlManager):
return await cls.deleteUserSeedByName(uid, seed)
async with cls._transaction():
await cls.m_pDB.execute(
await cls.getDB().execute(
"UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?",
(count, uid, seed),
)
@@ -161,7 +165,7 @@ class CUserSeedDB(CSqlManager):
return await cls.deleteUserSeedByName(uid, seed)
async with cls._transaction():
await cls.m_pDB.execute(
await cls.getDB().execute(
"UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?",
(count, uid, seed),
)
@@ -183,7 +187,7 @@ class CUserSeedDB(CSqlManager):
"""
try:
async with cls._transaction():
await cls.m_pDB.execute(
await cls.getDB().execute(
"DELETE FROM userSeed WHERE uid = ? AND seed = ?", (uid, seed)
)
return True
@@ -203,7 +207,7 @@ class CUserSeedDB(CSqlManager):
bool: 是否成功
"""
try:
await cls.m_pDB.execute(
await cls.getDB().execute(
"DELETE FROM userSeed WHERE uid = ? AND seed = ?", (uid, seed)
)
return True
+26 -23
View File
@@ -5,16 +5,16 @@ import random
from zhenxun.services.log import logger
from zhenxun.utils._build_image import BuildImage
from ...utils.config import g_bIsDebug
from ...utils.json import g_pJsonManager
from ...utils.tool import g_pToolManager
from ..dbService import g_pDBService
from ...utils import config, getJsonManager, getToolManager
from .database import CSqlManager
class CUserSignDB(CSqlManager):
@classmethod
async def initDB(cls):
def __init__(self):
super().__init__()
self.m_sTableName = "userSign"
async def initDB(self):
# userSignLog 表结构,每条为一次签到事件
userSignLog = {
"uid": "TEXT NOT NULL", # 用户ID
@@ -38,8 +38,9 @@ class CUserSignDB(CSqlManager):
"updatedAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime'))", # 更新时间 # noqa: E501
}
await cls.ensureTableSchema("userSignLog", userSignLog)
await cls.ensureTableSchema("userSignSummary", userSignSummary)
await self.ensureTableSchema("userSignLog", userSignLog)
await self.ensureTableSchema("userSignSummary", userSignSummary)
self.setInitialized()
@classmethod
async def getUserSignRewardByDate(cls, uid: str, date: str) -> tuple[int, int]:
@@ -54,7 +55,7 @@ class CUserSignDB(CSqlManager):
"""
try:
async with cls._transaction():
async with cls.m_pDB.execute(
async with cls.getDB().execute(
"SELECT exp, point FROM userSignLog WHERE uid=? AND signDate=?",
(uid, date),
) as cursor:
@@ -85,7 +86,7 @@ class CUserSignDB(CSqlManager):
try:
sql = "SELECT COUNT(*) FROM userSignLog WHERE uid=? AND signDate LIKE ?"
param = f"{monthStr}-%"
async with cls.m_pDB.execute(sql, (uid, param)) as cursor:
async with cls.getDB().execute(sql, (uid, param)) as cursor:
row = await cursor.fetchone()
return row[0] if row else 0
except Exception as e:
@@ -105,7 +106,7 @@ class CUserSignDB(CSqlManager):
"""
try:
sql = "SELECT 1 FROM userSignLog WHERE uid=? AND signDate=? LIMIT 1"
async with cls.m_pDB.execute(sql, (uid, signDate)) as cursor:
async with cls.getDB().execute(sql, (uid, signDate)) as cursor:
row = await cursor.fetchone()
return row is not None
except Exception as e:
@@ -124,19 +125,21 @@ class CUserSignDB(CSqlManager):
int: 0: 签到失败 1: 签到成功 2: 重复签到
"""
try:
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if not player:
return 0
if not signDate:
signDate = g_pToolManager.dateTime().date().today().strftime("%Y-%m-%d")
signDate = (
getToolManager().dateTime().date().today().strftime("%Y-%m-%d")
)
if await cls.hasSigned(uid, signDate):
return 2
todayStr = g_pToolManager.dateTime().date().today().strftime("%Y-%m-%d")
todayStr = getToolManager().dateTime().date().today().strftime("%Y-%m-%d")
isSupplement = 0 if signDate == todayStr else 1
sign = await g_pJsonManager.getSign()
sign = await getJsonManager().getSign()
expMax, expMin, pointMax, pointMin = [
sign.get(key, default)
@@ -153,12 +156,12 @@ class CUserSignDB(CSqlManager):
vipPoint = 0
async with cls._transaction():
await cls.m_pDB.execute(
await cls.getDB().execute(
"INSERT INTO userSignLog (uid, signDate, isSupplement, exp, point) VALUES (?, ?, ?, ?, ?)",
(uid, signDate, isSupplement, exp, point),
)
cursor = await cls.m_pDB.execute(
cursor = await cls.getDB().execute(
"SELECT * FROM userSignSummary WHERE uid=?", (uid,)
)
row = await cursor.fetchone()
@@ -171,7 +174,7 @@ class CUserSignDB(CSqlManager):
else 1
)
prevDate = (
g_pToolManager.dateTime().strptime(signDate, "%Y-%m-%d")
getToolManager().dateTime().strptime(signDate, "%Y-%m-%d")
- timedelta(days=1)
).strftime("%Y-%m-%d")
continuousDays = (
@@ -184,7 +187,7 @@ class CUserSignDB(CSqlManager):
if isSupplement
else row["supplementCount"]
)
await cls.m_pDB.execute(
await cls.getDB().execute(
"""
UPDATE userSignSummary
SET totalSignDays=totalSignDays+1,
@@ -206,7 +209,7 @@ class CUserSignDB(CSqlManager):
)
else:
monthSignDays = 1
await cls.m_pDB.execute(
await cls.getDB().execute(
"""
INSERT INTO userSignSummary
(uid, totalSignDays, currentMonth, monthSignDays, lastSignDate, continuousDays, supplementCount)
@@ -233,9 +236,9 @@ class CUserSignDB(CSqlManager):
plant = reward.get("plant", {})
if plant:
for key, value in plant.items():
await g_pDBService.userSeed.addUserSeedByUid(uid, key, value)
await cls.getUserSeedManager().addUserSeedByUid(uid, key, value)
if g_bIsDebug:
if config.g_bIsDebug:
exp += 9999
# 向数据库更新
@@ -268,7 +271,7 @@ class CUserSignDB(CSqlManager):
monthStr = f"{year:04d}-{month:02d}"
try:
sql = "SELECT signDate FROM userSignLog WHERE uid=? AND signDate LIKE ?"
async with cls.m_pDB.execute(sql, (uid, f"{monthStr}-%")) as cursor:
async with cls.getDB().execute(sql, (uid, f"{monthStr}-%")) as cursor:
rows = await cursor.fetchall()
signedDays = {int(r[0][-2:]) for r in rows if r[0][-2:].isdigit()}
except Exception as e:
+33 -31
View File
@@ -3,15 +3,16 @@ import re
from zhenxun.services.log import logger
from ...utils.config import g_bIsDebug
from ...utils.tool import g_pToolManager
from ..dbService import g_pDBService
from ...utils import config, getToolManager
from .database import CSqlManager
class CUserSoilDB(CSqlManager):
@classmethod
async def initDB(cls):
def __init__(self):
super().__init__()
self.m_sTableName = "userSoil"
async def initDB(self):
userSoil = {
"uid": "TEXT NOT NULL",
"soilIndex": "INTEGER NOT NULL", # 地块索引从1开始
@@ -29,7 +30,8 @@ class CUserSoilDB(CSqlManager):
"PRIMARY KEY": "(uid, soilIndex)",
}
await cls.ensureTableSchema("userSoil", userSoil)
await self.ensureTableSchema("userSoil", userSoil)
self.setInitialized()
@classmethod
async def nextPhase(cls, uid: str, soilIndex: int):
@@ -38,7 +40,7 @@ class CUserSoilDB(CSqlManager):
Args:
soilIndex (int): 地块索引 从1开始
"""
if not g_bIsDebug:
if not config.g_bIsDebug:
return
soilInfo = await cls.getUserSoil(uid, soilIndex)
@@ -46,13 +48,15 @@ class CUserSoilDB(CSqlManager):
if not soilInfo:
return
plantInfo = await g_pDBService.plant.getPlantByName(soilInfo["plantName"])
plantInfo = await cls.getPlantManager().getPlantByName(soilInfo["plantName"])
if not plantInfo:
return
currentTime = g_pToolManager.dateTime().now().timestamp()
phaseList = await g_pDBService.plant.getPlantPhaseByName(soilInfo["plantName"])
currentTime = getToolManager().dateTime().now().timestamp()
phaseList = await cls.getPlantManager().getPlantPhaseByName(
soilInfo["plantName"]
)
if currentTime >= soilInfo["matureTime"]:
return
@@ -88,11 +92,11 @@ class CUserSoilDB(CSqlManager):
if not plantName:
return
plantInfo = await g_pDBService.plant.getPlantByName(plantName)
plantInfo = await cls.getPlantManager().getPlantByName(plantName)
if not plantInfo:
return
currentTime = int(g_pToolManager.dateTime().now().timestamp())
currentTime = int(getToolManager().dateTime().now().timestamp())
# 如果当前时间已经超过或等于成熟时间,则作物已成熟或可收获
if currentTime >= soilInfo["matureTime"]:
return
@@ -110,7 +114,7 @@ class CUserSoilDB(CSqlManager):
Returns:
dict: 包含字段名-值的字典; 若无数据则返回空字典
"""
cursor = await cls.m_pDB.execute("SELECT * FROM soil WHERE uid = ?", (uid,))
cursor = await cls.getDB().execute("SELECT * FROM soil WHERE uid = ?", (uid,))
row = await cursor.fetchone()
if not row:
@@ -129,7 +133,7 @@ class CUserSoilDB(CSqlManager):
None
"""
async with cls._transaction():
await cls.m_pDB.execute(
await cls.getDB().execute(
"""
INSERT INTO userSoil
(uid, soilIndex, plantName, plantTime, matureTime,
@@ -164,7 +168,7 @@ class CUserSoilDB(CSqlManager):
Returns:
None
"""
await cls.m_pDB.execute(
await cls.getDB().execute(
"""
INSERT INTO userSoil
(uid, soilIndex, plantName, plantTime, matureTime,
@@ -201,7 +205,7 @@ class CUserSoilDB(CSqlManager):
dict: 记录存在返回字段-值字典,否则返回 None
"""
async with cls._transaction():
cursor = await cls.m_pDB.execute(
cursor = await cls.getDB().execute(
"SELECT * FROM userSoil WHERE uid = ? AND soilIndex = ?",
(uid, soilIndex),
)
@@ -222,7 +226,7 @@ class CUserSoilDB(CSqlManager):
Returns:
dict | None: 记录存在返回字段-值字典,否则返回 None
"""
cursor = await cls.m_pDB.execute(
cursor = await cls.getDB().execute(
"SELECT * FROM userSoil WHERE uid = ? AND soilIndex = ?",
(uid, soilIndex),
)
@@ -244,7 +248,7 @@ class CUserSoilDB(CSqlManager):
int: 符合条件的土地数量
"""
async with cls._transaction():
cursor = await cls.m_pDB.execute(
cursor = await cls.getDB().execute(
"SELECT COUNT(*) FROM userSoil WHERE uid = ? AND soilLevel = ?",
(uid, soilLevel),
)
@@ -265,7 +269,7 @@ class CUserSoilDB(CSqlManager):
None
"""
async with cls._transaction():
await cls.m_pDB.execute(
await cls.getDB().execute(
f"UPDATE userSoil SET {field} = ? WHERE uid = ? AND soilIndex = ?",
(value, uid, soilIndex),
)
@@ -283,7 +287,7 @@ class CUserSoilDB(CSqlManager):
Returns:
None
"""
await cls.m_pDB.execute(
await cls.getDB().execute(
f"UPDATE userSoil SET {field} = ? WHERE uid = ? AND soilIndex = ?",
(value, uid, soilIndex),
)
@@ -331,7 +335,7 @@ class CUserSoilDB(CSqlManager):
try:
async with cls._transaction():
await cls.m_pDB.execute(sql, tuple(values))
await cls.getDB().execute(sql, tuple(values))
return True
except Exception as e:
logger.error(f"批量更新土地字段失败: {e}")
@@ -349,7 +353,7 @@ class CUserSoilDB(CSqlManager):
None
"""
async with cls._transaction():
await cls.m_pDB.execute(
await cls.getDB().execute(
"DELETE FROM userSoil WHERE uid = ? AND soilIndex = ?", (uid, soilIndex)
)
@@ -364,7 +368,7 @@ class CUserSoilDB(CSqlManager):
Returns:
None
"""
await cls.m_pDB.execute(
await cls.getDB().execute(
"DELETE FROM userSoil WHERE uid = ? AND soilIndex = ?", (uid, soilIndex)
)
@@ -386,12 +390,12 @@ class CUserSoilDB(CSqlManager):
return False
# 获取植物配置""" """
plantCfg = await g_pDBService.plant.getPlantByName(plantName)
plantCfg = await cls.getPlantManager().getPlantByName(plantName)
if not plantCfg:
logger.error(f"未知植物: {plantName}")
return False
nowTs = int(g_pToolManager.dateTime().now().timestamp())
nowTs = int(getToolManager().dateTime().now().timestamp())
time = int(plantCfg.get("time", 0))
percent = await cls.getSoilLevelTime(soilInfo.get("soilLevel", 0))
@@ -413,11 +417,9 @@ class CUserSoilDB(CSqlManager):
base_name = plantName[len(m.group(0)) :]
# 只有当存在一星升级配置时才尝试按收获次数升级
if await g_pDBService.plant.existsPlant("一星" + base_name):
harvestCounts = (
await g_pDBService.userPlantCount.getUserPlantCountByPlantName(
uid, base_name
)
if await cls.getPlantManager().existsPlant("一星" + base_name):
harvestCounts = await cls.getUserPlantCountManager().getUserPlantCountByPlantName(
uid, base_name
)
# 根据阈值设定最高星级(避免重复拼接)
prefix = ""
@@ -455,7 +457,7 @@ class CUserSoilDB(CSqlManager):
@classmethod
async def getUserSoilStatus(cls, uid: str, soilIndex: int) -> str:
status = []
soilInfo = await g_pDBService.userSoil.getUserSoil(uid, soilIndex)
soilInfo = await cls.getUserSoilManager().getUserSoil(uid, soilIndex)
if not soilInfo:
return ""
+15 -11
View File
@@ -4,8 +4,11 @@ from .database import CSqlManager
class CUserStealDB(CSqlManager):
@classmethod
async def initDB(cls):
def __init__(self):
super().__init__()
self.m_sTableName = "userSteal"
async def initDB(self):
userSteal = {
"uid": "TEXT NOT NULL", # 被偷用户Uid
"soilIndex": "INTEGER NOT NULL", # 被偷的地块索引 从1开始
@@ -14,7 +17,8 @@ class CUserStealDB(CSqlManager):
"stealTime": "INTEGER NOT NULL", # 被偷时间
"PRIMARY KEY": "(uid, soilIndex, stealerUid)",
}
await cls.ensureTableSchema("userSteal", userSteal)
await self.ensureTableSchema("userSteal", userSteal)
self.setInitialized()
@classmethod
async def addStealRecord(
@@ -34,7 +38,7 @@ class CUserStealDB(CSqlManager):
"""
try:
async with cls._transaction():
await cls.m_pDB.execute(
await cls.getDB().execute(
'INSERT INTO "userSteal"(uid, soilIndex, stealerUid, stealCount, stealTime) VALUES(?, ?, ?, ?, ?);',
(uid, soilIndex, stealerUid, stealCount, stealTime),
)
@@ -55,7 +59,7 @@ class CUserStealDB(CSqlManager):
"""
try:
async with cls._transaction():
cursor = await cls.m_pDB.execute(
cursor = await cls.getDB().execute(
'SELECT soilIndex, stealerUid, stealCount, stealTime FROM "userSteal" WHERE uid=?;',
(uid,),
)
@@ -83,7 +87,7 @@ class CUserStealDB(CSqlManager):
"""
try:
async with cls._transaction():
cursor = await cls.m_pDB.execute(
cursor = await cls.getDB().execute(
'SELECT stealerUid, stealCount, stealTime FROM "userSteal" WHERE uid=? AND soilIndex=?;',
(uid, soilIndex),
)
@@ -115,7 +119,7 @@ class CUserStealDB(CSqlManager):
"""
try:
async with cls._transaction():
cursor = await cls.m_pDB.execute(
cursor = await cls.getDB().execute(
'SELECT SUM(stealCount) FROM "userSteal" WHERE uid=? AND soilIndex=?;',
(uid, soilIndex),
)
@@ -138,7 +142,7 @@ class CUserStealDB(CSqlManager):
"""
try:
async with cls._transaction():
cursor = await cls.m_pDB.execute(
cursor = await cls.getDB().execute(
'SELECT COUNT(DISTINCT stealerUid) FROM "userSteal" WHERE uid=? AND soilIndex=?;',
(uid, soilIndex),
)
@@ -162,7 +166,7 @@ class CUserStealDB(CSqlManager):
"""
try:
async with cls._transaction():
cursor = await cls.m_pDB.execute(
cursor = await cls.getDB().execute(
'SELECT 1 FROM "userSteal" WHERE uid=? AND soilIndex=? AND stealerUid=? LIMIT 1;',
(uid, soilIndex, stealerUid),
)
@@ -190,7 +194,7 @@ class CUserStealDB(CSqlManager):
"""
try:
async with cls._transaction():
await cls.m_pDB.execute(
await cls.getDB().execute(
'UPDATE "userSteal" SET stealCount=?, stealTime=? WHERE uid=? AND soilIndex=? AND stealerUid=?;',
(stealCount, stealTime, uid, soilIndex, stealerUid),
)
@@ -212,7 +216,7 @@ class CUserStealDB(CSqlManager):
"""
try:
async with cls._transaction():
await cls.m_pDB.execute(
await cls.getDB().execute(
'DELETE FROM "userSteal" WHERE uid=? AND soilIndex=?;',
(uid, soilIndex),
)
+102 -31
View File
@@ -1,44 +1,115 @@
import asyncio
from typing import Any
from zhenxun.services.log import logger
from .database import (
CPlantManager,
CUserDB,
CUserItemDB,
CUserPlantCountDB,
CUserPlantDB,
CUserSeedDB,
CUserSignDB,
CUserSoilDB,
CUserStealDB,
g_pDBlocator,
)
class CDBService:
"""
数据库服务管理器
负责初始化和协调所有数据库服务
"""
def __init__(self):
self.m_manager: dict[str, Any] = {}
self.m_bInitialized = False
async def init(self):
from .database.plant import CPlantManager
from .database.user import CUserDB
from .database.userItem import CUserItemDB
from .database.userPlant import CUserPlantDB
from .database.userPlantCount import CUserPlantCountDB
from .database.userSeed import CUserSeedDB
from .database.userSign import CUserSignDB
from .database.userSoil import CUserSoilDB
from .database.userSteal import CUserStealDB
if self.m_bInitialized:
logger.warning("真寻农场数据库服务已初始化")
return
self.plant = CPlantManager()
await self.plant.init()
m_manager = {
"plant": CPlantManager(),
"user": CUserDB(),
"userSoil": CUserSoilDB(),
"userPlant": CUserPlantDB(),
"userSeed": CUserSeedDB(),
"userItem": CUserItemDB(),
"userSteal": CUserStealDB(),
"userSign": CUserSignDB(),
"userPlantCount": CUserPlantCountDB(),
}
self.user = CUserDB()
await self.user.initDB()
for name, manager in m_manager.items():
g_pDBlocator.register(name, manager)
self.m_manager[name] = manager
self.userSoil = CUserSoilDB()
await self.userSoil.initDB()
tasks = []
for name, manager in self.m_manager.items():
tasks.append(manager.init())
tasks.append(manager.initDB())
self.userPlant = CUserPlantDB()
await self.userPlant.initDB()
await asyncio.gather(*tasks)
self.userSeed = CUserSeedDB()
await self.userSeed.initDB()
g_pDBlocator.markInitialized()
self.m_bInitialized = True
self.userItem = CUserItemDB()
await self.userItem.initDB()
self.userSteal = CUserStealDB()
await self.userSteal.initDB()
self.userSign = CUserSignDB()
await self.userSign.initDB()
self.userPlantCount = CUserPlantCountDB()
await self.userPlantCount.initDB()
logger.debug("真寻农场数据库服务初始化完成")
async def cleanup(self):
await self.plant.cleanup()
task = []
for manager in self.m_manager.values():
if hasattr(manager, "cleanup"):
task.append(manager.cleanup())
await asyncio.gather(*task)
self.m_manager.clear()
self.m_bInitialized = False
@property
def plant(self):
return self.m_manager["plant"]
@property
def user(self):
return self.m_manager["user"]
@property
def userSoil(self):
return self.m_manager["userSoil"]
@property
def userPlant(self):
return self.m_manager["userPlant"]
@property
def userSeed(self):
return self.m_manager["userSeed"]
@property
def userItem(self):
return self.m_manager["userItem"]
@property
def userSteal(self):
return self.m_manager["userSteal"]
@property
def userSign(self):
return self.m_manager["userSign"]
@property
def userPlantCount(self):
return self.m_manager["userPlantCount"]
@property
def initialized(self) -> bool:
return self.m_bInitialized
g_pDBService = CDBService()
+85 -440
View File
@@ -5,16 +5,12 @@ import re
from zhenxun.configs.config import Config
from zhenxun.models.user_console import UserConsole
from zhenxun.services.log import logger
from zhenxun.utils._build_image import BuildImage
from zhenxun.utils.enum import GoldHandle
from zhenxun.utils.image_utils import ImageTemplate
from zhenxun.utils.platform import PlatformUtils
from ..core.dbService import g_pDBService
from ..event.event import g_pEventManager
from ..utils.config import g_bIsDebug, g_iSoilLevelMax, g_sResourcePath, g_sTranslation
from ..utils.json import g_pJsonManager
from ..utils.tool import g_pToolManager
from ..event import g_pEventManager
from ..utils import config, getJsonManager, getToolManager
class CFarmManager:
@@ -50,372 +46,14 @@ class CFarmManager:
)
point = num * pro
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if not player:
return g_sTranslation["basic"]["error"]
return config.g_sTranslation["basic"]["error"]
await player.addPoint("point", int(point))
return f"充值{point}农场币成功,手续费{tax}金币,当前农场币:{player.user.get('point', 0)}"
@classmethod
async def drawFarmByUid(cls, uid: str) -> bytes:
"""绘制用户农场
Args:
uid (str): 用户UID
Returns:
bytes: 返回绘制结果
"""
img = BuildImage(background=g_sResourcePath / "background/background.jpg")
soil = await g_pJsonManager.getSoil()
soilSize = soil["size"]
soilPos = soil["soil"]
grass = BuildImage(background=g_sResourcePath / "soil/草土地.png")
await grass.resize(0, soilSize[0], soilSize[1])
player = await g_pToolManager.getPlayerByUid(uid)
if not player:
return img.pic2bytes()
soilUnlock = int(player.user.get("soil", 3))
x = 0
y = 0
isFirstExpansion = True # 首次添加扩建图片
isFirstRipe = True
plant = None
for index in range(0, 30):
x = soilPos[str(index + 1)]["x"]
y = soilPos[str(index + 1)]["y"]
# 如果土地已经到达对应等级
if index < soilUnlock:
soilUrl = ""
# TODO 缺少判断用户土地资源状况
soilInfo = await g_pDBService.userSoil.getUserSoil(uid, index + 1)
if not soilInfo:
soilUrl = "soil/普通土地.png"
else:
soilLevel = soilInfo.get("soilLevel", 0)
if soilLevel == 1:
soilUrl = "soil/红土地.png"
elif soilLevel == 2:
soilUrl = "soil/黑土地.png"
elif soilLevel == 3:
soilUrl = "soil/金土地.png"
else:
soilUrl = "soil/普通土地.png"
soil = BuildImage(background=g_sResourcePath / soilUrl)
await soil.resize(0, soilSize[0], soilSize[1])
await img.paste(soil, (x, y))
isPlant, plant, isRipe, offsetX, offsetY = await cls.drawSoilPlant(
uid, index + 1
)
if isPlant:
await img.paste(
plant,
(
x + soilSize[0] // 2 - plant.width // 2 + offsetX,
y + soilSize[1] // 2 - plant.height // 2 + offsetY,
),
)
# 1700 275
# 首次添加可收获图片
if isRipe and isFirstRipe:
ripe = BuildImage(
background=g_sResourcePath / "background/ripe.png"
)
await img.paste(
ripe,
(x + soilSize[0] // 2 - ripe.width // 2, y - ripe.height // 2),
)
isFirstRipe = False
else:
await img.paste(grass, (x, y))
if isFirstExpansion:
isFirstExpansion = False
# 首次添加扩建图片
expansion = BuildImage(
background=g_sResourcePath / "background/expansion.png"
)
await expansion.resize(0, 69, 69)
await img.paste(
expansion,
(
x + soilSize[0] // 2 - expansion.width // 2,
y + soilSize[1] // 2 - expansion.height,
),
)
# 左上角绘制用户信息
# 头像
image = await PlatformUtils.get_user_avatar(uid, "qq")
if image:
avatar = BuildImage(background=image)
await avatar.resize(0, 140, 150)
await img.paste(avatar, (125, 85))
# 头像框
frame = BuildImage(background=g_sResourcePath / "background/frame.png")
await img.paste(frame, (75, 44))
# 用户名
nameImg = await BuildImage.build_text_image(
player.user["name"], size=24, font_color=(77, 35, 4)
)
await img.paste(nameImg, (300, 92))
# 经验值
level = await player.getUserLevel()
beginX = 309
endX = 627
# 绘制宽度计算公式为 (当前经验值 / 经验值上限) * 宽度
width = int((level[2] / level[1]) * (endX - beginX))
await img.rectangle((beginX, 188, beginX + width, 222), (171, 194, 41))
expImg = await BuildImage.build_text_image(
f"{level[2]} / {level[1]}", size=24, font_color=(102, 120, 19)
)
await img.paste(expImg, (390, 193))
# 等级
levelImg = await BuildImage.build_text_image(
str(level[0]), size=32, font_color=(214, 111, 1)
)
await img.paste(levelImg, (660, 187))
# 金币
pointImg = await BuildImage.build_text_image(
str(player.user["point"]), size=24, font_color=(253, 253, 253)
)
await img.paste(pointImg, (330, 255))
# 点券 TODO
bondsImg = await BuildImage.build_text_image(
"0", size=24, font_color=(253, 253, 253)
)
await img.paste(bondsImg, (570, 255))
# 清晰度
definition = Config.get_config("zhenxun_plugin_farm", "绘制农场清晰度")
if definition == "medium":
await img.resize(0.6)
elif definition == "hight":
await img.resize(0.8)
elif definition == "original":
pass
else:
await img.resize(0.4)
return img.pic2bytes()
@classmethod
async def drawDetailFarmByUid(cls, uid: str) -> list:
info = []
farm = await cls.drawFarmByUid(uid)
player = await g_pToolManager.getPlayerByUid(uid)
if not player:
return info
info.append(BuildImage.open(farm))
dataList = []
columnName = [
"-",
"土地ID",
"土地等级",
"作物名称",
"成熟时间",
"土地状态",
"被偷数量",
"剩余产出",
]
icon = ""
soilNumber = player.user.get("soil", 3)
for i in range(1, soilNumber + 1):
soilInfo = await g_pDBService.userSoil.getUserSoil(uid, i)
if soilInfo:
match soilInfo.get("soilLevel", 0):
case 1:
name = "红土地.png"
case 2:
name = "黑土地.png"
case 3:
name = "金土地.png"
case _:
name = "普通土地.png"
iconPath = g_sResourcePath / "soil" / name
if iconPath.exists():
icon = (iconPath, 33, 33)
plantName = soilInfo.get("plantName", "-")
if plantName == "-":
matureTime = "-"
soilStatus = "-"
totalNumber = "-"
plantNumber = "-"
else:
matureTime = (
g_pToolManager.dateTime()
.fromtimestamp(int(soilInfo.get("matureTime", 0)))
.strftime("%Y-%m-%d %H:%M:%S")
)
soilStatus = await g_pDBService.userSoil.getUserSoilStatus(uid, i)
totalNumber = await g_pDBService.userSteal.getTotalStolenCount(
uid, i
)
planInfo = await g_pDBService.plant.getPlantByName(plantName)
if not planInfo:
plantNumber = "None"
else:
plantNumber = f"{planInfo['harvest'] - totalNumber}"
dataList.append(
[
icon,
i,
await g_pDBService.userSoil.getSoilLevelText(
soilInfo["soilLevel"]
),
plantName,
matureTime,
soilStatus,
totalNumber,
plantNumber,
]
)
if len(dataList) >= 15:
result = await ImageTemplate.table_page(
"土地详细信息",
"",
columnName,
dataList,
)
info.append(result.copy())
dataList.clear()
if i >= soilNumber:
result = await ImageTemplate.table_page(
"土地详细信息",
"",
columnName,
dataList,
)
info.append(result.copy())
dataList.clear()
return info
@classmethod
async def drawSoilPlant(
cls, uid: str, soilIndex: int
) -> tuple[bool, BuildImage, bool, int, int]:
"""绘制植物资源
Args:
uid (str): 用户Uid
soilIndex (int): 土地索引 从1开始
Returns:
tuple[bool, BuildImage]: [绘制是否成功,资源图片, 是否成熟]
"""
plant = None
soilInfo = await g_pDBService.userSoil.getUserSoil(uid, soilIndex)
if not soilInfo:
return False, None, False, 0, 0 # type: ignore
# 是否枯萎
if int(soilInfo.get("wiltStatus", 0)) == 1:
plant = BuildImage(background=g_sResourcePath / "plant/basic/9.png")
await plant.resize(0, 150, 212)
return True, plant, False, 0, 0
# 获取作物详细信息
plantInfo = await g_pDBService.plant.getPlantByName(soilInfo["plantName"])
if not plantInfo:
logger.error(f"绘制植物资源失败: {soilInfo['plantName']}")
return False, None, False, 0, 0 # type: ignore
offsetX = plantInfo.get("officX", 0)
offsetY = plantInfo.get("officY", 0)
offsetW = plantInfo.get("officW", 0)
offsetH = plantInfo.get("officH", 0)
currentTime = g_pToolManager.dateTime().now().timestamp()
phaseList = await g_pDBService.plant.getPlantPhaseByName(soilInfo["plantName"])
# 如果当前时间大于成熟时间 说明作物成熟
if currentTime >= soilInfo["matureTime"]:
plant = BuildImage(
background=g_sResourcePath
/ f"plant/{soilInfo['plantName']}/{len(phaseList)}.png"
)
return True, plant, True, offsetX, offsetY
else:
# 如果是多阶段作物 且没有成熟 #早期思路 多阶段作物 直接是倒数第二阶段图片
# if soilInfo["harvestCount"] >= 1:
# plant = BuildImage(
# background=g_sResourcePath
# / f"plant/{soilInfo['plantName']}/{plantInfo['phase'] - 1}.png"
# )
# return True, plant, False, offsetX, offsetY
# 如果没有成熟 则根据当前阶段进行绘制
elapsedTime = currentTime - soilInfo["plantTime"]
currentStage = currentStage = sum(
1 for thr in phaseList if elapsedTime >= thr
)
if currentStage <= 0:
if not plantInfo["general"]:
plant = BuildImage(
background=g_sResourcePath
/ f"plant/{soilInfo['plantName']}/0.png"
)
else:
plant = BuildImage(background=g_sResourcePath / "plant/basic/0.png")
await plant.resize(0, 35 + offsetW, 58 + offsetH)
else:
plant = BuildImage(
background=g_sResourcePath
/ f"plant/{soilInfo['plantName']}/{currentStage}.png"
)
return True, plant, False, offsetX, offsetY
@classmethod
async def getUserSeedByUid(cls, uid: str) -> bytes:
"""获取用户种子仓库"""
@@ -449,7 +87,7 @@ class CFarmManager:
if not plantInfo:
continue
iconPath = g_sResourcePath / f"plant/{seedName}/icon.png"
iconPath = config.g_sResourcePath / f"plant/{seedName}/icon.png"
icon = (iconPath, 33, 33) if iconPath.exists() else ""
sellable = "可以" if plantInfo["sell"] else "不可以"
@@ -495,16 +133,18 @@ class CFarmManager:
count = 0 # 如果返回 None,则视为没有种子
if count <= 0:
return g_sTranslation["sowing"]["noSeed"].format(name=name)
return config.g_sTranslation["sowing"]["noSeed"].format(name=name)
# 如果播种数量超过仓库种子数量
if count < num and num != -1:
return g_sTranslation["sowing"]["noNum"].format(name=name, num=count)
return config.g_sTranslation["sowing"]["noNum"].format(
name=name, num=count
)
# 获取用户土地数量
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if not player:
return g_sTranslation["basic"]["error"]
return config.g_sTranslation["basic"]["error"]
soilNumber = player.user.get("soil", 3)
# 如果播种数量为 -1,表示播种所有可播种的土地
@@ -540,13 +180,17 @@ class CFarmManager:
# 根据播种结果给出反馈
if num == 0:
return g_sTranslation["sowing"]["success"].format(name=name, num=count)
return config.g_sTranslation["sowing"]["success"].format(
name=name, num=count
)
else:
return g_sTranslation["sowing"]["success2"].format(name=name, num=count)
return config.g_sTranslation["sowing"]["success2"].format(
name=name, num=count
)
except Exception as e:
logger.warning("播种操作失败!", e=e)
return g_sTranslation["sowing"]["error"]
return config.g_sTranslation["sowing"]["error"]
@classmethod
async def harvest(cls, uid: str) -> str:
@@ -561,9 +205,9 @@ class CFarmManager:
try:
await g_pEventManager.m_beforeHarvest.emit(uid=uid) # type: ignore
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if not player:
return g_sTranslation["basic"]["error"]
return config.g_sTranslation["basic"]["error"]
soilNumber = player.user.get("soil", 3)
harvestRecords = [] # 收获日志记录
@@ -591,9 +235,11 @@ class CFarmManager:
if not plantInfo:
continue
currentTime = g_pToolManager.dateTime().now()
matureTime = g_pToolManager.dateTime().fromtimestamp(
int(soilInfo["matureTime"])
currentTime = getToolManager().dateTime().now()
matureTime = (
getToolManager()
.dateTime()
.fromtimestamp(int(soilInfo["matureTime"]))
)
if currentTime >= matureTime:
@@ -620,7 +266,7 @@ class CFarmManager:
experience = math.floor(experience * (100 + percent) // 100)
harvestRecords.append(
g_sTranslation["harvest"]["append"].format(
config.g_sTranslation["harvest"]["append"].format(
name=soilInfo["plantName"],
num=number,
exp=plantInfo["experience"],
@@ -680,19 +326,19 @@ class CFarmManager:
exp = player.user.get("exp", 0)
await player.addExp(exp + experience)
harvestRecords.append(
g_sTranslation["harvest"]["exp"].format(
config.g_sTranslation["harvest"]["exp"].format(
exp=experience,
)
)
if harvestCount <= 0:
return g_sTranslation["harvest"]["no"]
return config.g_sTranslation["harvest"]["no"]
else:
return "\n".join(harvestRecords)
except Exception as e:
logger.warning("收获操作失败!", e=e)
return g_sTranslation["harvest"]["error"]
return config.g_sTranslation["harvest"]["error"]
@classmethod
async def eradicate(cls, uid: str) -> str:
@@ -704,9 +350,9 @@ class CFarmManager:
Returns:
str: 返回
"""
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if not player:
return g_sTranslation["basic"]["error"]
return config.g_sTranslation["basic"]["error"]
soilNumber = player.user.get("soil", 3)
await g_pEventManager.m_beforeEradicate.emit(uid=uid) # type: ignore
@@ -727,7 +373,7 @@ class CFarmManager:
experience += 3
if g_bIsDebug:
if config.g_bIsDebug:
experience += 999
# 更新数据库操作
@@ -754,9 +400,9 @@ class CFarmManager:
exp = player.user.get("exp", 0)
await player.addExp(exp + experience)
return g_sTranslation["eradicate"]["success"].format(exp=experience)
return config.g_sTranslation["eradicate"]["success"].format(exp=experience)
else:
return g_sTranslation["eradicate"]["error"]
return config.g_sTranslation["eradicate"]["error"]
@classmethod
async def getUserPlantByUid(cls, uid: str) -> bytes:
@@ -797,7 +443,7 @@ class CFarmManager:
continue
icon = ""
icon_path = g_sResourcePath / f"plant/{name}/icon.png"
icon_path = config.g_sResourcePath / f"plant/{name}/icon.png"
if icon_path.exists():
icon = (icon_path, 33, 33)
@@ -841,16 +487,18 @@ class CFarmManager:
"""
# 先判断该用户仓库是否有该作物
if not await g_pDBService.userPlant.checkUserPlantByName(uid, name):
return g_sTranslation["lockPlant"]["noPlant"]
return config.g_sTranslation["lockPlant"]["noPlant"]
# 更改加锁状态
if await g_pDBService.userPlant.lockUserPlantByName(uid, name, lock):
if lock == 0:
return g_sTranslation["lockPlant"]["unlockPlant"].format(name=name)
return config.g_sTranslation["lockPlant"]["unlockPlant"].format(
name=name
)
else:
return g_sTranslation["lockPlant"]["lockPlant"].format(name=name)
return config.g_sTranslation["lockPlant"]["lockPlant"].format(name=name)
else:
return g_sTranslation["lockPlant"]["error"]
return config.g_sTranslation["lockPlant"]["error"]
@classmethod
async def stealing(cls, uid: str, target: str) -> str:
@@ -864,25 +512,25 @@ class CFarmManager:
str: 返回
"""
# 用户信息
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if not player:
return g_sTranslation["basic"]["error"]
return config.g_sTranslation["basic"]["error"]
stealTime = player.user.get("stealTime", "")
stealCount = int(player.user["stealCount"])
if stealTime == "" or not stealTime:
stealTime = g_pToolManager.dateTime().date().today().strftime("%Y-%m-%d")
stealTime = getToolManager().dateTime().date().today().strftime("%Y-%m-%d")
stealCount = 5
elif (
g_pToolManager.dateTime().date().fromisoformat(stealTime)
!= g_pToolManager.dateTime().date().today()
getToolManager().dateTime().date().fromisoformat(stealTime)
!= getToolManager().dateTime().date().today()
):
stealTime = g_pToolManager.dateTime().date().today().strftime("%Y-%m-%d")
stealTime = getToolManager().dateTime().date().today().strftime("%Y-%m-%d")
stealCount = 5
if stealCount <= 0:
return g_sTranslation["stealing"]["max"]
return config.g_sTranslation["stealing"]["max"]
# 获取用户解锁地块数量
soilNumber = player.user.get("soil", 3)
@@ -908,9 +556,9 @@ class CFarmManager:
if not plantInfo:
continue
currentTime = g_pToolManager.dateTime().now()
matureTime = g_pToolManager.dateTime().fromtimestamp(
int(soilInfo["matureTime"])
currentTime = getToolManager().dateTime().now()
matureTime = (
getToolManager().dateTime().fromtimestamp(int(soilInfo["matureTime"]))
)
if currentTime >= matureTime:
@@ -931,7 +579,7 @@ class CFarmManager:
)
harvestRecords.append(
g_sTranslation["stealing"]["info"].format(
config.g_sTranslation["stealing"]["info"].format(
name=soilInfo["plantName"], num=randomNumber
)
)
@@ -971,7 +619,7 @@ class CFarmManager:
i,
uid,
randomNumber,
int(g_pToolManager.dateTime().now().timestamp()),
int(getToolManager().dateTime().now().timestamp()),
)
else:
@@ -980,13 +628,13 @@ class CFarmManager:
i,
uid,
randomNumber,
int(g_pToolManager.dateTime().now().timestamp()),
int(getToolManager().dateTime().now().timestamp()),
)
if isStealingPlant <= 0 and isStealingNumber <= 0:
return g_sTranslation["stealing"]["noPlant"]
return config.g_sTranslation["stealing"]["noPlant"]
elif isStealingPlant <= 0 and isStealingNumber > 0:
return g_sTranslation["stealing"]["repeat"]
return config.g_sTranslation["stealing"]["repeat"]
else:
stealCount -= 1
@@ -1004,15 +652,15 @@ class CFarmManager:
Returns:
str: 返回条件文本信息
"""
jLevel = await g_pJsonManager.getLevel()
jLevel = await getJsonManager().getLevel()
rec = jLevel["reclamation"]
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if not player:
return g_sTranslation["basic"]["error"]
return config.g_sTranslation["basic"]["error"]
try:
if player.user["soil"] >= 30:
return g_sTranslation["reclamation"]["perfect"]
return config.g_sTranslation["reclamation"]["perfect"]
rec = rec[f"{player.user['soil'] + 1}"]
@@ -1022,17 +670,17 @@ class CFarmManager:
str = ""
if len(item) == 0:
str = g_sTranslation["reclamation"]["next"].format(
str = config.g_sTranslation["reclamation"]["next"].format(
level=level, num=point
)
else:
str = g_sTranslation["reclamation"]["next2"].format(
str = config.g_sTranslation["reclamation"]["next2"].format(
level=level, num=point, item=item
)
return str
except Exception:
return g_sTranslation["reclamation"]["error"]
return config.g_sTranslation["reclamation"]["error"]
@classmethod
async def reclamation(cls, uid: str) -> str:
@@ -1044,17 +692,17 @@ class CFarmManager:
Returns:
str: _description_
"""
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if not player:
return g_sTranslation["basic"]["error"]
return config.g_sTranslation["basic"]["error"]
level = await player.getUserLevel()
jsonLevel = await g_pJsonManager.getLevel()
jsonLevel = await getJsonManager().getLevel()
rec = jsonLevel["reclamation"]
try:
if player.user["soil"] >= 30:
return g_sTranslation["reclamation"]["perfect"]
return config.g_sTranslation["reclamation"]["perfect"]
rec = rec[f"{player.user['soil'] + 1}"]
@@ -1063,20 +711,20 @@ class CFarmManager:
# item = rec["item"]
if level[0] < levelFileter:
return g_sTranslation["reclamation"]["nextLevel"].format(
return config.g_sTranslation["reclamation"]["nextLevel"].format(
level=level[0], next=levelFileter
)
if player.user["point"] < point:
return g_sTranslation["reclamation"]["noNum"].format(num=point)
return config.g_sTranslation["reclamation"]["noNum"].format(num=point)
# TODO 缺少判断消耗的item
await player.subPoint("point", point)
await player.updateField("soil", player.user["soil"] + 1)
return g_sTranslation["reclamation"]["success"]
return config.g_sTranslation["reclamation"]["success"]
except Exception:
return g_sTranslation["reclamation"]["error1"]
return config.g_sTranslation["reclamation"]["error1"]
@classmethod
async def soilUpgradeCondition(cls, uid: str, soilIndex: int) -> str:
@@ -1092,18 +740,18 @@ class CFarmManager:
soilInfo = await g_pDBService.userSoil.getUserSoil(uid, soilIndex)
if not soilInfo:
return g_sTranslation["soilInfo"]["error"]
return config.g_sTranslation["soilInfo"]["error"]
soilLevel = soilInfo.get("soilLevel", 0) + 1
if soilLevel >= g_iSoilLevelMax:
return g_sTranslation["soilInfo"]["error1"]
if soilLevel >= config.g_iSoilLevelMax:
return config.g_sTranslation["soilInfo"]["error1"]
# 获取用户当前土地 的下一级土地 数量
countSoil = await g_pDBService.userSoil.countSoilByLevel(uid, soilLevel)
# 获取升级所需
soilLevelText = await g_pDBService.userSoil.getSoilLevel(soilLevel)
jSoil = await g_pJsonManager.getSoil()
jSoil = await getJsonManager().getSoil()
fileter = jSoil["upgrade"][soilLevelText][countSoil]
nextLevel = await g_pDBService.userSoil.getSoilLevelText(soilLevel)
@@ -1139,22 +787,22 @@ class CFarmManager:
Returns:
str:
"""
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if not player:
return g_sTranslation["basic"]["error"]
return config.g_sTranslation["basic"]["error"]
soilInfo = await g_pDBService.userSoil.getUserSoil(uid, soilIndex)
if not soilInfo:
return g_sTranslation["soilInfo"]["error"]
return config.g_sTranslation["soilInfo"]["error"]
soilLevel = soilInfo.get("soilLevel", 0) + 1
if soilLevel >= g_iSoilLevelMax:
return g_sTranslation["soilInfo"]["error1"]
if soilLevel >= config.g_iSoilLevelMax:
return config.g_sTranslation["soilInfo"]["error1"]
countSoil = await g_pDBService.userSoil.countSoilByLevel(uid, soilLevel)
soilLevelText = await g_pDBService.userSoil.getSoilLevel(soilLevel)
soil = await g_pJsonManager.getSoil()
soil = await getJsonManager().getSoil()
fileter = soil["upgrade"][soilLevelText][countSoil]
getters = {
@@ -1188,9 +836,9 @@ class CFarmManager:
await player.subPoint("point", fileter.get("point", 0))
await player.subPoint("vipPoint", fileter.get("vipPoint", 0))
return g_sTranslation["soilInfo"]["success"].format(
return config.g_sTranslation["soilInfo"]["success"].format(
name=await g_pDBService.userSoil.getSoilLevelText(soilLevel),
text=g_sTranslation["soilInfo"][soilLevelText],
text=config.g_sTranslation["soilInfo"][soilLevelText],
)
@classmethod
@@ -1218,9 +866,9 @@ class CFarmManager:
pro = int(Config.get_config("zhenxun_plugin_farm", "点券兑换倍数"))
pro *= num
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if not player:
return g_sTranslation["basic"]["error"]
return config.g_sTranslation["basic"]["error"]
point = player.user.get("point", 0)
if point < pro:
@@ -1241,6 +889,3 @@ class CFarmManager:
await player.subPoint("point", pro)
return f"兑换{num}点券成功,当前点券:{number},赠送点券:{giftPoints},当前农场币:{point}"
g_pFarmManager = CFarmManager()
+5 -9
View File
@@ -1,15 +1,14 @@
from zhenxun.configs.path_config import DATA_PATH
from zhenxun.services.log import logger
from ..utils.config import g_sResourcePath
from ..utils.tool import g_pToolManager
from ..utils import config, getToolManager
class CHelpManager:
@classmethod
async def createHelpImage(cls) -> bool:
templatePath = g_sResourcePath / "html/help.html"
outputPath = g_sResourcePath / "temp_html/help.html"
templatePath = config.g_sResourcePath / "html/help.html"
outputPath = config.g_sResourcePath / "temp_html/help.html"
savePath = DATA_PATH / "farm_res/html/help.png"
context = {
@@ -24,9 +23,9 @@ class CHelpManager:
}
try:
g_pToolManager.renderHtmlToFile(templatePath, context, outputPath)
getToolManager().renderHtmlToFile(templatePath, context, outputPath)
bytes = await g_pToolManager.screenshotSave(
bytes = await getToolManager().screenshotSave(
str(outputPath), str(savePath), 1500, 2300
)
except Exception as e:
@@ -34,6 +33,3 @@ class CHelpManager:
return False
return True
g_pHelpManager = CHelpManager()
+4
View File
@@ -0,0 +1,4 @@
from .player import CPlayer
from .playerPool import CPlayerPool
__all__ = ["CPlayer", "CPlayerPool"]
+15 -13
View File
@@ -1,4 +1,4 @@
from ..dbService import g_pDBService
from .. import g_pDBlocator
class CPlayer:
@@ -24,7 +24,7 @@ class CPlayer:
if uid == "":
return False
self.user = await g_pDBService.user.getUserInfoByUid(uid)
self.user = await g_pDBlocator.getUserManager().getUserInfoByUid(uid)
return True
@@ -39,7 +39,7 @@ class CPlayer:
if uid == "":
return False
return await g_pDBService.user.isRegistered(uid)
return await g_pDBlocator.getUserManager().isRegistered(uid)
async def addPoint(self, type: str, index: int) -> bool:
"""增加货币
@@ -53,7 +53,7 @@ class CPlayer:
"""
uid = self.user.get("uid", "")
if uid == "" or type not in g_pDBService.user.currencies:
if uid == "" or type not in g_pDBlocator.getUserManager().currencies:
return False
if index == 0:
@@ -64,7 +64,7 @@ class CPlayer:
if nowIndex < 0:
nowIndex = 0
if await g_pDBService.user.updatePoint(uid, type, nowIndex):
if await g_pDBlocator.getUserManager().updatePoint(uid, type, nowIndex):
self.user[type] = nowIndex
return True
@@ -82,7 +82,7 @@ class CPlayer:
"""
uid = self.user.get("uid", "")
if uid == "" or type not in g_pDBService.user.currencies:
if uid == "" or type not in g_pDBlocator.getUserManager().currencies:
return False
if index == 0:
@@ -93,7 +93,7 @@ class CPlayer:
if nowIndex < 0:
nowIndex = 0
if await g_pDBService.user.updatePoint(uid, type, nowIndex):
if await g_pDBlocator.getUserManager().updatePoint(uid, type, nowIndex):
self.user[type] = nowIndex
return True
@@ -121,7 +121,7 @@ class CPlayer:
if nowExp < 0:
nowExp = 0
if await g_pDBService.user.updateExp(uid, nowExp):
if await g_pDBlocator.getUserManager().updateExp(uid, nowExp):
self.user["exp"] = nowExp
return True
@@ -149,7 +149,7 @@ class CPlayer:
if nowExp < 0:
nowExp = 0
if await g_pDBService.user.updateExp(uid, nowExp):
if await g_pDBlocator.getUserManager().updateExp(uid, nowExp):
self.user["exp"] = nowExp
return True
@@ -169,7 +169,7 @@ class CPlayer:
if uid == "":
return "error"
return await g_pDBService.user.updateName(uid, name)
return await g_pDBlocator.getUserManager().updateName(uid, name)
async def getUserLevel(self) -> tuple[int, int, int]:
"""获取用户等级信息
@@ -183,7 +183,7 @@ class CPlayer:
if uid == "":
return -1, -1, -1
return await g_pDBService.user.getUserLevelByUid(uid)
return await g_pDBlocator.getUserManager().getUserLevelByUid(uid)
async def updateStealCountByUid(
self, uid: str, stealTime: str, stealCount: int
@@ -203,7 +203,9 @@ class CPlayer:
if uid == "":
return False
return await g_pDBService.user.updateStealCountByUid(uid, stealTime, stealCount)
return await g_pDBlocator.getUserManager().updateStealCountByUid(
uid, stealTime, stealCount
)
async def updateField(self, field: str, value) -> bool:
"""更新单字段信息
@@ -216,4 +218,4 @@ class CPlayer:
if uid == "":
return False
return await g_pDBService.user.updateFieldByUid(uid, field, value)
return await g_pDBlocator.getUserManager().updateFieldByUid(uid, field, value)
+32 -30
View File
@@ -2,9 +2,8 @@ import math
from zhenxun.utils.image_utils import ImageTemplate
from ..core.dbService import g_pDBService
from ..utils.config import g_sResourcePath, g_sTranslation
from ..utils.tool import g_pToolManager
from ..utils import config, getToolManager
from . import g_pDBlocator
class CShopManager:
@@ -46,7 +45,7 @@ class CShopManager:
]
# 查询所有可购买作物,并根据筛选关键字过滤
plants = await g_pDBService.plant.listPlants()
plants = await g_pDBlocator.getPlantManager().listPlants()
filteredPlants = []
# 如果是点券商店
@@ -87,7 +86,7 @@ class CShopManager:
for plant in pageItems:
# 图标处理
icon = ""
iconPath = g_sResourcePath / f"plant/{plant['name']}/icon.png"
iconPath = config.g_sResourcePath / f"plant/{plant['name']}/icon.png"
if iconPath.exists():
icon = (iconPath, 33, 33)
@@ -136,17 +135,17 @@ class CShopManager:
str:
"""
if num <= 0:
return g_sTranslation["buySeed"]["notNum"]
return config.g_sTranslation["buySeed"]["notNum"]
player = await g_pToolManager.getPlayerByUid(uid)
plantInfo = await g_pDBService.plant.getPlantByName(name)
player = await getToolManager().getPlayerByUid(uid)
plantInfo = await g_pDBlocator.getPlantManager().getPlantByName(name)
if not plantInfo or not player:
return g_sTranslation["buySeed"]["error"]
return config.g_sTranslation["buySeed"]["error"]
level = player.user.get("level", 0)
if level < int(plantInfo["level"]):
return g_sTranslation["buySeed"]["noLevel"]
return config.g_sTranslation["buySeed"]["noLevel"]
vipSeed = plantInfo.get("isVip", 0) == 1
currencyType = "vipPoint" if vipSeed else "point"
@@ -155,17 +154,19 @@ class CShopManager:
currentCurrency = player.user.get(currencyType, 0)
if currentCurrency < totalCost:
return g_sTranslation["buySeed"][f"no{'Vip' if vipSeed else ''}Point"]
return config.g_sTranslation["buySeed"][
f"no{'Vip' if vipSeed else ''}Point"
]
await player.addPoint(currencyType, currentCurrency - totalCost)
await player.subPoint(currencyType, totalCost)
if not await g_pDBService.userSeed.addUserSeedByUid(uid, name, num):
return g_sTranslation["buySeed"]["errorSql"]
if not await g_pDBlocator.getUserSeedManager().addUserSeedByUid(uid, name, num):
return config.g_sTranslation["buySeed"]["errorSql"]
success_key = "vipSuccess" if vipSeed else "success"
remaining_currency = currentCurrency - totalCost
return g_sTranslation["buySeed"][success_key].format(
return config.g_sTranslation["buySeed"][success_key].format(
name=name, total=totalCost, point=remaining_currency
)
@@ -182,9 +183,9 @@ class CShopManager:
if not isinstance(name, str) or name.strip() == "":
name = ""
plant = await g_pDBService.userPlant.getUserPlantByUid(uid)
plant = await g_pDBlocator.getUserPlantManager().getUserPlantByUid(uid)
if not plant:
return g_sTranslation["sellPlant"]["no"]
return config.g_sTranslation["sellPlant"]["no"]
point = 0
totalSold = 0
@@ -192,27 +193,31 @@ class CShopManager:
if name == "":
for plantName, count in plant.items():
isLock = await g_pDBService.userPlant.checkPlantLockByName(
isLock = await g_pDBlocator.getUserPlantManager().checkPlantLockByName(
uid, plantName
)
if isLock:
continue
plantInfo = await g_pDBService.plant.getPlantByName(plantName)
plantInfo = await g_pDBlocator.getUserPlantManager().getPlantByName(
plantName
)
if not plantInfo:
continue
point += plantInfo["price"] * count
await g_pDBService.userPlant.updateUserPlantByName(uid, plantName, 0)
await g_pDBlocator.getUserPlantManager().updateUserPlantByName(
uid, plantName, 0
)
else:
if name not in plant:
return g_sTranslation["sellPlant"]["error"].format(name=name)
return config.g_sTranslation["sellPlant"]["error"].format(name=name)
available = plant[name]
sellAmount = available if isAll else min(available, num)
if sellAmount <= 0:
return g_sTranslation["sellPlant"]["error1"].format(name=name)
await g_pDBService.userPlant.updateUserPlantByName(
return config.g_sTranslation["sellPlant"]["error1"].format(name=name)
await g_pDBlocator.getUserPlantManager().updateUserPlantByName(
uid, name, available - sellAmount
)
totalSold = sellAmount
@@ -220,7 +225,7 @@ class CShopManager:
if name == "":
totalPoint = point
else:
plantInfo = await g_pDBService.plant.getPlantByName(name)
plantInfo = await g_pDBlocator.getUserPlantManager().getPlantByName(name)
if not plantInfo:
price = 0
else:
@@ -228,18 +233,15 @@ class CShopManager:
totalPoint = totalSold * price
player = await g_pToolManager.getPlayerByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if not player:
return g_sTranslation["basic"]["error"]
return config.g_sTranslation["basic"]["error"]
currentPoint = player.user.get("point", 0)
await player.addPoint("point", currentPoint + totalPoint)
result = "success1" if name == "" else "success"
return g_sTranslation["sellPlant"][result].format(
return config.g_sTranslation["sellPlant"][result].format(
point=totalPoint, num=currentPoint + totalPoint
)
g_pShopManager = CShopManager()
+3
View File
@@ -0,0 +1,3 @@
from .event import g_pEventManager
__all__ = ["g_pEventManager"]
+37
View File
@@ -0,0 +1,37 @@
def getConfig():
from . import config
return config
def getDrawFarm():
from .darw.drawFarm import CDarwFarm
return CDarwFarm
def getRequestManager():
from .request import CRequestManager
return CRequestManager
def getToolManager():
from .tool import CToolManager
return CToolManager
def getJsonManager():
from .json import g_pJsonManager
return g_pJsonManager
__all__ = [
"getConfig",
"getDrawFarm",
"getJsonManager",
"getRequestManager",
"getToolManager",
]
+3
View File
@@ -0,0 +1,3 @@
from .drawFarm import CDarwFarm
__all__ = ["CDarwFarm"]
+426
View File
@@ -0,0 +1,426 @@
from zhenxun.configs.config import Config
from zhenxun.services.log import logger
from zhenxun.utils._build_image import BuildImage
from zhenxun.utils.image_utils import ImageTemplate
from zhenxun.utils.platform import PlatformUtils
from ...core.dbService import g_pDBService
from .. import config, getJsonManager, getToolManager
class CDarwFarm:
@classmethod
async def drawFarmByUid(cls, uid: str) -> bytes:
"""绘制用户农场
Args:
uid (str): 用户UID
Returns:
bytes: 返回绘制结果
"""
img, soilSize, soilPos, grass = await cls.createBaseCanvas()
player = await getToolManager().getPlayerByUid(uid)
if not player:
return img.pic2bytes()
soilUnlock = int(player.user.get("soil", 3))
isFirstExpansion = True # 首次添加扩建图片
isFirstRipe = True
for index in range(0, 30):
x = soilPos[str(index + 1)]["x"]
y = soilPos[str(index + 1)]["y"]
# 已解锁格子
if index < soilUnlock:
isRipe = await cls.drawUnlockedTile(img, uid, index + 1, x, y, soilSize)
if isRipe and isFirstRipe:
await cls.pasteRipeOnce(img, x, y, soilSize)
isFirstRipe = False
else:
addedExpansion = await cls.drawLockedTile(
img, x, y, soilSize, grass, isFirstExpansion
)
if addedExpansion:
isFirstExpansion = False
await cls.drawUserInfo(img, player, uid)
await cls.applyDefinitionResize(img)
return img.pic2bytes()
@classmethod
async def createBaseCanvas(cls) -> tuple[BuildImage, tuple, dict, BuildImage]:
"""创建基础画布并返回 (img, soilSize, soilPos, grass)
Returns:
tuple: (主画布, 土地尺寸, 土地坐标映射, 草地图)
"""
img = BuildImage(
background=config.g_sResourcePath / "background/background.jpg"
)
soil = await getJsonManager().getSoil()
soilSize = soil["size"]
soilPos = soil["soil"]
grass = BuildImage(background=config.g_sResourcePath / "soil/草土地.png")
await grass.resize(0, soilSize[0], soilSize[1])
return img, soilSize, soilPos, grass
@classmethod
async def drawUnlockedTile(
cls, img: BuildImage, uid: str, soilIndex: int, x: int, y: int, soilSize
) -> bool:
"""绘制已解锁土地格(包含土地贴图与作物),返回该格是否可收获。
Args:
img (BuildImage): 主画布。
uid (str): 用户UID。
soilIndex (int): 土地索引(从1开始)。
x (int), y (int): 贴图位置。
soilSize: 土地贴图尺寸([w,h] 或 (w,h))。
Returns:
bool: 是否有可收获作物(isRipe)。
"""
soilUrl = "soil/普通土地.png"
soilInfo = await g_pDBService.userSoil.getUserSoil(uid, soilIndex)
if soilInfo:
soilLevel = soilInfo.get("soilLevel", 0)
if soilLevel == 1:
soilUrl = "soil/红土地.png"
elif soilLevel == 2:
soilUrl = "soil/黑土地.png"
elif soilLevel == 3:
soilUrl = "soil/金土地.png"
soil = BuildImage(background=config.g_sResourcePath / soilUrl)
await soil.resize(0, soilSize[0], soilSize[1])
await img.paste(soil, (x, y))
isPlant, plant, isRipe, offsetX, offsetY = await cls.drawSoilPlant(
uid, soilIndex
)
if isPlant and plant is not None:
await img.paste(
plant,
(
x + soilSize[0] // 2 - plant.width // 2 + offsetX,
y + soilSize[1] // 2 - plant.height // 2 + offsetY,
),
)
return bool(isRipe)
@classmethod
async def drawLockedTile(
cls,
img: BuildImage,
x: int,
y: int,
soilSize,
grass: BuildImage,
isFirstExpansion: bool,
) -> bool:
"""绘制未解锁格子并在首次出现时绘制扩建图标。
Returns:
bool: 是否在此格绘制了扩建图标(仅首次返回 True)。
"""
await img.paste(grass, (x, y))
if isFirstExpansion:
expansion = BuildImage(
background=config.g_sResourcePath / "background/expansion.png"
)
await expansion.resize(0, 69, 69)
await img.paste(
expansion,
(
x + soilSize[0] // 2 - expansion.width // 2,
y + soilSize[1] // 2 - expansion.height,
),
)
return True
return False
@classmethod
async def pasteRipeOnce(cls, img: BuildImage, x: int, y: int, soilSize):
"""首次发现成熟作物时贴上成熟提示图(ripe)。"""
ripe = BuildImage(background=config.g_sResourcePath / "background/ripe.png")
await img.paste(
ripe,
(x + soilSize[0] // 2 - ripe.width // 2, y - ripe.height // 2),
)
@classmethod
async def drawUserInfo(cls, img: BuildImage, player, uid: str):
"""绘制左上角用户信息(头像、框、昵称、经验、等级、货币等)。
TODO 需要详细的绘制头像框
Args:
img (BuildImage): 主画布。
player: 用户对象(包含 user 字段)。
uid (str): 用户UID。
"""
image = await PlatformUtils.get_user_avatar(uid, "qq")
if image:
avatar = BuildImage(background=image)
await avatar.resize(0, 140, 150)
await img.paste(avatar, (125, 85))
frame = BuildImage(background=config.g_sResourcePath / "background/frame.png")
await img.paste(frame, (75, 44))
nameImg = await BuildImage.build_text_image(
player.user["name"], size=24, font_color=(77, 35, 4)
)
await img.paste(nameImg, (300, 92))
level = await player.getUserLevel()
beginX = 309
endX = 627
width = int((level[2] / level[1]) * (endX - beginX)) if level[1] else 0
await img.rectangle((beginX, 188, beginX + width, 222), (171, 194, 41))
# 经验
expImg = await BuildImage.build_text_image(
f"{level[2]} / {level[1]}", size=24, font_color=(102, 120, 19)
)
await img.paste(expImg, (390, 193))
# 等级
levelImg = await BuildImage.build_text_image(
str(level[0]), size=32, font_color=(214, 111, 1)
)
await img.paste(levelImg, (660, 187))
# 农场币
pointImg = await BuildImage.build_text_image(
str(player.user.get("point", 0)), size=24, font_color=(253, 253, 253)
)
await img.paste(pointImg, (330, 255))
# 点券
bondsImg = await BuildImage.build_text_image(
"0", size=24, font_color=(253, 253, 253)
)
await img.paste(bondsImg, (570, 255))
@classmethod
async def applyDefinitionResize(cls, img: BuildImage):
"""根据配置调整绘制清晰度(original/medium/hight/其他)。"""
definition = Config.get_config("zhenxun_plugin_farm", "绘制农场清晰度")
if definition == "medium":
await img.resize(0.6)
elif definition == "hight":
await img.resize(0.8)
elif definition == "original":
pass
else:
await img.resize(0.4)
@classmethod
async def drawDetailFarmByUid(cls, uid: str) -> list:
"""绘制用户详细信息
Args:
uid (str): 用户Uid
Returns:
list:
"""
info = []
farm = await cls.drawFarmByUid(uid)
player = await getToolManager().getPlayerByUid(uid)
if not player:
return info
info.append(BuildImage.open(farm))
dataList = []
columnName = [
"-",
"土地ID",
"土地等级",
"作物名称",
"成熟时间",
"土地状态",
"被偷数量",
"剩余产出",
]
icon = ""
soilNumber = player.user.get("soil", 3)
for i in range(1, soilNumber + 1):
soilInfo = await g_pDBService.userSoil.getUserSoil(uid, i)
if not soilInfo:
continue
match soilInfo.get("soilLevel", 0):
case 1:
name = "红土地.png"
case 2:
name = "黑土地.png"
case 3:
name = "金土地.png"
case _:
name = "普通土地.png"
iconPath = config.g_sResourcePath / "soil" / name
if iconPath.exists():
icon = (iconPath, 33, 33)
plantName = soilInfo.get("plantName", "-")
if plantName == "-":
matureTime = "-"
soilStatus = "-"
totalNumber = "-"
plantNumber = "-"
else:
matureTime = (
getToolManager()
.dateTime()
.fromtimestamp(int(soilInfo.get("matureTime", 0)))
.strftime("%Y-%m-%d %H:%M:%S")
)
soilStatus = await g_pDBService.userSoil.getUserSoilStatus(uid, i)
totalNumber = await g_pDBService.userSteal.getTotalStolenCount(uid, i)
planInfo = await g_pDBService.plant.getPlantByName(plantName)
if not planInfo:
plantNumber = "None"
else:
plantNumber = f"{planInfo['harvest'] - totalNumber}"
dataList.append(
[
icon,
i,
await g_pDBService.userSoil.getSoilLevelText(soilInfo["soilLevel"]),
plantName,
matureTime,
soilStatus,
totalNumber,
plantNumber,
]
)
if len(dataList) >= 15:
result = await ImageTemplate.table_page(
"土地详细信息",
"",
columnName,
dataList,
)
info.append(result.copy())
dataList.clear()
if i >= soilNumber:
result = await ImageTemplate.table_page(
"土地详细信息",
"",
columnName,
dataList,
)
info.append(result.copy())
dataList.clear()
return info
@classmethod
async def drawSoilPlant(
cls, uid: str, soilIndex: int
) -> tuple[bool, BuildImage, bool, int, int]:
"""绘制植物资源
Args:
uid (str): 用户Uid
soilIndex (int): 土地索引 从1开始
Returns:
tuple[bool, BuildImage]: [绘制是否成功,资源图片, 是否成熟]
"""
plant = None
soilInfo = await g_pDBService.userSoil.getUserSoil(uid, soilIndex)
if not soilInfo:
return False, None, False, 0, 0 # type: ignore
# 是否枯萎
if int(soilInfo.get("wiltStatus", 0)) == 1:
plant = BuildImage(background=config.g_sResourcePath / "plant/basic/9.png")
await plant.resize(0, 150, 212)
return True, plant, False, 0, 0
# 获取作物详细信息
plantInfo = await g_pDBService.plant.getPlantByName(soilInfo["plantName"])
if not plantInfo:
logger.error(f"绘制植物资源失败: {soilInfo['plantName']}")
return False, None, False, 0, 0 # type: ignore
offsetX = plantInfo.get("officX", 0)
offsetY = plantInfo.get("officY", 0)
offsetW = plantInfo.get("officW", 0)
offsetH = plantInfo.get("officH", 0)
currentTime = getToolManager().dateTime().now().timestamp()
phaseList = await g_pDBService.plant.getPlantPhaseByName(soilInfo["plantName"])
# 如果当前时间大于成熟时间 说明作物成熟
if currentTime >= soilInfo["matureTime"]:
plant = BuildImage(
background=config.g_sResourcePath
/ f"plant/{soilInfo['plantName']}/{len(phaseList)}.png"
)
return True, plant, True, offsetX, offsetY
else:
# 如果是多阶段作物 且没有成熟 #早期思路 多阶段作物 直接是倒数第二阶段图片
# if soilInfo["harvestCount"] >= 1:
# plant = BuildImage(
# background=g_sResourcePath
# / f"plant/{soilInfo['plantName']}/{plantInfo['phase'] - 1}.png"
# )
# return True, plant, False, offsetX, offsetY
# 如果没有成熟 则根据当前阶段进行绘制
elapsedTime = currentTime - soilInfo["plantTime"]
currentStage = currentStage = sum(
1 for thr in phaseList if elapsedTime >= thr
)
if currentStage <= 0:
if not plantInfo["general"]:
plant = BuildImage(
background=config.g_sResourcePath
/ f"plant/{soilInfo['plantName']}/0.png"
)
else:
plant = BuildImage(
background=config.g_sResourcePath / "plant/basic/0.png"
)
await plant.resize(0, 35 + offsetW, 58 + offsetH)
else:
plant = BuildImage(
background=config.g_sResourcePath
/ f"plant/{soilInfo['plantName']}/{currentStage}.png"
)
return True, plant, False, offsetX, offsetY
+2 -3
View File
@@ -2,8 +2,7 @@ import json
from zhenxun.services.log import logger
from . import config
from .request import g_pRequestManager
from . import config, getRequestManager
class CJsonManager:
@@ -117,7 +116,7 @@ class CJsonManager:
return False
async def initSignInFile(self) -> bool:
if not await g_pRequestManager.initSignInFile():
if not await getRequestManager().initSignInFile():
config.g_bSignStatus = False
return False
else:
+10 -14
View File
@@ -15,8 +15,7 @@ from zhenxun.configs.config import Config
from zhenxun.services.log import logger
from ..core.dbService import g_pDBService
from .config import g_sPlantPath, g_sSignInPath
from .tool import g_pToolManager
from . import config, getToolManager
class CRequestManager:
@@ -162,14 +161,14 @@ class CRequestManager:
@classmethod
async def initSignInFile(cls) -> bool:
if os.path.exists(g_sSignInPath):
if os.path.exists(config.g_sSignInPath):
try:
with open(g_sSignInPath, encoding="utf-8") as f:
with open(config.g_sSignInPath, encoding="utf-8") as f:
content = f.read()
sign = json.loads(content)
date = sign.get("date", "")
yearMonth = g_pToolManager.dateTime().now().strftime("%Y%m")
yearMonth = getToolManager().dateTime().now().strftime("%Y%m")
if date == yearMonth:
logger.debug("真寻农场签到文件检查完毕")
@@ -193,8 +192,8 @@ class CRequestManager:
try:
baseUrl = Config.get_config("zhenxun_plugin_farm", "服务地址")
url = f"{baseUrl.rstrip('/')}:8998/sign_in"
path = str(g_sSignInPath.parent.resolve(strict=False))
yearMonth = g_pToolManager.dateTime().now().strftime("%Y%m")
path = str(config.g_sSignInPath.parent.resolve(strict=False))
yearMonth = getToolManager().dateTime().now().strftime("%Y%m")
# 下载为 signTemp.json
success = await cls.download(
@@ -208,7 +207,7 @@ class CRequestManager:
return False
# 重命名为 sign_in.json
g_pToolManager.renameFile(f"{path}/signTemp.json", "sign_in.json")
getToolManager().renameFile(f"{path}/signTemp.json", "sign_in.json")
return True
except Exception as e:
logger.error("下载签到文件失败", e=e)
@@ -221,7 +220,7 @@ class CRequestManager:
Returns:
bool: 是否为最新版或成功更新
"""
versionPath = os.path.join(os.path.dirname(g_sPlantPath), "version.json")
versionPath = os.path.join(os.path.dirname(config.g_sPlantPath), "version.json")
try:
with open(versionPath, encoding="utf-8") as f:
@@ -262,7 +261,7 @@ class CRequestManager:
"""
baseUrl = Config.get_config("zhenxun_plugin_farm", "服务地址")
savePath = os.path.dirname(g_sPlantPath)
savePath = os.path.dirname(config.g_sPlantPath)
success = await cls.download(
url=f"{baseUrl.rstrip('/')}:8998/file/plant.db",
savePath=savePath,
@@ -273,7 +272,7 @@ class CRequestManager:
return False
# 重命名为 sign_in.json
g_pToolManager.renameFile(f"{savePath}/plantTemp.db", "plant.db")
getToolManager().renameFile(f"{savePath}/plantTemp.db", "plant.db")
versionPath = os.path.join(savePath, "version.json")
try:
@@ -288,6 +287,3 @@ class CRequestManager:
await g_pDBService.plant.downloadPlant()
return True
g_pRequestManager = CRequestManager()
+1 -5
View File
@@ -9,8 +9,7 @@ from playwright.async_api import async_playwright
from zhenxun.services.log import logger
from zhenxun.utils.message import MessageUtils
from ..core.player.player import CPlayer
from ..core.player.playerPool import g_pUserPool
from ..core import CPlayer, g_pUserPool
class CToolManager:
@@ -192,6 +191,3 @@ class CToolManager:
# 截图并保存到本地文件
await page.screenshot(path=save, full_page=True)
await browser.close()
g_pToolManager = CToolManager()