diff --git a/__init__.py b/__init__.py index ba53d5c..6dbdcd6 100644 --- a/__init__.py +++ b/__init__.py @@ -7,7 +7,8 @@ from zhenxun.utils.message import MessageUtils from .command import diuse_farm, diuse_register, reclamation from .config import g_pJsonManager -from .database import g_pSqlManager +from .database.database import g_pSqlManager +from .dbService import g_pDBService from .farm.farm import g_pFarmManager from .farm.shop import g_pShopManager from .request import g_pRequestManager @@ -36,7 +37,7 @@ __plugin_meta__ = PluginMetadata( """.strip(), extra=PluginExtraData( author="Art_Sakura", - version="1.1", + version="1.2", commands=[Command(command="我的农场")], menu_type="群内小游戏", configs=[ @@ -79,6 +80,8 @@ async def start(): # 初始化读取Json await g_pJsonManager.init() + await g_pDBService.init() + # 析构函数 @driver.on_shutdown async def shutdown(): diff --git a/command.py b/command.py index 1d4ae4a..278e765 100644 --- a/command.py +++ b/command.py @@ -1,6 +1,5 @@ from nonebot.adapters import Event, MessageTemplate from nonebot.rule import to_me -from nonebot.typing import T_State from nonebot_plugin_alconna import (Alconna, AlconnaMatch, AlconnaQuery, Args, Arparma, At, Match, MultiVar, Option, Query, Subcommand, on_alconna, store_true) @@ -11,15 +10,15 @@ from zhenxun.services.log import logger from zhenxun.utils.depends import UserName from zhenxun.utils.message import MessageUtils -from .database import g_pSqlManager +from .dbService import g_pDBService from .farm.farm import g_pFarmManager from .farm.shop import g_pShopManager async def isRegisteredByUid(uid: str) -> bool: - point = await g_pSqlManager.getUserPointByUid(uid) + result = await g_pDBService.user.isUserExist(uid) - if point < 0: + if not result: await MessageUtils.build_message("尚未开通农场,快at我发送 开通农场 开通吧").send() return False @@ -36,7 +35,7 @@ diuse_register = on_alconna( @diuse_register.handle() async def handle_register(session: Uninfo): uid = str(session.user.id) - user = await g_pSqlManager.getUserInfoByUid(uid) + user = await g_pDBService.user.getUserInfoByUid(uid) if user: await MessageUtils.build_message("🎉 您已经开通农场啦~").send(reply_to=True) @@ -48,7 +47,7 @@ async def handle_register(session: Uninfo): safe_name = sanitize_username(raw_name) # 初始化用户信息 - success = await g_pSqlManager.initUserInfoByUid( + success = await g_pDBService.user.initUserInfoByUid( uid=uid, name=safe_name, exp=0, @@ -160,7 +159,7 @@ diuse_farm.shortcut( @diuse_farm.assign("my-point") async def _(session: Uninfo): uid = str(session.user.id) - point = await g_pSqlManager.getUserPointByUid(uid) + point = await g_pDBService.user.getUserPointByUid(uid) if point < 0: await MessageUtils.build_message("尚未开通农场,快at我发送 开通农场 开通吧").send() @@ -366,9 +365,9 @@ async def _(session: Uninfo, target: Match[At]): await MessageUtils.build_message("请在指令后跟需要at的人").finish(reply_to=True) tar = target.result - point = await g_pSqlManager.getUserPointByUid(tar.target) + result = await g_pDBService.user.isUserExist(tar.target) - if point < 0: + if not result: await MessageUtils.build_message("目标尚未开通农场,快邀请ta开通吧").send() return None @@ -419,7 +418,7 @@ async def _(session: Uninfo, name: Match[str]): safeName = sanitize_username(name.result) - result = await g_pSqlManager.updateUserNameByUid(uid, safeName) + result = await g_pDBService.user.updateUserNameByUid(uid, safeName) if result == True: await MessageUtils.build_message("更新用户名成功!").send(reply_to=True) diff --git a/database/database.py b/database/database.py index 3c5824d..f0cf4dd 100644 --- a/database/database.py +++ b/database/database.py @@ -8,7 +8,6 @@ import aiosqlite from zhenxun.services.log import logger from ..config import g_sDBFilePath, g_sDBPath -from ..dbService import g_pDBService class CSqlManager: @@ -27,8 +26,6 @@ class CSqlManager: cls.m_pDB = await aiosqlite.connect(g_sDBFilePath) cls.m_pDB.row_factory = aiosqlite.Row - await g_pDBService.init() - return True @classmethod diff --git a/database/user.py b/database/user.py index 1bee7ed..4a978c1 100644 --- a/database/user.py +++ b/database/user.py @@ -1,10 +1,11 @@ +import math from datetime import date, datetime, timedelta from typing import List, Union -from database import CSqlManager - from zhenxun.services.log import logger +from .database import CSqlManager + class CUserDB(CSqlManager): @classmethod @@ -65,6 +66,28 @@ class CUserDB(CSqlManager): rows = await cursor.fetchall() return [row[0] for row in rows] + @classmethod + async def isUserExist(cls, uid: str) -> bool: + """判断用户是否存在 + + Args: + uid (str): 用户Uid + + Returns: + bool: 如果用户存在返回True,否则返回False + """ + if not uid: + return False + try: + async with cls.m_pDB.execute( + "SELECT 1 FROM user WHERE uid = ?", (uid,) + ) as cursor: + row = await cursor.fetchone() + return row is not None + except Exception as e: + logger.warning("isUserExist 查询失败!", e=e) + return False + @classmethod async def getUserInfoByUid(cls, uid: str) -> dict: """获取指定用户完整信息 @@ -240,22 +263,37 @@ class CUserDB(CSqlManager): uid (str): 用户Uid Returns: - tuple[int, int, int]: (当前等级, 下级所需经验, 当前等级剩余经验),失败返回(-1, -1, -1) + tuple[int, int, int]: (当前等级, 升至下级还需经验, 当前等级已获经验),失败返回(-1, -1, -1) """ if not uid: return -1, -1, -1 + try: async with cls.m_pDB.execute( "SELECT exp FROM user WHERE uid = ?", (uid,) ) as cursor: row = await cursor.fetchone() - if row and row[0] is not None: - expVal = int(row[0]) - level = expVal // 200 - nextLevelExp = 200 * (level + 1) - currentLevelExp = level * 200 - remainingExp = expVal - currentLevelExp - return level, nextLevelExp, remainingExp + if not row or row[0] is None: + return -1, -1, -1 + + expVal = int(row[0]) + levelStep = 200 # 每级经验增量 + + discriminant = 1 + 8 * expVal / levelStep + level = int((-1 + math.sqrt(discriminant)) // 2) + if level < 0: + level = 0 + + def cumExp(k: int) -> int: + return levelStep * k * (k + 1) // 2 + + totalExpCurrentLevel = cumExp(level) + totalExpNextLevel = cumExp(level + 1) + + currentExp = expVal - totalExpCurrentLevel + + return level, totalExpNextLevel, currentExp + return -1, -1, -1 except Exception as e: logger.warning("getUserLevelByUid 查询失败!", e=e) diff --git a/database/userItem.py b/database/userItem.py index 142ce83..c0b35da 100644 --- a/database/userItem.py +++ b/database/userItem.py @@ -1,9 +1,9 @@ from typing import Optional -from database import CSqlManager - from zhenxun.services.log import logger +from .database import CSqlManager + class CUserItemDB(CSqlManager): @classmethod @@ -41,7 +41,7 @@ class CUserItemDB(CSqlManager): row = await cursor.fetchone() return row[0] if row else None except Exception as e: - logger.warning(f"真寻农场getUserItemByName查询失败!", e=e) + logger.warning(f"getUserItemByName查询失败!", e=e) return None @classmethod @@ -64,7 +64,7 @@ class CUserItemDB(CSqlManager): rows = await cursor.fetchall() return {row["item"]: row["count"] for row in rows} except Exception as e: - logger.warning(f"真寻农场getUserItemByUid查询失败!", e=e) + logger.warning(f"getUserItemByUid查询失败!", e=e) return {} @classmethod @@ -88,7 +88,7 @@ class CUserItemDB(CSqlManager): ) return True except Exception as e: - logger.warning(f"真寻农场deleteUserItemByName失败!", e=e) + logger.warning(f"deleteUserItemByName失败!", e=e) return False @classmethod @@ -119,7 +119,7 @@ class CUserItemDB(CSqlManager): ) return True except Exception as e: - logger.warning(f"真寻农场updateUserItemByName失败!", e=e) + logger.warning(f"updateUserItemByName失败!", e=e) return False @classmethod @@ -164,5 +164,5 @@ class CUserItemDB(CSqlManager): ) return True except Exception as e: - logger.warning(f"真寻农场addUserItemByUid失败!", e=e) + logger.warning(f"addUserItemByUid失败!", e=e) return False diff --git a/database/userPlant.py b/database/userPlant.py index 76445cb..aaaeaa9 100644 --- a/database/userPlant.py +++ b/database/userPlant.py @@ -1,9 +1,9 @@ from typing import Dict, Optional -from database import CSqlManager - from zhenxun.services.log import logger +from .database import CSqlManager + class CUserPlantDB(CSqlManager): @classmethod @@ -56,7 +56,7 @@ class CUserPlantDB(CSqlManager): ) return True except Exception as e: - logger.warning(f"真寻农场addUserPlantByUid 失败!", e=e) + logger.warning(f"addUserPlantByUid 失败!", e=e) return False @classmethod @@ -95,7 +95,7 @@ class CUserPlantDB(CSqlManager): row = await cursor.fetchone() return row[0] if row else None except Exception as e: - logger.warning(f"真寻农场getUserPlantByName 查询失败!", e=e) + logger.warning(f"getUserPlantByName 查询失败!", e=e) return None @classmethod @@ -121,7 +121,7 @@ class CUserPlantDB(CSqlManager): ) return True except Exception as e: - logger.warning(f"真寻农场updateUserPlantByName失败!", e=e) + logger.warning(f"updateUserPlantByName失败!", e=e) return False @classmethod @@ -143,5 +143,5 @@ class CUserPlantDB(CSqlManager): ) return True except Exception as e: - logger.warning(f"真寻农场deleteUserPlantByName 失败!", e=e) + logger.warning(f"deleteUserPlantByName 失败!", e=e) return False diff --git a/database/userSeed.py b/database/userSeed.py index dc4df5f..8628db5 100644 --- a/database/userSeed.py +++ b/database/userSeed.py @@ -1,9 +1,9 @@ from typing import Optional -from database import CSqlManager - from zhenxun.services.log import logger +from .database import CSqlManager + class CUserSeedDB(CSqlManager): @classmethod @@ -22,7 +22,7 @@ class CUserSeedDB(CSqlManager): @classmethod async def addUserSeedByUid(cls, uid: str, seed: str, count: int = 1) -> bool: - """根据用户uid添加种子信息 + """根据用户uid添加种子信息(事务版本) Args: uid (str): 用户uid @@ -34,7 +34,6 @@ class CUserSeedDB(CSqlManager): """ try: async with cls._transaction(): - #检查是否已存在该种子 async with cls.m_pDB.execute( "SELECT count FROM userSeed WHERE uid = ? AND seed = ?", (uid, seed) @@ -42,21 +41,18 @@ class CUserSeedDB(CSqlManager): row = await cursor.fetchone() if row: - #如果种子已存在,则更新数量 newCount = row[0] + count await cls.m_pDB.execute( "UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?", (newCount, uid, seed) ) else: - #如果种子不存在,则插入新记录 newCount = count await cls.m_pDB.execute( "INSERT INTO userSeed (uid, seed, count) VALUES (?, ?, ?)", (uid, seed, count) ) - #如果种子数量为 0,删除记录 if newCount <= 0: await cls.m_pDB.execute( "DELETE FROM userSeed WHERE uid = ? AND seed = ?", @@ -64,9 +60,33 @@ class CUserSeedDB(CSqlManager): ) return True except Exception as e: - logger.warning(f"真寻农场addUserSeedByUid 失败!", e=e) + logger.warning(f"addUserSeedByUid 失败!", e=e) return False + @classmethod + async def _addUserSeedByUid(cls, uid: str, seed: str, count: int = 1) -> bool: + """根据用户uid添加种子信息(非事务版,复用其他非事务接口)""" + try: + existing = await cls.getUserSeedByName(uid, seed) + newCount = (existing or 0) + count + + if existing is not None: + await cls._updateUserSeedByName(uid, seed, newCount) + else: + await cls.m_pDB.execute( + "INSERT INTO userSeed (uid, seed, count) VALUES (?, ?, ?)", + (uid, seed, newCount) + ) + + if newCount <= 0: + await cls._deleteUserSeedByName(uid, seed) + + return True + except Exception as e: + logger.warning(f"_addUserSeedByUid 失败!", e=e) + return False + + @classmethod async def getUserSeedByName(cls, uid: str, seed: str) -> Optional[int]: """根据种子名称获取种子数量 @@ -87,7 +107,7 @@ class CUserSeedDB(CSqlManager): row = await cursor.fetchone() return row[0] if row else None except Exception as e: - logger.warning(f"真寻农场getUserSeedByName 查询失败!", e=e) + logger.warning(f"getUserSeedByName 查询失败!", e=e) return None @classmethod @@ -131,7 +151,33 @@ class CUserSeedDB(CSqlManager): ) return True except Exception as e: - logger.warning(f"真寻农场updateUserSeedByName失败!", e=e) + logger.warning(f"updateUserSeedByName失败!", e=e) + return False + + @classmethod + async def _updateUserSeedByName(cls, uid: str, seed: str, count: int) -> bool: + """根据种子名称更新种子数量 + + Args: + uid (str): 用户uid + seed (str): 种子名称 + count (int): 种子数量 + + Returns: + bool: 是否成功 + """ + try: + if count <= 0: + return await cls.deleteUserSeedByName(uid, seed) + + async with cls._transaction(): + await cls.m_pDB.execute( + "UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?", + (count, uid, seed) + ) + return True + except Exception as e: + logger.warning(f"updateUserSeedByName失败!", e=e) return False @classmethod @@ -153,5 +199,26 @@ class CUserSeedDB(CSqlManager): ) return True except Exception as e: - logger.warning(f"真寻农场deleteUserSeedByName 删除失败!", e=e) + logger.warning(f"deleteUserSeedByName 删除失败!", e=e) + return False + + @classmethod + async def _deleteUserSeedByName(cls, uid: str, seed: str) -> bool: + """根据种子名称从种子仓库中删除种子 + + Args: + uid (str): 用户uid + seed (str): 种子名称 + + Returns: + bool: 是否成功 + """ + try: + await cls.m_pDB.execute( + "DELETE FROM userSeed WHERE uid = ? AND seed = ?", + (uid, seed) + ) + return True + except Exception as e: + logger.warning(f"deleteUserSeedByName 删除失败!", e=e) return False diff --git a/database/userSoil.py b/database/userSoil.py index ca3548b..6273184 100644 --- a/database/userSoil.py +++ b/database/userSoil.py @@ -1,28 +1,27 @@ from datetime import date, datetime, timedelta from typing import Optional -from database import CSqlManager - from zhenxun.services.log import logger from ..config import g_pJsonManager from ..dbService import g_pDBService +from .database import CSqlManager class CUserSoilDB(CSqlManager): @classmethod async def initDB(cls): - #用户Uid - #地块索引从1开始 - #作物名称 - #播种时间 - #成熟时间 - #土地等级 0=普通地,1=红土地,2=黑土地,3=金土地 - #枯萎状态 0=未枯萎,1=枯萎 - #施肥状态 0=未施肥,1=施肥 - #虫害状态 0=无虫害,1=有虫害 - #杂草状态 0=无杂草,1=有杂草 - #缺水状态 0=不缺水,1=缺水 + # 用户Uid + # 地块索引从1开始 + # 作物名称 + # 播种时间 + # 成熟时间 + # 土地等级 0=普通地,1=红土地,2=黑土地,3=金土地 + # 枯萎状态 0=未枯萎,1=枯萎 + # 施肥状态 0=未施肥,1=施肥 + # 虫害状态 0=无虫害,1=有虫害 + # 杂草状态 0=无杂草,1=有杂草 + # 缺水状态 0=不缺水,1=缺水 userSoil = { "uid": "TEXT NOT NULL", "soilIndex": "INTEGER NOT NULL", @@ -35,7 +34,7 @@ class CUserSoilDB(CSqlManager): "bugStatus": "INTEGER DEFAULT 0", "weedStatus": "INTEGER DEFAULT 0", "waterStatus": "INTEGER DEFAULT 0", - "PRIMARY KEY": "(uid, soilIndex)" + "PRIMARY KEY": "(uid, soilIndex)", } await cls.ensureTableSchema("userSoil", userSoil) @@ -52,61 +51,50 @@ class CUserSoilDB(CSqlManager): """ cursor = await cls.m_pDB.execute("SELECT * FROM soil WHERE uid = ?", (uid,)) row = await cursor.fetchone() + if not row: return {} columns = [description[0] for description in cursor.description] return dict(zip(columns, row)) @classmethod - async def migrateOldFarmData(cls): + async def migrateOldFarmData(cls) -> bool: """迁移旧土地数据到新表 userSoil 并删除旧表 - Raises: - aiosqlite.Error: 数据库操作失败时抛出 - Returns: - None + bool: 如果旧表不存在则返回 False,否则迁移并删除后返回 True """ + # 检查旧表是否存在 + cursor = await cls.m_pDB.execute( + "SELECT name FROM sqlite_master WHERE type='table' AND name='soil'" + ) + if not await cursor.fetchone(): + return False + async with cls._transaction(): users = await g_pDBService.user.getAllUsers() + for uid in users: farmInfo = await cls.getUserFarmByUid(uid) for i in range(1, 31): - soilName = f"soil{i}" - if soilName not in farmInfo: + key = f"soil{i}" + data = farmInfo.get(key) + if not data: continue - soilData = farmInfo[soilName] - if not soilData: + parts = data.split(",") + if len(parts) < 3: continue + name = parts[0] + pt = int(parts[1]) + mt = int(parts[2]) - fields = soilData.split(',') - if len(fields) < 6: - continue + await cls.m_pDB.execute( + "INSERT INTO userSoil (uid,soilIndex,plantName,plantTime,matureTime) VALUES (?,?,?,?,?)", + (uid, i, name, pt, mt), + ) - plantName = fields[0] - plantTime = int(fields[1]) - matureTime = int(fields[2]) - soilLevel = int(fields[5]) - - # 构建新的土地数据 - soilInfo = { - "uid": uid, - "soilIndex": i, - "plantName": plantName, - "plantTime": plantTime, - "matureTime": matureTime, - "soilLevel": soilLevel, - "wiltStatus":0, - "fertilizerStatus": 0, - "bugStatus": 0, - "weedStatus": 0, - "waterStatus": 0 - } - - await cls.insertUserSoil(soilInfo) - - # 彻底清除旧表 await cls.m_pDB.execute("DROP TABLE soil") + return True @classmethod async def insertUserSoil(cls, soilInfo: dict): @@ -131,10 +119,36 @@ class CUserSoilDB(CSqlManager): soilInfo.get("fertilizerStatus", 0), soilInfo.get("bugStatus", 0), soilInfo.get("weedStatus", 0), - soilInfo.get("waterStatus", 0) - ) + soilInfo.get("waterStatus", 0), + ), ) + @classmethod + async def _insertUserSoil(cls, soilInfo: dict): + """插入一条新的 userSoil 记录 + + Args: + soilInfo (dict): 新土地数据 + + Returns: + None + """ + await cls.m_pDB.execute( + "INSERT INTO userSoil (uid, soilIndex, plantName, plantTime, matureTime, soilLevel, fertilizerStatus, bugStatus, weedStatus, waterStatus) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + soilInfo["uid"], + soilInfo["soilIndex"], + soilInfo.get("plantName", ""), + soilInfo.get("plantTime", 0), + soilInfo.get("matureTime", 0), + soilInfo.get("soilLevel", 0), + soilInfo.get("fertilizerStatus", 0), + soilInfo.get("bugStatus", 0), + soilInfo.get("weedStatus", 0), + soilInfo.get("waterStatus", 0), + ), + ) + @classmethod async def getUserSoil(cls, uid: str, soilIndex: int) -> Optional[dict]: """获取指定用户某块土地的详细信息 @@ -149,7 +163,7 @@ class CUserSoilDB(CSqlManager): async with cls._transaction(): cursor = await cls.m_pDB.execute( "SELECT * FROM userSoil WHERE uid = ? AND soilIndex = ?", - (uid, soilIndex) + (uid, soilIndex), ) row = await cursor.fetchone() if not row: @@ -157,6 +171,27 @@ class CUserSoilDB(CSqlManager): columns = [description[0] for description in cursor.description] return dict(zip(columns, row)) + @classmethod + async def _getUserSoil(cls, uid: str, soilIndex: int) -> Optional[dict]: + """获取指定用户某块土地的详细信息 + + Args: + uid (str): 用户ID + soilIndex (int): 土地索引 + + Returns: + Optional[dict]: 记录存在返回字段-值字典,否则返回 None + """ + cursor = await cls.m_pDB.execute( + "SELECT * FROM userSoil WHERE uid = ? AND soilIndex = ?", + (uid, soilIndex), + ) + row = await cursor.fetchone() + if not row: + return None + columns = [description[0] for description in cursor.description] + return dict(zip(columns, row)) + @classmethod async def updateUserSoil(cls, uid: str, soilIndex: int, field: str, value): """更新指定用户土地的单个字段 @@ -173,9 +208,27 @@ class CUserSoilDB(CSqlManager): async with cls._transaction(): await cls.m_pDB.execute( f"UPDATE userSoil SET {field} = ? WHERE uid = ? AND soilIndex = ?", - (value, uid, soilIndex) + (value, uid, soilIndex), ) + @classmethod + async def _updateUserSoil(cls, uid: str, soilIndex: int, field: str, value): + """更新指定用户土地的单个字段 + + Args: + uid (str): 用户ID + soilIndex (int): 土地索引 + field (str): 需更新的字段名 + value: 新值 + + Returns: + None + """ + await cls.m_pDB.execute( + f"UPDATE userSoil SET {field} = ? WHERE uid = ? AND soilIndex = ?", + (value, uid, soilIndex), + ) + @classmethod async def deleteUserSoil(cls, uid: str, soilIndex: int): """删除指定用户的土地记录 @@ -189,10 +242,24 @@ class CUserSoilDB(CSqlManager): """ async with cls._transaction(): await cls.m_pDB.execute( - "DELETE FROM userSoil WHERE uid = ? AND soilIndex = ?", - (uid, soilIndex) + "DELETE FROM userSoil WHERE uid = ? AND soilIndex = ?", (uid, soilIndex) ) + @classmethod + async def _deleteUserSoil(cls, uid: str, soilIndex: int): + """删除指定用户的土地记录 + + Args: + uid (str): 用户ID + soilIndex (int): 土地索引 + + Returns: + None + """ + await cls.m_pDB.execute( + "DELETE FROM userSoil WHERE uid = ? AND soilIndex = ?", (uid, soilIndex) + ) + @classmethod async def isSoilPlanted(cls, uid: str, soilIndex: int) -> bool: """判断指定用户的指定土地是否已种植 @@ -240,22 +307,24 @@ class CUserSoilDB(CSqlManager): async with cls._transaction(): # 复用原有记录字段,保留土壤状态等信息 prev = soilRecord or {} - await cls.deleteUserSoil(uid, soilIndex) - await cls.insertUserSoil({ - "uid": uid, - "soilIndex": soilIndex, - "plantName": plantName, - "plantTime": nowTs, - "matureTime": matureTs, - # 保留之前的土壤等级和状态字段,避免数据丢失 - "soilLevel": prev.get("soilLevel", 0), - "wiltStatus": prev.get("wiltStatus", 0), - "fertilizerStatus": prev.get("fertilizerStatus", 0), - "bugStatus": prev.get("bugStatus", 0), - "weedStatus": prev.get("weedStatus", 0), - "waterStatus": prev.get("waterStatus", 0) - }) + await cls._deleteUserSoil(uid, soilIndex) + await cls._insertUserSoil( + { + "uid": uid, + "soilIndex": soilIndex, + "plantName": plantName, + "plantTime": nowTs, + "matureTime": matureTs, + # 保留之前的土壤等级和状态字段,避免数据丢失 + "soilLevel": prev.get("soilLevel", 0), + "wiltStatus": prev.get("wiltStatus", 0), + "fertilizerStatus": prev.get("fertilizerStatus", 0), + "bugStatus": prev.get("bugStatus", 0), + "weedStatus": prev.get("weedStatus", 0), + "waterStatus": prev.get("waterStatus", 0), + } + ) return True except Exception as e: - logger.error(f"真寻农场播种失败!", e=e) + logger.error(f"播种失败!", e=e) return False diff --git a/database/userSteal.py b/database/userSteal.py index cb46e2d..a46cc94 100644 --- a/database/userSteal.py +++ b/database/userSteal.py @@ -1,7 +1,7 @@ -from database import CSqlManager - from zhenxun.services.log import logger +from .database import CSqlManager + class CUserStealDB(CSqlManager): @classmethod diff --git a/dbService.py b/dbService.py index f3c0aeb..79d3480 100644 --- a/dbService.py +++ b/dbService.py @@ -1,29 +1,35 @@ from typing import Optional -from .database.user import CUserDB -from .database.userItem import CUserItemDB -from .database.userPlant import CUserPlantDB -from .database.userSeed import CUserSeedDB -from .database.userSoil import CUserSoilDB -from .database.userSteal import CUserStealDB - class CDBService: - def __init__(self): - user: Optional["CUserDB"] = None - userSoil: Optional["CUserSoilDB"] = None - userPlant: Optional["CUserPlantDB"] = None - userSeed: Optional["CUserSeedDB"] = None - userItem: Optional["CUserItemDB"] = None - userSteal: Optional["CUserStealDB"] = None - @classmethod async def init(cls): + from .database.user import CUserDB + from .database.userItem import CUserItemDB + from .database.userPlant import CUserPlantDB + from .database.userSeed import CUserSeedDB + from .database.userSoil import CUserSoilDB + from .database.userSteal import CUserStealDB + cls.user = CUserDB() + await cls.user.initDB() + cls.userSoil = CUserSoilDB() + await cls.userSoil.initDB() + cls.userPlant = CUserPlantDB() + await cls.userPlant.initDB() + cls.userSeed = CUserSeedDB() + await cls.userSeed.initDB() + cls.userItem = CUserItemDB() + await cls.userItem.initDB() + cls.userSteal = CUserStealDB() + await cls.userSteal.initDB() + + #迁移旧数据库 + await cls.userSoil.migrateOldFarmData() g_pDBService = CDBService() diff --git a/farm/farm.py b/farm/farm.py index 8061499..d7d0af3 100644 --- a/farm/farm.py +++ b/farm/farm.py @@ -389,7 +389,7 @@ class CFarmManager: number = plantInfo['harvest'] #处理偷菜扣除数量 - stealNum = g_pDBService.userSteal.getTotalStolenCount(uid, i) + stealNum = await g_pDBService.userSteal.getTotalStolenCount(uid, i) number -= stealNum diff --git a/request.py b/request.py index 3031324..df23129 100644 --- a/request.py +++ b/request.py @@ -37,47 +37,73 @@ class CRequestManager: return False @classmethod - async def post(cls, endpoint: str, name: str = "", jsonData: dict = None, formData: dict = None) -> dict: - """发送POST请求到指定接口,供其他方法统一调用 + async def post(cls, endpoint: str, name: str = "", jsonData: dict = None) -> dict: + """发送POST请求到指定接口,统一调用,仅支持JSON格式数据 Args: endpoint (str): 请求的接口路径 name (str, optional): 操作名称用于日志记录 - jsonData (dict, optional): 以JSON格式发送的数据 - formData (dict, optional): 以表单格式发送的数据 + jsonData (dict): 以JSON格式发送的数据 Raises: - ValueError: 当jsonData和formData都未提供时抛出 + ValueError: 当jsonData未提供时抛出 Returns: dict: 返回请求结果的JSON数据 """ - if jsonData is None and formData is None: - raise ValueError("post请求必须提供jsonData或formData其中之一") + if jsonData is None: + raise ValueError("post请求必须提供jsonData") baseUrl = Config.get_config("zhenxun_plugin_farm", "服务地址") - url = f"{baseUrl.rstrip('/')}/{endpoint.lstrip('/')}" + headers = {"token": "xZ%?z5LtWV7H:0-Xnwp+bNRNQ-jbfrxG"} try: async with httpx.AsyncClient(timeout=5.0) as client: - if jsonData is not None: - response = await client.post(url, json=jsonData) - else: - response = await client.post(url, data=formData) + response = await client.post(url, json=jsonData, headers=headers) if response.status_code == 200: return response.json() else: - logger.warning(f"真寻农场{name}请求失败: HTTP {response.status_code} {response.text}") + logger.warning(f"{name}请求失败: HTTP {response.status_code} {response.text}") return {} except httpx.RequestError as e: - logger.warning(f"真寻农场{name}请求异常: {e}") + logger.warning(f"{name}请求异常", e=e) return {} except Exception as e: - logger.warning(f"真寻农场{name}处理异常: {e}") + logger.warning(f"{name}处理异常", e=e) return {} + @classmethod + async def get(cls, endpoint: str, name: str = "") -> dict: + """发送GET请求到指定接口,统一调用,仅支持无体的查询 + + Args: + endpoint (str): 请求的接口路径 + name (str, optional): 操作名称用于日志记录 + + Returns: + dict: 返回请求结果的JSON数据 + """ + baseUrl = Config.get_config("zhenxun_plugin_farm", "服务地址") + url = f"{baseUrl.rstrip('/')}/{endpoint.lstrip('/')}" + headers = {"token": "xZ%?z5LtWV7H:0-Xnwp+bNRNQ-jbfrxG"} + + try: + async with httpx.AsyncClient(timeout=5.0) as client: + response = await client.get(url, headers=headers) + + if response.status_code == 200: + return response.json() + else: + logger.warning(f"{name}请求失败: HTTP {response.status_code} {response.text}") + return {} + except httpx.RequestError as e: + logger.warning(f"{name}请求异常", e=e) + return {} + except Exception as e: + logger.warning(f"{name}处理异常", e=e) + return {} @classmethod async def sign(cls, uid: str) -> str: