🎨 更新了对数据库的表、字段判断

This commit is contained in:
Art_Sakura 2025-04-08 19:00:17 +08:00
parent 6b3137e015
commit d17c1b8ed7
6 changed files with 179 additions and 106 deletions

View File

@ -1,11 +1,11 @@
from nonebot import get_driver from nonebot import get_driver
from nonebot.plugin import PluginMetadata from nonebot.plugin import PluginMetadata
from zhenxun.configs.utils import Command, PluginExtraData from zhenxun.configs.utils import Command, PluginExtraData, RegisterConfig
from zhenxun.services.log import logger from zhenxun.services.log import logger
from zhenxun.utils.message import MessageUtils from zhenxun.utils.message import MessageUtils
from .command import diuse_farm, diuse_register from .command import diuse_farm, diuse_register, reclamation
from .config import g_pJsonManager from .config import g_pJsonManager
from .database import g_pSqlManager from .database import g_pSqlManager
from .farm.farm import g_pFarmManager from .farm.farm import g_pFarmManager
@ -30,13 +30,33 @@ __plugin_meta__ = PluginMetadata(
出售作物 [作物/种子名称] [数量] 出售作物 [作物/种子名称] [数量]
偷菜 at 偷菜 at
开垦 开垦
购买农场币 [数量] 金币转换农场币比率是 1 : 2 购买农场币 [数量] 数量为消耗金币的数量
""".strip(), """.strip(),
extra=PluginExtraData( extra=PluginExtraData(
author="Art_Sakura", author="Art_Sakura",
version="1.0", version="1.0",
commands=[Command(command="我的农场")], commands=[Command(command="我的农场")],
menu_type="群内小游戏" menu_type="群内小游戏",
configs=[
RegisterConfig(
key="兑换倍数",
value="2",
help="金币兑换农场币的倍数 默认值为: 2倍",
default_value="2",
),
RegisterConfig(
key="手续费",
value="0.2",
help="金币兑换农场币的手续费 默认值为: 0.2 实际意义为20%手续费",
default_value="0.2",
),
RegisterConfig(
key="服务地址",
value="http://diuse.work",
help="签到、交易行、活动等服务器地址",
default_value="http://diuse.work",
)
]
).to_dict(), ).to_dict(),
) )
driver = get_driver() driver = get_driver()
@ -51,9 +71,6 @@ async def start():
# 初始化读取Json # 初始化读取Json
await g_pJsonManager.init() await g_pJsonManager.init()
# await g_pFarmManager.reclamation("1754798088")
# await g_pSqlManager.initUserInfoByUid("1754798088", "Art_Sakura", 0, 100)
# 析构函数 # 析构函数
@driver.on_shutdown @driver.on_shutdown
async def shutdown(): async def shutdown():

View File

@ -258,33 +258,6 @@ async def _(session: Uninfo):
res = await g_pFarmManager.reclamation(uid) res = await g_pFarmManager.reclamation(uid)
await MessageUtils.build_message(res).send(reply_to=True) await MessageUtils.build_message(res).send(reply_to=True)
diuse_farm.shortcut(
"开垦",
command="我的农场",
arguments=["reclamation"],
prefix=True,
)
@diuse_farm.assign("reclamation")
async def _(session: Uninfo):
uid = str(session.user.id)
point = await g_pSqlManager.getUserPointByUid(uid)
if point < 0:
await MessageUtils.build_message("尚未开通农场快at我发送 开通农场 开通吧").send()
return None
result = await g_pFarmManager.getUserPlantByUid(uid)
await MessageUtils.build_message(result).send(reply_to=True)
diuse_farm.set_path_arg("reclamation", "result")
@diuse_farm.got_path("test", "测试一下")
async def _(name: str):
await MessageUtils.build_message(name).send(reply_to=True)
diuse_farm.shortcut( diuse_farm.shortcut(
"出售作物(?P<name>.*?)", "出售作物(?P<name>.*?)",
command="我的农场", command="我的农场",

View File

@ -1,32 +1,7 @@
{ {
<<<<<<< HEAD
"soil":[1, 1, 1, 2, 3, 5, 7, 9, 11, 13, "soil":[1, 1, 1, 2, 3, 5, 7, 9, 11, 13,
15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33,
36, 39, 42, 45, 48, 51, 54, 57, 60, 70 36, 39, 42, 45, 48, 51, 54, 57, 60, 70
=======
"level":
{
"0": 0,
"1": 50,
"2": 75,
"3": 125,
"4": 185,
"5": 200,
"6": 250,
"7": 275,
"8": 350,
"9": 500,
"10": 850,
"11": 1250,
"12": 2250,
"13": 3500,
"14": 4500,
"15": 5800
},
"soil":[1, 1, 1, 2, 3, 5, 7, 9, 12, 15,
18, 21, 25, 29, 33, 38, 43, 48, 54, 60,
66, 72, 78, 85, 92, 99, 106, 114, 120, 130
>>>>>>> f85ab9758c44ce45c6aae9e792f7a5d9e2f7459a
], ],
"reclamation": "reclamation":
{ {

View File

@ -1,5 +1,6 @@
import math import math
import os import os
import re
from datetime import date, datetime, timedelta from datetime import date, datetime, timedelta
from io import StringIO from io import StringIO
from math import e from math import e
@ -20,7 +21,6 @@ class CSqlManager:
async def cleanup(cls): async def cleanup(cls):
if cls.m_pDB: if cls.m_pDB:
await cls.m_pDB.close() await cls.m_pDB.close()
cls.m_pDB = None
@classmethod @classmethod
async def init(cls) -> bool: async def init(cls) -> bool:
@ -28,62 +28,125 @@ class CSqlManager:
cls.m_pDB = await aiosqlite.connect(g_sDBFilePath) cls.m_pDB = await aiosqlite.connect(g_sDBFilePath)
if bIsExist == False: #if bIsExist == False:
# TODO 缺少判断创建失败事件 #TODO 缺少判断创建失败事件
await cls.createDB() #await cls.createDB()
await cls.checkDB()
return True return True
@classmethod @classmethod
async def createDB(cls) -> bool: async def getColumns(cls, tableName):
"""初始化数据库用户信息表 """ 由AI生成
获取表的列信息
"""
try:
cursor = await cls.m_pDB.execute(f'PRAGMA table_info("{tableName}")')
columns = [row[1] for row in await cursor.fetchall()]
return columns
except aiosqlite.Error as e:
logger.error(f"获取表结构失败: {str(e)}")
raise
@classmethod
async def ensure_table_exists(cls, tableName, columns) -> bool:
"""智能创建并分析数据库表、字段是否存在 由AI生成
Args:
tableName (_type_): 表名
columns (_type_): 字典
Returns: Returns:
bool: 是否创建成功 _type_: _description_
""" """
try:
current_columns = await cls.getColumns(tableName)
#用户信息 #检查表是否存在
userInfo = """ table_exists = bool(current_columns)
CREATE TABLE user (
uid INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
exp INTEGER DEFAULT 0,
point INTEGER DEFAULT 0,
soil INTEGER DEFAULT 3,
stealing TEXT DEFAULT NULL
);
"""
#用户仓库 #如果表不存在,直接创建
userStorehouse = """ if not table_exists:
CREATE TABLE storehouse ( create_sql = f'''
uid INTEGER PRIMARY KEY AUTOINCREMENT, CREATE TABLE "{tableName}" (
item TEXT DEFAULT '', {", ".join(f'"{k}" {v}' for k, v in columns.items())}
plant TEXT DEFAULT '', );
seed TEXT DEFAULT '' '''
); await cls.m_pDB.execute(create_sql)
""" await cls.m_pDB.commit() #显式提交新建表操作
return True
#用户土地信息 #表存在时的处理
with StringIO() as buffer: columns_to_add = []
buffer.write("CREATE TABLE soil (") columns_to_remove = []
buffer.write("uid INTEGER PRIMARY KEY AUTOINCREMENT,")
fields = [f"soil{i} TEXT DEFAULT ''" for i in range(1, 31)] #检查需要添加的列
buffer.write(",\n".join(fields)) for k, v in columns.items():
if k not in current_columns:
columns_to_add.append(f'"{k}" {v}')
buffer.write(");") #检查需要移除的列
for col in current_columns:
if col not in columns.keys():
columns_to_remove.append(col)
userSoilInfo = buffer.getvalue() #执行修改
if columns_to_add or columns_to_remove:
try:
#开启事务使用connection级别的事务控制
await cls.m_pDB.execute('BEGIN TRANSACTION')
#添加新列
for col_def in columns_to_add:
await cls.m_pDB.execute(f'ALTER TABLE "{tableName}" ADD COLUMN {col_def}')
#删除旧列
for col in columns_to_remove:
await cls.m_pDB.execute(f'ALTER TABLE "{tableName}" DROP COLUMN "{col}"')
#显式提交事务
await cls.m_pDB.commit()
return True
except Exception as e:
#回滚事务
await cls.m_pDB.rollback()
logger.error(f"表结构迁移失败: {str(e)}")
if not await cls.executeDB(userInfo):
return False return False
except aiosqlite.Error as e:
logger.error(f"表结构迁移失败: {str(e)}")
if not await cls.executeDB(userStorehouse): return True
return False
if not await cls.executeDB(userSoilInfo): @classmethod
return False async def checkDB(cls) -> bool:
userInfo = {
"uid": "INTEGER PRIMARY KEY AUTOINCREMENT",
"name": "TEXT NOT NULL",
"exp": "INTEGER DEFAULT 0",
"point": "INTEGER DEFAULT 0",
"soil": "INTEGER DEFAULT 3",
"stealing": "TEXT DEFAULT NULL"
}
userStorehouse = {
"uid": "INTEGER PRIMARY KEY AUTOINCREMENT",
"item": "TEXT DEFAULT ''",
"plant": "TEXT DEFAULT ''",
"seed": "TEXT DEFAULT ''"
}
userSoilInfo = {
"uid": "INTEGER PRIMARY KEY AUTOINCREMENT",
**{f"soil{i}": "TEXT DEFAULT ''" for i in range(1, 31)}
}
await cls.ensure_table_exists("user", userInfo)
await cls.ensure_table_exists("storehouse", userStorehouse)
await cls.ensure_table_exists("soil", userSoilInfo)
return True return True
@ -373,7 +436,7 @@ class CSqlManager:
s = "" s = ""
else: else:
#获取种子信息 这里能崩我吃 #获取种子信息 这里能崩我吃
plantInfo = g_pJsonManager.m_pPlant['plant'][plant] # type: ignore plantInfo = g_pJsonManager.m_pPlant['plant'][plant] #type: ignore
currentTime = datetime.now() currentTime = datetime.now()
newTime = currentTime + timedelta(hours=int(plantInfo['time'])) newTime = currentTime + timedelta(hours=int(plantInfo['time']))

View File

@ -4,6 +4,9 @@ from datetime import date, datetime
from io import StringIO from io import StringIO
from typing import Dict, List, Tuple from typing import Dict, List, Tuple
from numpy import number
from zhenxun.configs.config import Config
from zhenxun.models.user_console import UserConsole from zhenxun.models.user_console import UserConsole
from zhenxun.services.log import logger from zhenxun.services.log import logger
from zhenxun.utils._build_image import BuildImage from zhenxun.utils._build_image import BuildImage
@ -22,18 +25,23 @@ class CFarmManager:
user = await UserConsole.get_user(uid) user = await UserConsole.get_user(uid)
point = num // 2 if user.gold < num:
if user.gold < point:
return "你的金币不足" return "你的金币不足"
await UserConsole.reduce_gold(uid, point, GoldHandle.BUY , 'zhenxun_plugin_farm') await UserConsole.reduce_gold(uid, num, GoldHandle.BUY , 'zhenxun_plugin_farm')
pro = Config.get_config("zhenxun_plugin_farm", "兑换倍数")
tax = Config.get_config("zhenxun_plugin_farm", "手续费")
exc = num * pro
point = exc - (exc * tax)
p = await g_pSqlManager.getUserPointByUid(uid) p = await g_pSqlManager.getUserPointByUid(uid)
number = point + p
await g_pSqlManager.updateUserPointByUid(uid, num + p) await g_pSqlManager.updateUserPointByUid(uid, number)
return f"充值{num}农场币成功,当前农场币:{num + p}" return f"充值{num}农场币成功,当前农场币:{number}"
@classmethod @classmethod
async def drawFarmByUid(cls, uid: str) -> bytes: async def drawFarmByUid(cls, uid: str) -> bytes:

37
request.py Normal file
View File

@ -0,0 +1,37 @@
from unittest import result
import requests
class CRequestManager:
@classmethod
async def post(cls, url, json_data=None, form_data=None):
"""发送 POST 请求(支持 JSON/Form-Data 格式)"""
try:
headers = {"Content-Type": "application/json"} if json_data else None
response = requests.post(
url,
json=json_data,
data=form_data,
headers=headers,
timeout=5
)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
return {}
@classmethod
async def sign(cls, uid: str) -> str:
a = await cls.post("http://diuse.work:9099/testPost", json_data={"level":3})
result = ""
if int(a["type"]) == 1:
result = f"签到成功"
return result
g_pRequestManager = CRequestManager()