🎨 将文本内容同一更新
🐛 修复偷菜无法正常计算的BUG
This commit is contained in:
parent
ba2ecf19fc
commit
ac13ab9280
197
.gitignore
vendored
197
.gitignore
vendored
@ -1,3 +1,198 @@
|
|||||||
__pycache__
|
__pycache__/
|
||||||
|
|
||||||
./config/sign_in.json
|
./config/sign_in.json
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# UV
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
#uv.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
||||||
|
.pdm.toml
|
||||||
|
.pdm-python
|
||||||
|
.pdm-build/
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
||||||
|
|
||||||
|
# Abstra
|
||||||
|
# Abstra is an AI-powered process automation framework.
|
||||||
|
# Ignore directories containing user credentials, local state, and settings.
|
||||||
|
# Learn more at https://abstra.io/docs
|
||||||
|
.abstra/
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
||||||
|
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
||||||
|
# you could uncomment the following to ignore the enitre vscode folder
|
||||||
|
# .vscode/
|
||||||
|
|
||||||
|
# Ruff stuff:
|
||||||
|
.ruff_cache/
|
||||||
|
|
||||||
|
# PyPI configuration file
|
||||||
|
.pypirc
|
||||||
|
|
||||||
|
# Cursor
|
||||||
|
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
||||||
|
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
||||||
|
# refer to https://docs.cursor.com/context/ignore-files
|
||||||
|
.cursorignore
|
||||||
|
.cursorindexingignore
|
||||||
|
|||||||
14
__init__.py
14
__init__.py
@ -39,7 +39,7 @@ __plugin_meta__ = PluginMetadata(
|
|||||||
""".strip(),
|
""".strip(),
|
||||||
extra=PluginExtraData(
|
extra=PluginExtraData(
|
||||||
author="Art_Sakura",
|
author="Art_Sakura",
|
||||||
version="1.4.2",
|
version="1.4.3",
|
||||||
commands=[Command(command="我的农场")],
|
commands=[Command(command="我的农场")],
|
||||||
menu_type="群内小游戏",
|
menu_type="群内小游戏",
|
||||||
configs=[
|
configs=[
|
||||||
@ -66,8 +66,8 @@ __plugin_meta__ = PluginMetadata(
|
|||||||
value="http://diuse.work",
|
value="http://diuse.work",
|
||||||
help="签到、交易行、活动等服务器地址",
|
help="签到、交易行、活动等服务器地址",
|
||||||
default_value="http://diuse.work",
|
default_value="http://diuse.work",
|
||||||
)
|
),
|
||||||
]
|
],
|
||||||
).to_dict(),
|
).to_dict(),
|
||||||
)
|
)
|
||||||
driver = get_driver()
|
driver = get_driver()
|
||||||
@ -84,6 +84,7 @@ async def start():
|
|||||||
|
|
||||||
await g_pDBService.init()
|
await g_pDBService.init()
|
||||||
|
|
||||||
|
|
||||||
# 析构函数
|
# 析构函数
|
||||||
@driver.on_shutdown
|
@driver.on_shutdown
|
||||||
async def shutdown():
|
async def shutdown():
|
||||||
@ -92,12 +93,7 @@ async def shutdown():
|
|||||||
await g_pDBService.cleanup()
|
await g_pDBService.cleanup()
|
||||||
|
|
||||||
|
|
||||||
@scheduler.scheduled_job(
|
@scheduler.scheduled_job(trigger="cron", hour=0, minute=30, id="signInFile")
|
||||||
trigger="cron",
|
|
||||||
hour=0,
|
|
||||||
minute=30,
|
|
||||||
id="signInFile"
|
|
||||||
)
|
|
||||||
async def signInFile():
|
async def signInFile():
|
||||||
try:
|
try:
|
||||||
await g_pJsonManager.initSignInFile()
|
await g_pJsonManager.initSignInFile()
|
||||||
|
|||||||
289
command.py
289
command.py
@ -1,10 +1,20 @@
|
|||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
from nonebot.adapters import Event, MessageTemplate
|
from nonebot.adapters import Event
|
||||||
from nonebot.rule import to_me
|
from nonebot.rule import to_me
|
||||||
from nonebot_plugin_alconna import (Alconna, AlconnaMatch, AlconnaQuery, Args,
|
from nonebot_plugin_alconna import (
|
||||||
Arparma, At, Match, MultiVar, Option,
|
Alconna,
|
||||||
Query, Subcommand, on_alconna, store_true)
|
AlconnaQuery,
|
||||||
|
Args,
|
||||||
|
At,
|
||||||
|
Match,
|
||||||
|
MultiVar,
|
||||||
|
Option,
|
||||||
|
Query,
|
||||||
|
Subcommand,
|
||||||
|
on_alconna,
|
||||||
|
store_true,
|
||||||
|
)
|
||||||
from nonebot_plugin_uninfo import Uninfo
|
from nonebot_plugin_uninfo import Uninfo
|
||||||
from nonebot_plugin_waiter import waiter
|
from nonebot_plugin_waiter import waiter
|
||||||
|
|
||||||
@ -12,24 +22,13 @@ from zhenxun.configs.config import BotConfig
|
|||||||
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 .config import g_bSignStatus
|
from .config import g_bSignStatus, g_sTranslation
|
||||||
from .dbService import g_pDBService
|
from .dbService import g_pDBService
|
||||||
from .farm.farm import g_pFarmManager
|
from .farm.farm import g_pFarmManager
|
||||||
from .farm.shop import g_pShopManager
|
from .farm.shop import g_pShopManager
|
||||||
from .json import g_pJsonManager
|
from .json import g_pJsonManager
|
||||||
from .tool import g_pToolManager
|
from .tool import g_pToolManager
|
||||||
|
|
||||||
|
|
||||||
async def isRegisteredByUid(uid: str) -> bool:
|
|
||||||
result = await g_pDBService.user.isUserExist(uid)
|
|
||||||
|
|
||||||
if not result:
|
|
||||||
await MessageUtils.build_message("尚未开通农场,快at我发送 开通农场 开通吧").send()
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
diuse_register = on_alconna(
|
diuse_register = on_alconna(
|
||||||
Alconna("开通农场"),
|
Alconna("开通农场"),
|
||||||
priority=5,
|
priority=5,
|
||||||
@ -37,89 +36,40 @@ diuse_register = on_alconna(
|
|||||||
block=True,
|
block=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_register.handle()
|
@diuse_register.handle()
|
||||||
async def handle_register(session: Uninfo):
|
async def handle_register(session: Uninfo):
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
user = await g_pDBService.user.getUserInfoByUid(uid)
|
user = await g_pDBService.user.getUserInfoByUid(uid)
|
||||||
|
|
||||||
if user:
|
if user:
|
||||||
await MessageUtils.build_message("🎉 您已经开通农场啦~").send(reply_to=True)
|
await MessageUtils.build_message(g_sTranslation["register"]["repeat"]).send(
|
||||||
|
reply_to=True
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
raw_name = str(session.user.name)
|
raw_name = str(session.user.name)
|
||||||
safe_name = sanitize_username(raw_name)
|
safe_name = g_pToolManager.sanitize_username(raw_name)
|
||||||
|
|
||||||
# 初始化用户信息
|
# 初始化用户信息
|
||||||
success = await g_pDBService.user.initUserInfoByUid(
|
success = await g_pDBService.user.initUserInfoByUid(
|
||||||
uid=uid,
|
uid=uid, name=safe_name, exp=0, point=500
|
||||||
name=safe_name,
|
|
||||||
exp=0,
|
|
||||||
point=500
|
|
||||||
)
|
)
|
||||||
|
|
||||||
msg = (
|
msg = (
|
||||||
"✅ 农场开通成功!\n💼 初始资金:500农场币"
|
g_sTranslation["register"]["success"]
|
||||||
if success
|
if success
|
||||||
else "⚠️ 开通失败,请稍后再试"
|
else g_sTranslation["register"]["error"]
|
||||||
)
|
)
|
||||||
logger.info(f"用户注册 {'成功' if success else '失败'}:{uid}")
|
logger.info(f"用户注册 {'成功' if success else '失败'}:{uid}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
msg = "⚠️ 系统繁忙,请稍后再试"
|
msg = g_sTranslation["register"]["error"]
|
||||||
logger.error(f"注册异常 | UID:{uid} | 错误:{str(e)}")
|
logger.error(f"注册异常 | UID:{uid} | 错误:{e}")
|
||||||
|
|
||||||
await MessageUtils.build_message(msg).send(reply_to=True)
|
await MessageUtils.build_message(msg).send(reply_to=True)
|
||||||
|
|
||||||
def sanitize_username(username: str, max_length: int = 15) -> str:
|
|
||||||
"""
|
|
||||||
安全处理用户名
|
|
||||||
功能:
|
|
||||||
1. 移除首尾空白
|
|
||||||
2. 过滤危险字符
|
|
||||||
3. 转义单引号
|
|
||||||
4. 处理空值
|
|
||||||
5. 限制长度
|
|
||||||
"""
|
|
||||||
# 处理空值
|
|
||||||
if not username:
|
|
||||||
return "神秘农夫"
|
|
||||||
|
|
||||||
# 基础清洗
|
|
||||||
cleaned = username.strip()
|
|
||||||
|
|
||||||
# 允许的字符白名单(可自定义扩展)
|
|
||||||
safe_chars = {
|
|
||||||
'_', '-', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
|
|
||||||
'+', '=', '.', ',', '~', '·', ' ',
|
|
||||||
'a','b','c','d','e','f','g','h','i','j','k','l','m',
|
|
||||||
'n','o','p','q','r','s','t','u','v','w','x','y','z',
|
|
||||||
'A','B','C','D','E','F','G','H','I','J','K','L','M',
|
|
||||||
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
|
|
||||||
'0','1','2','3','4','5','6','7','8','9',
|
|
||||||
}
|
|
||||||
# 添加常用中文字符(Unicode范围)
|
|
||||||
safe_chars.update(chr(c) for c in range(0x4E00, 0x9FFF+1))
|
|
||||||
|
|
||||||
# 过滤危险字符
|
|
||||||
filtered = [
|
|
||||||
c if c in safe_chars or 0x4E00 <= ord(c) <= 0x9FFF
|
|
||||||
else ''
|
|
||||||
for c in cleaned
|
|
||||||
]
|
|
||||||
|
|
||||||
# 合并处理结果
|
|
||||||
safe_str = ''.join(filtered)
|
|
||||||
|
|
||||||
# 转义单引号(双重保障)
|
|
||||||
escaped = safe_str.replace("'", "''")
|
|
||||||
|
|
||||||
# 处理空结果
|
|
||||||
if not escaped:
|
|
||||||
return "神秘农夫"
|
|
||||||
|
|
||||||
# 长度限制
|
|
||||||
return escaped[:max_length]
|
|
||||||
|
|
||||||
diuse_farm = on_alconna(
|
diuse_farm = on_alconna(
|
||||||
Alconna(
|
Alconna(
|
||||||
@ -137,25 +87,28 @@ diuse_farm = on_alconna(
|
|||||||
Subcommand("sell-plant", Args["name?", str]["num?", int], help_text="出售作物"),
|
Subcommand("sell-plant", Args["name?", str]["num?", int], help_text="出售作物"),
|
||||||
Subcommand("stealing", Args["target?", At], help_text="偷菜"),
|
Subcommand("stealing", Args["target?", At], help_text="偷菜"),
|
||||||
Subcommand("buy-point", Args["num?", int], help_text="购买农场币"),
|
Subcommand("buy-point", Args["num?", int], help_text="购买农场币"),
|
||||||
#Subcommand("sell-point", Args["num?", int], help_text="转换金币")
|
# Subcommand("sell-point", Args["num?", int], help_text="转换金币")
|
||||||
Subcommand("change-name", Args["name?", str], help_text="更改农场名"),
|
Subcommand("change-name", Args["name?", str], help_text="更改农场名"),
|
||||||
Subcommand("sign-in", help_text="农场签到"),
|
Subcommand("sign-in", help_text="农场签到"),
|
||||||
Subcommand("admin-up", Args["num?", int], help_text="农场下阶段"),
|
Subcommand("admin-up", Args["num?", int], help_text="农场下阶段"),
|
||||||
),
|
),
|
||||||
priority=5,
|
priority=5,
|
||||||
block=True,
|
block=True,
|
||||||
|
use_cmd_start=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("$main")
|
@diuse_farm.assign("$main")
|
||||||
async def _(session: Uninfo):
|
async def _(session: Uninfo):
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
|
|
||||||
if not await isRegisteredByUid(uid):
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
return
|
return
|
||||||
|
|
||||||
image = await g_pFarmManager.drawFarmByUid(uid)
|
image = await g_pFarmManager.drawFarmByUid(uid)
|
||||||
await MessageUtils.build_message(image).send(reply_to=True)
|
await MessageUtils.build_message(image).send(reply_to=True)
|
||||||
|
|
||||||
|
|
||||||
diuse_farm.shortcut(
|
diuse_farm.shortcut(
|
||||||
"农场详述",
|
"农场详述",
|
||||||
command="我的农场",
|
command="我的农场",
|
||||||
@ -163,16 +116,20 @@ diuse_farm.shortcut(
|
|||||||
prefix=True,
|
prefix=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("detail")
|
@diuse_farm.assign("detail")
|
||||||
async def _(session: Uninfo):
|
async def _(session: Uninfo):
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
|
|
||||||
if not await isRegisteredByUid(uid):
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
return
|
return
|
||||||
|
|
||||||
info = await g_pFarmManager.drawDetailFarmByUid(uid)
|
info = await g_pFarmManager.drawDetailFarmByUid(uid)
|
||||||
|
|
||||||
await MessageUtils.alc_forward_msg([info], session.self_id, BotConfig.self_nickname).send()
|
await MessageUtils.alc_forward_msg(
|
||||||
|
[info], session.self_id, BotConfig.self_nickname
|
||||||
|
).send()
|
||||||
|
|
||||||
|
|
||||||
diuse_farm.shortcut(
|
diuse_farm.shortcut(
|
||||||
"我的农场币",
|
"我的农场币",
|
||||||
@ -181,16 +138,20 @@ diuse_farm.shortcut(
|
|||||||
prefix=True,
|
prefix=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("my-point")
|
@diuse_farm.assign("my-point")
|
||||||
async def _(session: Uninfo):
|
async def _(session: Uninfo):
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
point = await g_pDBService.user.getUserPointByUid(uid)
|
point = await g_pDBService.user.getUserPointByUid(uid)
|
||||||
|
|
||||||
if point < 0:
|
if point < 0:
|
||||||
await MessageUtils.build_message("尚未开通农场,快at我发送 开通农场 开通吧").send()
|
await MessageUtils.build_message(g_sTranslation["basic"]["notFarm"]).send()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
await MessageUtils.build_message(f"你的当前农场币为: {point}").send(reply_to=True)
|
await MessageUtils.build_message(
|
||||||
|
g_sTranslation["basic"]["point"].format(point=point)
|
||||||
|
).send(reply_to=True)
|
||||||
|
|
||||||
|
|
||||||
diuse_farm.shortcut(
|
diuse_farm.shortcut(
|
||||||
"种子商店(.*?)",
|
"种子商店(.*?)",
|
||||||
@ -199,11 +160,12 @@ diuse_farm.shortcut(
|
|||||||
prefix=True,
|
prefix=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("seed-shop")
|
@diuse_farm.assign("seed-shop")
|
||||||
async def _(session: Uninfo, res: Match[tuple[str, ...]]):
|
async def _(session: Uninfo, res: Match[tuple[str, ...]]):
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
|
|
||||||
if not await isRegisteredByUid(uid):
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
return
|
return
|
||||||
|
|
||||||
if res.result is inspect._empty:
|
if res.result is inspect._empty:
|
||||||
@ -221,7 +183,12 @@ async def _(session: Uninfo, res: Match[tuple[str, ...]]):
|
|||||||
else:
|
else:
|
||||||
filterKey = first
|
filterKey = first
|
||||||
|
|
||||||
if len(raw) >= 2 and raw[1] is not None and isinstance(raw[1], str) and raw[1].isdigit():
|
if (
|
||||||
|
len(raw) >= 2
|
||||||
|
and raw[1] is not None
|
||||||
|
and isinstance(raw[1], str)
|
||||||
|
and raw[1].isdigit()
|
||||||
|
):
|
||||||
page = int(raw[1])
|
page = int(raw[1])
|
||||||
|
|
||||||
if filterKey is None:
|
if filterKey is None:
|
||||||
@ -231,6 +198,7 @@ async def _(session: Uninfo, res: Match[tuple[str, ...]]):
|
|||||||
|
|
||||||
await MessageUtils.build_message(image).send()
|
await MessageUtils.build_message(image).send()
|
||||||
|
|
||||||
|
|
||||||
diuse_farm.shortcut(
|
diuse_farm.shortcut(
|
||||||
"购买种子(?P<name>.*?)",
|
"购买种子(?P<name>.*?)",
|
||||||
command="我的农场",
|
command="我的农场",
|
||||||
@ -238,21 +206,25 @@ diuse_farm.shortcut(
|
|||||||
prefix=True,
|
prefix=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("buy-seed")
|
@diuse_farm.assign("buy-seed")
|
||||||
async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", 1)):
|
async def _(
|
||||||
|
session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", 1)
|
||||||
|
):
|
||||||
if not name.available:
|
if not name.available:
|
||||||
await MessageUtils.build_message(
|
await MessageUtils.build_message(g_sTranslation["buySeed"]["notSeed"]).finish(
|
||||||
"请在指令后跟需要购买的种子名称"
|
reply_to=True
|
||||||
).finish(reply_to=True)
|
)
|
||||||
|
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
|
|
||||||
if not await isRegisteredByUid(uid):
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
return
|
return
|
||||||
|
|
||||||
result = await g_pShopManager.buySeed(uid, name.result, num.result)
|
result = await g_pShopManager.buySeed(uid, name.result, num.result)
|
||||||
await MessageUtils.build_message(result).send(reply_to=True)
|
await MessageUtils.build_message(result).send(reply_to=True)
|
||||||
|
|
||||||
|
|
||||||
diuse_farm.shortcut(
|
diuse_farm.shortcut(
|
||||||
"我的种子",
|
"我的种子",
|
||||||
command="我的农场",
|
command="我的农场",
|
||||||
@ -260,16 +232,18 @@ diuse_farm.shortcut(
|
|||||||
prefix=True,
|
prefix=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("my-seed")
|
@diuse_farm.assign("my-seed")
|
||||||
async def _(session: Uninfo):
|
async def _(session: Uninfo):
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
|
|
||||||
if not await isRegisteredByUid(uid):
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
return
|
return
|
||||||
|
|
||||||
result = await g_pFarmManager.getUserSeedByUid(uid)
|
result = await g_pFarmManager.getUserSeedByUid(uid)
|
||||||
await MessageUtils.build_message(result).send(reply_to=True)
|
await MessageUtils.build_message(result).send(reply_to=True)
|
||||||
|
|
||||||
|
|
||||||
diuse_farm.shortcut(
|
diuse_farm.shortcut(
|
||||||
"播种(?P<name>.*?)",
|
"播种(?P<name>.*?)",
|
||||||
command="我的农场",
|
command="我的农场",
|
||||||
@ -277,16 +251,19 @@ diuse_farm.shortcut(
|
|||||||
prefix=True,
|
prefix=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("sowing")
|
@diuse_farm.assign("sowing")
|
||||||
async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1)):
|
async def _(
|
||||||
|
session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1)
|
||||||
|
):
|
||||||
if not name.available:
|
if not name.available:
|
||||||
await MessageUtils.build_message(
|
await MessageUtils.build_message(g_sTranslation["sowing"]["notSeed"]).finish(
|
||||||
"请在指令后跟需要播种的种子名称"
|
reply_to=True
|
||||||
).finish(reply_to=True)
|
)
|
||||||
|
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
|
|
||||||
if not await isRegisteredByUid(uid):
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
return
|
return
|
||||||
|
|
||||||
result = await g_pFarmManager.sowing(uid, name.result, num.result)
|
result = await g_pFarmManager.sowing(uid, name.result, num.result)
|
||||||
@ -300,16 +277,18 @@ diuse_farm.shortcut(
|
|||||||
prefix=True,
|
prefix=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("harvest")
|
@diuse_farm.assign("harvest")
|
||||||
async def _(session: Uninfo):
|
async def _(session: Uninfo):
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
|
|
||||||
if not await isRegisteredByUid(uid):
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
return
|
return
|
||||||
|
|
||||||
result = await g_pFarmManager.harvest(uid)
|
result = await g_pFarmManager.harvest(uid)
|
||||||
await MessageUtils.build_message(result).send(reply_to=True)
|
await MessageUtils.build_message(result).send(reply_to=True)
|
||||||
|
|
||||||
|
|
||||||
diuse_farm.shortcut(
|
diuse_farm.shortcut(
|
||||||
"铲除",
|
"铲除",
|
||||||
command="我的农场",
|
command="我的农场",
|
||||||
@ -317,11 +296,12 @@ diuse_farm.shortcut(
|
|||||||
prefix=True,
|
prefix=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("eradicate")
|
@diuse_farm.assign("eradicate")
|
||||||
async def _(session: Uninfo):
|
async def _(session: Uninfo):
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
|
|
||||||
if not await isRegisteredByUid(uid):
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
return
|
return
|
||||||
|
|
||||||
result = await g_pFarmManager.eradicate(uid)
|
result = await g_pFarmManager.eradicate(uid)
|
||||||
@ -335,11 +315,12 @@ diuse_farm.shortcut(
|
|||||||
prefix=True,
|
prefix=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("my-plant")
|
@diuse_farm.assign("my-plant")
|
||||||
async def _(session: Uninfo):
|
async def _(session: Uninfo):
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
|
|
||||||
if not await isRegisteredByUid(uid):
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
return
|
return
|
||||||
|
|
||||||
result = await g_pFarmManager.getUserPlantByUid(uid)
|
result = await g_pFarmManager.getUserPlantByUid(uid)
|
||||||
@ -352,15 +333,16 @@ reclamation = on_alconna(
|
|||||||
block=True,
|
block=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@reclamation.handle()
|
@reclamation.handle()
|
||||||
async def _(session: Uninfo):
|
async def _(session: Uninfo):
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
|
|
||||||
if not await isRegisteredByUid(uid):
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
return
|
return
|
||||||
|
|
||||||
condition = await g_pFarmManager.reclamationCondition(uid)
|
condition = await g_pFarmManager.reclamationCondition(uid)
|
||||||
condition += "\n 回复是将执行开垦"
|
condition += f"\n{g_sTranslation['reclamation']['confirm']}"
|
||||||
await MessageUtils.build_message(condition).send(reply_to=True)
|
await MessageUtils.build_message(condition).send(reply_to=True)
|
||||||
|
|
||||||
@waiter(waits=["message"], keep_session=True)
|
@waiter(waits=["message"], keep_session=True)
|
||||||
@ -369,7 +351,9 @@ async def _(session: Uninfo):
|
|||||||
|
|
||||||
resp = await check.wait(timeout=60)
|
resp = await check.wait(timeout=60)
|
||||||
if resp is None:
|
if resp is None:
|
||||||
await MessageUtils.build_message("等待超时").send(reply_to=True)
|
await MessageUtils.build_message(g_sTranslation["reclamation"]["timeOut"]).send(
|
||||||
|
reply_to=True
|
||||||
|
)
|
||||||
return
|
return
|
||||||
if not resp == "是":
|
if not resp == "是":
|
||||||
return
|
return
|
||||||
@ -377,6 +361,7 @@ 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(
|
diuse_farm.shortcut(
|
||||||
"出售作物(?P<name>.*?)",
|
"出售作物(?P<name>.*?)",
|
||||||
command="我的农场",
|
command="我的农场",
|
||||||
@ -384,16 +369,20 @@ diuse_farm.shortcut(
|
|||||||
prefix=True,
|
prefix=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("sell-plant")
|
@diuse_farm.assign("sell-plant")
|
||||||
async def _(session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1)):
|
async def _(
|
||||||
|
session: Uninfo, name: Match[str], num: Query[int] = AlconnaQuery("num", -1)
|
||||||
|
):
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
|
|
||||||
if not await isRegisteredByUid(uid):
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
return
|
return
|
||||||
|
|
||||||
result = await g_pShopManager.sellPlantByUid(uid, name.result, num.result)
|
result = await g_pShopManager.sellPlantByUid(uid, name.result, num.result)
|
||||||
await MessageUtils.build_message(result).send(reply_to=True)
|
await MessageUtils.build_message(result).send(reply_to=True)
|
||||||
|
|
||||||
|
|
||||||
diuse_farm.shortcut(
|
diuse_farm.shortcut(
|
||||||
"偷菜",
|
"偷菜",
|
||||||
command="我的农场",
|
command="我的农场",
|
||||||
@ -401,26 +390,32 @@ diuse_farm.shortcut(
|
|||||||
prefix=True,
|
prefix=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("stealing")
|
@diuse_farm.assign("stealing")
|
||||||
async def _(session: Uninfo, target: Match[At]):
|
async def _(session: Uninfo, target: Match[At]):
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
|
|
||||||
if not await isRegisteredByUid(uid):
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
return
|
return
|
||||||
|
|
||||||
if not target.available:
|
if not target.available:
|
||||||
await MessageUtils.build_message("请在指令后跟需要at的人").finish(reply_to=True)
|
await MessageUtils.build_message(g_sTranslation["stealing"]["noTarget"]).finish(
|
||||||
|
reply_to=True
|
||||||
|
)
|
||||||
|
|
||||||
tar = target.result
|
tar = target.result
|
||||||
result = await g_pDBService.user.isUserExist(tar.target)
|
result = await g_pDBService.user.isUserExist(tar.target)
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
await MessageUtils.build_message("目标尚未开通农场,快邀请ta开通吧").send()
|
await MessageUtils.build_message(
|
||||||
|
g_sTranslation["stealing"]["targetNotFarm"]
|
||||||
|
).send()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
result = await g_pFarmManager.stealing(uid, tar.target)
|
result = await g_pFarmManager.stealing(uid, tar.target)
|
||||||
await MessageUtils.build_message(result).send(reply_to=True)
|
await MessageUtils.build_message(result).send(reply_to=True)
|
||||||
|
|
||||||
|
|
||||||
diuse_farm.shortcut(
|
diuse_farm.shortcut(
|
||||||
"购买农场币(.*?)",
|
"购买农场币(.*?)",
|
||||||
command="我的农场",
|
command="我的农场",
|
||||||
@ -428,16 +423,17 @@ diuse_farm.shortcut(
|
|||||||
prefix=True,
|
prefix=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("buy-point")
|
@diuse_farm.assign("buy-point")
|
||||||
async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 0)):
|
async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 0)):
|
||||||
if num.result <= 0:
|
if num.result <= 0:
|
||||||
await MessageUtils.build_message(
|
await MessageUtils.build_message("请在指令后跟需要购买农场币的数量").finish(
|
||||||
"请在指令后跟需要购买农场币的数量"
|
reply_to=True
|
||||||
).finish(reply_to=True)
|
)
|
||||||
|
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
|
|
||||||
if not await isRegisteredByUid(uid):
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
return
|
return
|
||||||
|
|
||||||
result = await g_pFarmManager.buyPointByUid(uid, num.result)
|
result = await g_pFarmManager.buyPointByUid(uid, num.result)
|
||||||
@ -451,30 +447,38 @@ diuse_farm.shortcut(
|
|||||||
prefix=True,
|
prefix=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("change-name")
|
@diuse_farm.assign("change-name")
|
||||||
async def _(session: Uninfo, name: Match[str]):
|
async def _(session: Uninfo, name: Match[str]):
|
||||||
if not name.available:
|
if not name.available:
|
||||||
await MessageUtils.build_message(
|
await MessageUtils.build_message(g_sTranslation["changeName"]["noName"]).finish(
|
||||||
"请在指令后跟需要更改的农场名"
|
reply_to=True
|
||||||
).finish(reply_to=True)
|
)
|
||||||
|
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
|
|
||||||
if not await isRegisteredByUid(uid):
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
return
|
return
|
||||||
|
|
||||||
safeName = sanitize_username(name.result)
|
safeName = g_pToolManager.sanitize_username(name.result)
|
||||||
|
|
||||||
if safeName == "神秘农夫":
|
if safeName == "神秘农夫":
|
||||||
await MessageUtils.build_message("农场名不支持特殊符号!").send(reply_to=True)
|
await MessageUtils.build_message(g_sTranslation["changeName"]["error"]).send(
|
||||||
|
reply_to=True
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
result = await g_pDBService.user.updateUserNameByUid(uid, safeName)
|
result = await g_pDBService.user.updateUserNameByUid(uid, safeName)
|
||||||
|
|
||||||
if result == True:
|
if result:
|
||||||
await MessageUtils.build_message("更新农场名成功!").send(reply_to=True)
|
await MessageUtils.build_message(g_sTranslation["changeName"]["success"]).send(
|
||||||
|
reply_to=True
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
await MessageUtils.build_message("更新农场名失败!").send(reply_to=True)
|
await MessageUtils.build_message(g_sTranslation["changeName"]["error1"]).send(
|
||||||
|
reply_to=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
diuse_farm.shortcut(
|
diuse_farm.shortcut(
|
||||||
"农场签到",
|
"农场签到",
|
||||||
@ -483,16 +487,17 @@ diuse_farm.shortcut(
|
|||||||
prefix=True,
|
prefix=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("sign-in")
|
@diuse_farm.assign("sign-in")
|
||||||
async def _(session: Uninfo):
|
async def _(session: Uninfo):
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
|
|
||||||
if not await isRegisteredByUid(uid):
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
return
|
return
|
||||||
|
|
||||||
#判断签到是否正常加载
|
# 判断签到是否正常加载
|
||||||
if not g_bSignStatus:
|
if not g_bSignStatus:
|
||||||
await MessageUtils.build_message("签到功能异常!").send()
|
await MessageUtils.build_message(g_sTranslation["signIn"]["error"]).send()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -500,39 +505,50 @@ async def _(session: Uninfo):
|
|||||||
message = ""
|
message = ""
|
||||||
status = await g_pDBService.userSign.sign(uid, toDay.strftime("%Y-%m-%d"))
|
status = await g_pDBService.userSign.sign(uid, toDay.strftime("%Y-%m-%d"))
|
||||||
|
|
||||||
#如果完成签到
|
# 如果完成签到
|
||||||
if status == 1 or status == 2:
|
if status == 1 or status == 2:
|
||||||
#获取签到总天数
|
# 获取签到总天数
|
||||||
signDay = await g_pDBService.userSign.getUserSignCountByDate(uid, toDay.strftime("%Y-%m"))
|
signDay = await g_pDBService.userSign.getUserSignCountByDate(
|
||||||
exp, point = await g_pDBService.userSign.getUserSignRewardByDate(uid, toDay.strftime("%Y-%m-%d"))
|
uid, toDay.strftime("%Y-%m")
|
||||||
|
)
|
||||||
|
exp, point = await g_pDBService.userSign.getUserSignRewardByDate(
|
||||||
|
uid, toDay.strftime("%Y-%m-%d")
|
||||||
|
)
|
||||||
|
|
||||||
message += f"签到成功!累计签到天数:{signDay}\n获得经验{exp},获得金币{point}"
|
message += g_sTranslation["signIn"]["success"].format(
|
||||||
|
day=signDay, exp=exp, num=point
|
||||||
|
)
|
||||||
|
|
||||||
reward = g_pJsonManager.m_pSign['continuou'].get(f"{signDay}", None)
|
reward = g_pJsonManager.m_pSign["continuou"].get(f"{signDay}", None)
|
||||||
|
|
||||||
if reward:
|
if reward:
|
||||||
extraPoint = reward.get('point', 0)
|
extraPoint = reward.get("point", 0)
|
||||||
extraExp = reward.get('exp', 0)
|
extraExp = reward.get("exp", 0)
|
||||||
|
|
||||||
plant = reward.get('plant', {})
|
plant = reward.get("plant", {})
|
||||||
|
|
||||||
message += f"\n\n成功领取累计签到奖励:\n额外获得经验{extraExp},额外获得金币{extraPoint}"
|
message += g_sTranslation["signIn"]["grandTotal"].format(
|
||||||
|
exp=extraExp, num=extraPoint
|
||||||
|
)
|
||||||
|
|
||||||
vipPoint = reward.get('vipPoint', 0)
|
vipPoint = reward.get("vipPoint", 0)
|
||||||
|
|
||||||
if vipPoint > 0:
|
if vipPoint > 0:
|
||||||
message += f",额外获得点券{vipPoint}"
|
message += g_sTranslation["signIn"]["grandTotal1"].format(num=vipPoint)
|
||||||
|
|
||||||
if plant:
|
if plant:
|
||||||
for key, value in plant.items():
|
for key, value in plant.items():
|
||||||
message += f"\n获得{key}种子 * {value}"
|
message += g_sTranslation["signIn"]["grandTotal2"].format(
|
||||||
|
name=key, num=value
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
message = "签到失败!未知错误"
|
message = g_sTranslation["signIn"]["error1"]
|
||||||
|
|
||||||
await MessageUtils.build_message(message).send()
|
await MessageUtils.build_message(message).send()
|
||||||
|
|
||||||
# await MessageUtils.alc_forward_msg([info], session.self_id, BotConfig.self_nickname).send(reply_to=True)
|
# await MessageUtils.alc_forward_msg([info], session.self_id, BotConfig.self_nickname).send(reply_to=True)
|
||||||
|
|
||||||
|
|
||||||
diuse_farm.shortcut(
|
diuse_farm.shortcut(
|
||||||
"农场下阶段(.*?)",
|
"农场下阶段(.*?)",
|
||||||
command="我的农场",
|
command="我的农场",
|
||||||
@ -540,11 +556,12 @@ diuse_farm.shortcut(
|
|||||||
prefix=True,
|
prefix=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@diuse_farm.assign("admin-up")
|
@diuse_farm.assign("admin-up")
|
||||||
async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 0)):
|
async def _(session: Uninfo, num: Query[int] = AlconnaQuery("num", 0)):
|
||||||
uid = str(session.user.id)
|
uid = str(session.user.id)
|
||||||
|
|
||||||
if not await isRegisteredByUid(uid):
|
if not await g_pToolManager.isRegisteredByUid(uid):
|
||||||
return
|
return
|
||||||
|
|
||||||
await g_pDBService.userSoil.nextPhase(uid, num.result)
|
await g_pDBService.userSoil.nextPhase(uid, num.result)
|
||||||
|
|||||||
95
config.py
95
config.py
@ -2,15 +2,108 @@ from pathlib import Path
|
|||||||
|
|
||||||
from zhenxun.configs.path_config import DATA_PATH
|
from zhenxun.configs.path_config import DATA_PATH
|
||||||
|
|
||||||
|
# 签到状态
|
||||||
|
g_bSignStatus = True
|
||||||
|
|
||||||
|
# 是否处于Debug模式
|
||||||
g_bIsDebug = False
|
g_bIsDebug = False
|
||||||
|
|
||||||
|
# 数据库文件目录
|
||||||
g_sDBPath = DATA_PATH / "farm_db"
|
g_sDBPath = DATA_PATH / "farm_db"
|
||||||
|
|
||||||
|
# 数据库文件路径
|
||||||
g_sDBFilePath = DATA_PATH / "farm_db/farm.db"
|
g_sDBFilePath = DATA_PATH / "farm_db/farm.db"
|
||||||
|
|
||||||
|
# 农场资源文件目录
|
||||||
g_sResourcePath = Path(__file__).resolve().parent / "resource"
|
g_sResourcePath = Path(__file__).resolve().parent / "resource"
|
||||||
|
|
||||||
|
# 农场作物数据库
|
||||||
g_sPlantPath = g_sResourcePath / "db/plant.db"
|
g_sPlantPath = g_sResourcePath / "db/plant.db"
|
||||||
|
|
||||||
|
# 农场配置文件目录
|
||||||
g_sConfigPath = Path(__file__).resolve().parent / "config"
|
g_sConfigPath = Path(__file__).resolve().parent / "config"
|
||||||
|
|
||||||
|
# 农场签到文件路径
|
||||||
g_sSignInPath = g_sConfigPath / "sign_in.json"
|
g_sSignInPath = g_sConfigPath / "sign_in.json"
|
||||||
|
|
||||||
g_bSignStatus = True
|
# 农场同一文本
|
||||||
|
g_sTranslation = {
|
||||||
|
"basic": {
|
||||||
|
"notFarm": "尚未开通农场,快at我发送 开通农场 开通吧 🌱🚜",
|
||||||
|
"point": "你的当前农场币为: {point} 🌾💰",
|
||||||
|
},
|
||||||
|
"register": {
|
||||||
|
"success": "✅ 农场开通成功!\n💼 初始资金:{point}农场币 🥳🎉",
|
||||||
|
"repeat": "🎉 您已经开通农场啦~ 😄",
|
||||||
|
"error": "⚠️ 开通失败,请稍后再试 💔",
|
||||||
|
},
|
||||||
|
"buySeed": {
|
||||||
|
"notSeed": "🌱 请在指令后跟需要购买的种子名称",
|
||||||
|
"notNum": "❗️ 请输入购买数量!",
|
||||||
|
"noLevel": "🔒 你的等级不够哦,努努力吧 💪",
|
||||||
|
"noPoint": "💰 你的农场币不够哦~ 快速速氪金吧!💸",
|
||||||
|
"success": "✅ 成功购买{name},花费{total}农场币,剩余{point}农场币 🌾",
|
||||||
|
"errorSql": "❌ 购买失败,执行数据库错误!🛑",
|
||||||
|
"error": "❌ 购买出错!请检查需购买的种子名称!🔍",
|
||||||
|
},
|
||||||
|
"sowing": {
|
||||||
|
"notSeed": "🌱 请在指令后跟需要播种的种子名称",
|
||||||
|
"noSeed": "❌ 没有在你的仓库发现{name}种子,快去买点吧!🛒",
|
||||||
|
"noNum": "⚠️ 播种失败!仓库中的{name}种子数量不足,当前剩余{num}个种子 🍂",
|
||||||
|
"success": "✅ 播种{name}成功!仓库剩余{num}个种子 🌱",
|
||||||
|
"success2": "✅ 播种数量超出开垦土地数量,已将可播种土地成功播种{name}!仓库剩余{num}个种子 🌾",
|
||||||
|
"error": "❌ 播种失败,请稍后重试!⏳",
|
||||||
|
},
|
||||||
|
"harvest": {
|
||||||
|
"append": "🌾 收获作物:{name},数量为:{num},经验为:{exp} ✨",
|
||||||
|
"exp": "✨ 累计获得经验:{exp} 📈",
|
||||||
|
"no": "🤷♂️ 没有可收获的作物哦~ 不要试图拔苗助长 🚫",
|
||||||
|
"error": "❌ 收获失败,请稍后重试!⏳",
|
||||||
|
},
|
||||||
|
"eradicate": {
|
||||||
|
"success": "🗑️ 成功铲除荒废作物,累计获得经验:{exp} ✨",
|
||||||
|
"error": "❌ 没有可以铲除的作物 🚜",
|
||||||
|
},
|
||||||
|
"reclamation": {
|
||||||
|
"confirm": "⚠️ 回复“是”将执行开垦 ⛏️",
|
||||||
|
"timeOut": "⏰ 等待开垦回复超时,请重试",
|
||||||
|
"perfect": "🌟 你已经开垦了全部土地 🎉",
|
||||||
|
"next": "🔜 下次开垦所需条件:等级:{level},农场币:{num} 💰",
|
||||||
|
"next2": "🔜 下次开垦所需条件:等级:{level},农场币:{num},物品:{item} 📦",
|
||||||
|
"nextLevel": "📈 当前用户等级{level},升级所需等级为{next} ⏳",
|
||||||
|
"noNum": "💰 当前用户农场币不足,升级所需农场币为{num} 💸",
|
||||||
|
"success": "✅ 开垦土地成功!🌱",
|
||||||
|
"error": "❌ 获取开垦土地条件失败!",
|
||||||
|
"error1": "❌ 执行开垦失败!",
|
||||||
|
"error2": "❌ 未知错误{e}💥",
|
||||||
|
},
|
||||||
|
"sellPlant": {
|
||||||
|
"no": "🤷♀️ 你仓库没有可以出售的作物 🌾",
|
||||||
|
"success": "💰 成功出售所有作物,获得农场币:{point},当前农场币:{num} 🎉",
|
||||||
|
"success1": "💰 成功出售{name},获得农场币:{point},当前农场币:{num} 🥳",
|
||||||
|
"error": "❌ 出售作物{name}出错:仓库中不存在该作物 🚫",
|
||||||
|
"error1": "❌ 出售作物{name}出错:数量不足 ⚠️",
|
||||||
|
},
|
||||||
|
"stealing": {
|
||||||
|
"noTarget": "🎯 请在指令后跟需要at的人 👤",
|
||||||
|
"targetNotFarm": "🚜 目标尚未开通农场,快邀请ta开通吧 😉",
|
||||||
|
"max": "❌ 你今天可偷次数到达上限啦,手下留情吧 🙏",
|
||||||
|
"info": "🤫 成功偷到作物:{name},数量为:{num} 🍒",
|
||||||
|
"noPlant": "🌱 目标没有作物可以被偷 🌾",
|
||||||
|
"repeat": "🚫 你已经偷过目标啦,请手下留情 🙏",
|
||||||
|
},
|
||||||
|
"changeName": {
|
||||||
|
"noName": "✏️ 请在指令后跟需要更改的农场名",
|
||||||
|
"success": "✅ 更新农场名成功!🎉",
|
||||||
|
"error": "❌ 农场名不支持特殊符号!🚫",
|
||||||
|
"error1": "❌ 更新农场名失败!💔",
|
||||||
|
},
|
||||||
|
"signIn": {
|
||||||
|
"success": "📝 签到成功!累计签到天数:{day}\n🎁 获得经验{exp},获得金币{num} 💰",
|
||||||
|
"grandTotal": "\n🎉 成功领取累计签到奖励:\n✨ 额外获得经验{exp},额外获得金币{num} 🥳",
|
||||||
|
"grandTotal1": ",额外获得点券{num} 🎫",
|
||||||
|
"grandTotal2": "\n🌱 获得{name}种子 * {num} 🌟",
|
||||||
|
"error": "❗️ 签到功能异常!",
|
||||||
|
"error1": "❌ 签到失败!未知错误 💔",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import math
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
@ -46,7 +45,7 @@ class CSqlManager:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def getTableInfo(cls, tableName: str) -> list:
|
async def getTableInfo(cls, tableName: str) -> list:
|
||||||
if not re.match(r'^[A-Za-z_][A-Za-z0-9_]*$', tableName):
|
if not re.match(r"^[A-Za-z_][A-Za-z0-9_]*$", tableName):
|
||||||
raise ValueError(f"Illegal table name: {tableName}")
|
raise ValueError(f"Illegal table name: {tableName}")
|
||||||
try:
|
try:
|
||||||
cursor = await cls.m_pDB.execute(f'PRAGMA table_info("{tableName}")')
|
cursor = await cls.m_pDB.execute(f'PRAGMA table_info("{tableName}")')
|
||||||
@ -70,7 +69,7 @@ class CSqlManager:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
info = await cls.getTableInfo(tableName)
|
info = await cls.getTableInfo(tableName)
|
||||||
existing = {col['name']: col['type'].upper() for col in info}
|
existing = {col["name"]: col["type"].upper() for col in info}
|
||||||
desired = {k: v.upper() for k, v in columns.items() if k != "PRIMARY KEY"}
|
desired = {k: v.upper() for k, v in columns.items() if k != "PRIMARY KEY"}
|
||||||
primaryKey = columns.get("PRIMARY KEY", "")
|
primaryKey = columns.get("PRIMARY KEY", "")
|
||||||
|
|
||||||
@ -83,7 +82,9 @@ class CSqlManager:
|
|||||||
|
|
||||||
toAdd = [k for k in desired if k not in existing]
|
toAdd = [k for k in desired if k not in existing]
|
||||||
toRemove = [k for k in existing if k not in desired]
|
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]]
|
typeMismatch = [
|
||||||
|
k for k in desired if k in existing and existing[k] != desired[k]
|
||||||
|
]
|
||||||
|
|
||||||
if toAdd and not toRemove and not typeMismatch:
|
if toAdd and not toRemove and not typeMismatch:
|
||||||
for col in toAdd:
|
for col in toAdd:
|
||||||
@ -106,7 +107,9 @@ class CSqlManager:
|
|||||||
f'INSERT INTO "{tmpTable}" ({colsStr}) SELECT {colsStr} FROM "{tableName}";'
|
f'INSERT INTO "{tmpTable}" ({colsStr}) SELECT {colsStr} FROM "{tableName}";'
|
||||||
)
|
)
|
||||||
await cls.m_pDB.execute(f'DROP TABLE "{tableName}";')
|
await cls.m_pDB.execute(f'DROP TABLE "{tableName}";')
|
||||||
await cls.m_pDB.execute(f'ALTER TABLE "{tmpTable}" RENAME TO "{tableName}";')
|
await cls.m_pDB.execute(
|
||||||
|
f'ALTER TABLE "{tmpTable}" RENAME TO "{tableName}";'
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -131,4 +134,5 @@ class CSqlManager:
|
|||||||
logger.warning(f"数据库语句执行出错: {command}", e=e)
|
logger.warning(f"数据库语句执行出错: {command}", e=e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
g_pSqlManager = CSqlManager()
|
g_pSqlManager = CSqlManager()
|
||||||
|
|||||||
@ -1,8 +1,5 @@
|
|||||||
import ast
|
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
from unittest import result
|
|
||||||
|
|
||||||
import aiosqlite
|
import aiosqlite
|
||||||
|
|
||||||
@ -29,7 +26,9 @@ class CPlantManager:
|
|||||||
_ = os.path.exists(g_sPlantPath)
|
_ = os.path.exists(g_sPlantPath)
|
||||||
|
|
||||||
if g_bIsDebug:
|
if g_bIsDebug:
|
||||||
cls.m_pDB = await aiosqlite.connect(str(g_sPlantPath.parent / "plant-test.db"))
|
cls.m_pDB = await aiosqlite.connect(
|
||||||
|
str(g_sPlantPath.parent / "plant-test.db")
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
cls.m_pDB = await aiosqlite.connect(str(g_sPlantPath))
|
cls.m_pDB = await aiosqlite.connect(str(g_sPlantPath))
|
||||||
|
|
||||||
@ -73,7 +72,6 @@ class CPlantManager:
|
|||||||
logger.warning(f"数据库语句执行出错: {command}", e=e)
|
logger.warning(f"数据库语句执行出错: {command}", e=e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def getPlantByName(cls, name: str) -> dict | None:
|
async def getPlantByName(cls, name: str) -> dict | None:
|
||||||
"""根据作物名称查询记录
|
"""根据作物名称查询记录
|
||||||
@ -113,7 +111,7 @@ class CPlantManager:
|
|||||||
if not row:
|
if not row:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
phase = row[0].split(',')
|
phase = row[0].split(",")
|
||||||
|
|
||||||
seen = set()
|
seen = set()
|
||||||
result = []
|
result = []
|
||||||
@ -149,9 +147,9 @@ class CPlantManager:
|
|||||||
if not row:
|
if not row:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
phase = row[0].split(',')
|
phase = row[0].split(",")
|
||||||
|
|
||||||
#去重
|
# 去重
|
||||||
seen = set()
|
seen = set()
|
||||||
result = []
|
result = []
|
||||||
for x in phase:
|
for x in phase:
|
||||||
@ -184,7 +182,7 @@ class CPlantManager:
|
|||||||
if not row:
|
if not row:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
phase = row[0].split(',')
|
phase = row[0].split(",")
|
||||||
again = phase[-1] - phase[3] / 60 / 60
|
again = phase[-1] - phase[3] / 60 / 60
|
||||||
|
|
||||||
return again
|
return again
|
||||||
@ -241,7 +239,9 @@ class CPlantManager:
|
|||||||
async def listPlants(cls) -> list[dict]:
|
async def listPlants(cls) -> list[dict]:
|
||||||
"""查询所有作物记录"""
|
"""查询所有作物记录"""
|
||||||
try:
|
try:
|
||||||
async with cls.m_pDB.execute("SELECT * FROM plant ORDER BY level") as cursor:
|
async with cls.m_pDB.execute(
|
||||||
|
"SELECT * FROM plant ORDER BY level"
|
||||||
|
) as cursor:
|
||||||
rows = await cursor.fetchall()
|
rows = await cursor.fetchall()
|
||||||
return [dict(r) for r in rows]
|
return [dict(r) for r in rows]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
import math
|
import math
|
||||||
from typing import List, Union
|
|
||||||
from unittest import result
|
|
||||||
|
|
||||||
from zhenxun.services.log import logger
|
from zhenxun.services.log import logger
|
||||||
|
|
||||||
@ -13,19 +11,21 @@ class CUserDB(CSqlManager):
|
|||||||
async def initDB(cls):
|
async def initDB(cls):
|
||||||
"""初始化用户表结构,确保user表存在且字段完整"""
|
"""初始化用户表结构,确保user表存在且字段完整"""
|
||||||
userInfo = {
|
userInfo = {
|
||||||
"uid": "TEXT PRIMARY KEY", #用户Uid
|
"uid": "TEXT PRIMARY KEY", # 用户Uid
|
||||||
"name": "TEXT NOT NULL", #农场名称
|
"name": "TEXT NOT NULL", # 农场名称
|
||||||
"exp": "INTEGER DEFAULT 0", #经验值
|
"exp": "INTEGER DEFAULT 0", # 经验值
|
||||||
"point": "INTEGER DEFAULT 0", #金币
|
"point": "INTEGER DEFAULT 0", # 金币
|
||||||
"vipPoint": "INTEGER DEFAULT 0", #点券
|
"vipPoint": "INTEGER DEFAULT 0", # 点券
|
||||||
"soil": "INTEGER DEFAULT 3", #解锁土地数量
|
"soil": "INTEGER DEFAULT 3", # 解锁土地数量
|
||||||
"stealTime": "TEXT DEFAULT ''", #偷菜时间字符串
|
"stealTime": "TEXT DEFAULT ''", # 偷菜时间字符串
|
||||||
"stealCount": "INTEGER DEFAULT 0" #剩余偷菜次数
|
"stealCount": "INTEGER DEFAULT 0", # 剩余偷菜次数
|
||||||
}
|
}
|
||||||
await cls.ensureTableSchema("user", userInfo)
|
await cls.ensureTableSchema("user", userInfo)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def initUserInfoByUid(cls, uid: str, name: str = "", exp: int = 0, point: int = 500) -> Union[bool, str]:
|
async def initUserInfoByUid(
|
||||||
|
cls, uid: str, name: str = "", exp: int = 0, point: int = 500
|
||||||
|
) -> bool | str:
|
||||||
"""初始化用户信息,包含初始偷菜时间字符串与次数
|
"""初始化用户信息,包含初始偷菜时间字符串与次数
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -37,7 +37,7 @@ class CUserDB(CSqlManager):
|
|||||||
Returns:
|
Returns:
|
||||||
Union[bool, str]: False 表示失败,字符串表示成功信息
|
Union[bool, str]: False 表示失败,字符串表示成功信息
|
||||||
"""
|
"""
|
||||||
nowStr = g_pToolManager.dateTime().date().today().strftime('%Y-%m-%d')
|
nowStr = g_pToolManager.dateTime().date().today().strftime("%Y-%m-%d")
|
||||||
sql = (
|
sql = (
|
||||||
f"INSERT INTO user (uid, name, exp, point, soil, stealTime, stealCount) "
|
f"INSERT INTO user (uid, name, exp, point, soil, stealTime, stealCount) "
|
||||||
f"VALUES ({uid}, '{name}', {exp}, {point}, 3, '{nowStr}', 5)"
|
f"VALUES ({uid}, '{name}', {exp}, {point}, 3, '{nowStr}', 5)"
|
||||||
@ -51,7 +51,7 @@ class CUserDB(CSqlManager):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def getAllUsers(cls) -> List[str]:
|
async def getAllUsers(cls) -> list[str]:
|
||||||
"""获取所有用户UID列表
|
"""获取所有用户UID列表
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@ -395,8 +395,7 @@ class CUserDB(CSqlManager):
|
|||||||
return ""
|
return ""
|
||||||
try:
|
try:
|
||||||
async with cls.m_pDB.execute(
|
async with cls.m_pDB.execute(
|
||||||
"SELECT stealTime FROM user WHERE uid = ?", (uid,
|
"SELECT stealTime FROM user WHERE uid = ?", (uid,)
|
||||||
)
|
|
||||||
) as cursor:
|
) as cursor:
|
||||||
row = await cursor.fetchone()
|
row = await cursor.fetchone()
|
||||||
return row[0] if row and row[0] else ""
|
return row[0] if row and row[0] else ""
|
||||||
@ -451,11 +450,14 @@ class CUserDB(CSqlManager):
|
|||||||
return -1
|
return -1
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def updateStealCountByUid(cls, uid: str, stealCount: int) -> bool:
|
async def updateStealCountByUid(
|
||||||
|
cls, uid: str, stealTime: str, stealCount: int
|
||||||
|
) -> bool:
|
||||||
"""根据用户Uid更新剩余偷菜次数
|
"""根据用户Uid更新剩余偷菜次数
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
uid (str): 用户Uid
|
uid (str): 用户Uid
|
||||||
|
stealTime (str): 偷菜日期
|
||||||
stealCount (int): 新剩余偷菜次数
|
stealCount (int): 新剩余偷菜次数
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@ -467,7 +469,8 @@ class CUserDB(CSqlManager):
|
|||||||
try:
|
try:
|
||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"UPDATE user SET stealCount = ? WHERE uid = ?", (stealCount, uid)
|
"UPDATE user SET stealTime = ?, stealCount = ? WHERE uid = ?",
|
||||||
|
(stealTime, stealCount, uid),
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
from typing import Optional
|
|
||||||
|
|
||||||
from zhenxun.services.log import logger
|
from zhenxun.services.log import logger
|
||||||
|
|
||||||
from .database import CSqlManager
|
from .database import CSqlManager
|
||||||
@ -9,16 +7,16 @@ class CUserItemDB(CSqlManager):
|
|||||||
@classmethod
|
@classmethod
|
||||||
async def initDB(cls):
|
async def initDB(cls):
|
||||||
userItem = {
|
userItem = {
|
||||||
"uid": "TEXT NOT NULL", #用户Uid
|
"uid": "TEXT NOT NULL", # 用户Uid
|
||||||
"item": "TEXT NOT NULL", #物品名称
|
"item": "TEXT NOT NULL", # 物品名称
|
||||||
"count": "INTEGER NOT NULL DEFAULT 0", #数量
|
"count": "INTEGER NOT NULL DEFAULT 0", # 数量
|
||||||
"PRIMARY KEY": "(uid, item)"
|
"PRIMARY KEY": "(uid, item)",
|
||||||
}
|
}
|
||||||
|
|
||||||
await cls.ensureTableSchema("userItem", userItem)
|
await cls.ensureTableSchema("userItem", userItem)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def getUserItemByName(cls, uid: str, item: str) -> Optional[int]:
|
async def getUserItemByName(cls, uid: str, item: str) -> int | None:
|
||||||
"""根据道具名称查询某一项数量
|
"""根据道具名称查询某一项数量
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -32,13 +30,12 @@ class CUserItemDB(CSqlManager):
|
|||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
async with cls.m_pDB.execute(
|
async with cls.m_pDB.execute(
|
||||||
"SELECT count FROM userItem WHERE uid = ? AND item = ?",
|
"SELECT count FROM userItem WHERE uid = ? AND item = ?", (uid, item)
|
||||||
(uid, item)
|
|
||||||
) as cursor:
|
) as cursor:
|
||||||
row = await cursor.fetchone()
|
row = await cursor.fetchone()
|
||||||
return row[0] if row else None
|
return row[0] if row else None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"getUserItemByName查询失败!", e=e)
|
logger.warning("getUserItemByName查询失败!", e=e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -55,13 +52,12 @@ class CUserItemDB(CSqlManager):
|
|||||||
return {}
|
return {}
|
||||||
try:
|
try:
|
||||||
cursor = await cls.m_pDB.execute(
|
cursor = await cls.m_pDB.execute(
|
||||||
"SELECT item, count FROM userItem WHERE uid = ?",
|
"SELECT item, count FROM userItem WHERE uid = ?", (uid,)
|
||||||
(uid,)
|
|
||||||
)
|
)
|
||||||
rows = await cursor.fetchall()
|
rows = await cursor.fetchall()
|
||||||
return {row["item"]: row["count"] for row in rows}
|
return {row["item"]: row["count"] for row in rows}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"getUserItemByUid查询失败!", e=e)
|
logger.warning("getUserItemByUid查询失败!", e=e)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -80,12 +76,11 @@ class CUserItemDB(CSqlManager):
|
|||||||
try:
|
try:
|
||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"DELETE FROM userItem WHERE uid = ? AND item = ?",
|
"DELETE FROM userItem WHERE uid = ? AND item = ?", (uid, item)
|
||||||
(uid, item)
|
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"deleteUserItemByName失败!", e=e)
|
logger.warning("deleteUserItemByName失败!", e=e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -106,17 +101,16 @@ class CUserItemDB(CSqlManager):
|
|||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
if count <= 0:
|
if count <= 0:
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"DELETE FROM userItem WHERE uid = ? AND item = ?",
|
"DELETE FROM userItem WHERE uid = ? AND item = ?", (uid, item)
|
||||||
(uid, item)
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"UPDATE userItem SET count = ? WHERE uid = ? AND item = ?",
|
"UPDATE userItem SET count = ? WHERE uid = ? AND item = ?",
|
||||||
(count, uid, item)
|
(count, uid, item),
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"updateUserItemByName失败!", e=e)
|
logger.warning("updateUserItemByName失败!", e=e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -136,8 +130,7 @@ class CUserItemDB(CSqlManager):
|
|||||||
try:
|
try:
|
||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
async with cls.m_pDB.execute(
|
async with cls.m_pDB.execute(
|
||||||
"SELECT count FROM userItem WHERE uid = ? AND item = ?",
|
"SELECT count FROM userItem WHERE uid = ? AND item = ?", (uid, item)
|
||||||
(uid, item)
|
|
||||||
) as cursor:
|
) as cursor:
|
||||||
row = await cursor.fetchone()
|
row = await cursor.fetchone()
|
||||||
|
|
||||||
@ -146,20 +139,20 @@ class CUserItemDB(CSqlManager):
|
|||||||
if newCount <= 0:
|
if newCount <= 0:
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"DELETE FROM userItem WHERE uid = ? AND item = ?",
|
"DELETE FROM userItem WHERE uid = ? AND item = ?",
|
||||||
(uid, item)
|
(uid, item),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"UPDATE userItem SET count = ? WHERE uid = ? AND item = ?",
|
"UPDATE userItem SET count = ? WHERE uid = ? AND item = ?",
|
||||||
(newCount, uid, item)
|
(newCount, uid, item),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if count > 0:
|
if count > 0:
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"INSERT INTO userItem (uid, item, count) VALUES (?, ?, ?)",
|
"INSERT INTO userItem (uid, item, count) VALUES (?, ?, ?)",
|
||||||
(uid, item, count)
|
(uid, item, count),
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"addUserItemByUid失败!", e=e)
|
logger.warning("addUserItemByUid失败!", e=e)
|
||||||
return False
|
return False
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
from typing import Dict, Optional
|
|
||||||
|
|
||||||
from zhenxun.services.log import logger
|
from zhenxun.services.log import logger
|
||||||
|
|
||||||
from .database import CSqlManager
|
from .database import CSqlManager
|
||||||
@ -9,10 +7,10 @@ class CUserPlantDB(CSqlManager):
|
|||||||
@classmethod
|
@classmethod
|
||||||
async def initDB(cls):
|
async def initDB(cls):
|
||||||
userPlant = {
|
userPlant = {
|
||||||
"uid": "TEXT NOT NULL", #用户Uid
|
"uid": "TEXT NOT NULL", # 用户Uid
|
||||||
"plant": "TEXT NOT NULL", #作物名称
|
"plant": "TEXT NOT NULL", # 作物名称
|
||||||
"count": "INTEGER NOT NULL DEFAULT 0", #数量
|
"count": "INTEGER NOT NULL DEFAULT 0", # 数量
|
||||||
"PRIMARY KEY": "(uid, plant)"
|
"PRIMARY KEY": "(uid, plant)",
|
||||||
}
|
}
|
||||||
|
|
||||||
await cls.ensureTableSchema("userPlant", userPlant)
|
await cls.ensureTableSchema("userPlant", userPlant)
|
||||||
@ -31,33 +29,33 @@ class CUserPlantDB(CSqlManager):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
#检查是否已存在该作物
|
# 检查是否已存在该作物
|
||||||
async with cls.m_pDB.execute(
|
async with cls.m_pDB.execute(
|
||||||
"SELECT count FROM userPlant WHERE uid = ? AND plant = ?",
|
"SELECT count FROM userPlant WHERE uid = ? AND plant = ?",
|
||||||
(uid, plant)
|
(uid, plant),
|
||||||
) as cursor:
|
) as cursor:
|
||||||
row = await cursor.fetchone()
|
row = await cursor.fetchone()
|
||||||
|
|
||||||
if row:
|
if row:
|
||||||
#如果作物已存在,则更新数量
|
# 如果作物已存在,则更新数量
|
||||||
new_count = row[0] + count
|
new_count = row[0] + count
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"UPDATE userPlant SET count = ? WHERE uid = ? AND plant = ?",
|
"UPDATE userPlant SET count = ? WHERE uid = ? AND plant = ?",
|
||||||
(new_count, uid, plant)
|
(new_count, uid, plant),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
#如果作物不存在,则插入新记录
|
# 如果作物不存在,则插入新记录
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"INSERT INTO userPlant (uid, plant, count) VALUES (?, ?, ?)",
|
"INSERT INTO userPlant (uid, plant, count) VALUES (?, ?, ?)",
|
||||||
(uid, plant, count)
|
(uid, plant, count),
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"addUserPlantByUid 失败!", e=e)
|
logger.warning("addUserPlantByUid 失败!", e=e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def getUserPlantByUid(cls, uid: str) -> Dict[str, int]:
|
async def getUserPlantByUid(cls, uid: str) -> dict[str, int]:
|
||||||
"""根据用户uid获取全部作物信息
|
"""根据用户uid获取全部作物信息
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -67,14 +65,13 @@ class CUserPlantDB(CSqlManager):
|
|||||||
Dict[str, int]: 作物名称和数量
|
Dict[str, int]: 作物名称和数量
|
||||||
"""
|
"""
|
||||||
cursor = await cls.m_pDB.execute(
|
cursor = await cls.m_pDB.execute(
|
||||||
"SELECT plant, count FROM userPlant WHERE uid=?",
|
"SELECT plant, count FROM userPlant WHERE uid=?", (uid,)
|
||||||
(uid,)
|
|
||||||
)
|
)
|
||||||
rows = await cursor.fetchall()
|
rows = await cursor.fetchall()
|
||||||
return {row["plant"]: row["count"] for row in rows}
|
return {row["plant"]: row["count"] for row in rows}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def getUserPlantByName(cls, uid: str, plant: str) -> Optional[int]:
|
async def getUserPlantByName(cls, uid: str, plant: str) -> int | None:
|
||||||
"""根据作物名称获取用户的作物数量
|
"""根据作物名称获取用户的作物数量
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -86,13 +83,12 @@ class CUserPlantDB(CSqlManager):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
async with cls.m_pDB.execute(
|
async with cls.m_pDB.execute(
|
||||||
"SELECT count FROM userPlant WHERE uid = ? AND plant = ?",
|
"SELECT count FROM userPlant WHERE uid = ? AND plant = ?", (uid, plant)
|
||||||
(uid, plant)
|
|
||||||
) as cursor:
|
) as cursor:
|
||||||
row = await cursor.fetchone()
|
row = await cursor.fetchone()
|
||||||
return row[0] if row else None
|
return row[0] if row else None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"getUserPlantByName 查询失败!", e=e)
|
logger.warning("getUserPlantByName 查询失败!", e=e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -114,11 +110,11 @@ class CUserPlantDB(CSqlManager):
|
|||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"UPDATE userPlant SET count = ? WHERE uid = ? AND plant = ?",
|
"UPDATE userPlant SET count = ? WHERE uid = ? AND plant = ?",
|
||||||
(count, uid, plant)
|
(count, uid, plant),
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"updateUserPlantByName失败!", e=e)
|
logger.warning("updateUserPlantByName失败!", e=e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -135,10 +131,9 @@ class CUserPlantDB(CSqlManager):
|
|||||||
try:
|
try:
|
||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"DELETE FROM userPlant WHERE uid = ? AND plant = ?",
|
"DELETE FROM userPlant WHERE uid = ? AND plant = ?", (uid, plant)
|
||||||
(uid, plant)
|
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"deleteUserPlantByName 失败!", e=e)
|
logger.warning("deleteUserPlantByName 失败!", e=e)
|
||||||
return False
|
return False
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
from typing import Optional
|
|
||||||
|
|
||||||
from zhenxun.services.log import logger
|
from zhenxun.services.log import logger
|
||||||
|
|
||||||
from .database import CSqlManager
|
from .database import CSqlManager
|
||||||
@ -9,10 +7,10 @@ class CUserSeedDB(CSqlManager):
|
|||||||
@classmethod
|
@classmethod
|
||||||
async def initDB(cls):
|
async def initDB(cls):
|
||||||
userSeed = {
|
userSeed = {
|
||||||
"uid": "TEXT NOT NULL", #用户Uid
|
"uid": "TEXT NOT NULL", # 用户Uid
|
||||||
"seed": "TEXT NOT NULL", #种子名称
|
"seed": "TEXT NOT NULL", # 种子名称
|
||||||
"count": "INTEGER NOT NULL DEFAULT 0", #数量
|
"count": "INTEGER NOT NULL DEFAULT 0", # 数量
|
||||||
"PRIMARY KEY": "(uid, seed)"
|
"PRIMARY KEY": "(uid, seed)",
|
||||||
}
|
}
|
||||||
|
|
||||||
await cls.ensureTableSchema("userSeed", userSeed)
|
await cls.ensureTableSchema("userSeed", userSeed)
|
||||||
@ -32,8 +30,7 @@ class CUserSeedDB(CSqlManager):
|
|||||||
try:
|
try:
|
||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
async with cls.m_pDB.execute(
|
async with cls.m_pDB.execute(
|
||||||
"SELECT count FROM userSeed WHERE uid = ? AND seed = ?",
|
"SELECT count FROM userSeed WHERE uid = ? AND seed = ?", (uid, seed)
|
||||||
(uid, seed)
|
|
||||||
) as cursor:
|
) as cursor:
|
||||||
row = await cursor.fetchone()
|
row = await cursor.fetchone()
|
||||||
|
|
||||||
@ -41,23 +38,22 @@ class CUserSeedDB(CSqlManager):
|
|||||||
newCount = row[0] + count
|
newCount = row[0] + count
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?",
|
"UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?",
|
||||||
(newCount, uid, seed)
|
(newCount, uid, seed),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
newCount = count
|
newCount = count
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"INSERT INTO userSeed (uid, seed, count) VALUES (?, ?, ?)",
|
"INSERT INTO userSeed (uid, seed, count) VALUES (?, ?, ?)",
|
||||||
(uid, seed, count)
|
(uid, seed, count),
|
||||||
)
|
)
|
||||||
|
|
||||||
if newCount <= 0:
|
if newCount <= 0:
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"DELETE FROM userSeed WHERE uid = ? AND seed = ?",
|
"DELETE FROM userSeed WHERE uid = ? AND seed = ?", (uid, seed)
|
||||||
(uid, seed)
|
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"addUserSeedByUid 失败!", e=e)
|
logger.warning("addUserSeedByUid 失败!", e=e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -72,7 +68,7 @@ class CUserSeedDB(CSqlManager):
|
|||||||
else:
|
else:
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"INSERT INTO userSeed (uid, seed, count) VALUES (?, ?, ?)",
|
"INSERT INTO userSeed (uid, seed, count) VALUES (?, ?, ?)",
|
||||||
(uid, seed, newCount)
|
(uid, seed, newCount),
|
||||||
)
|
)
|
||||||
|
|
||||||
if newCount <= 0:
|
if newCount <= 0:
|
||||||
@ -80,12 +76,11 @@ class CUserSeedDB(CSqlManager):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"_addUserSeedByUid 失败!", e=e)
|
logger.warning("_addUserSeedByUid 失败!", e=e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def getUserSeedByName(cls, uid: str, seed: str) -> Optional[int]:
|
async def getUserSeedByName(cls, uid: str, seed: str) -> int | None:
|
||||||
"""根据种子名称获取种子数量
|
"""根据种子名称获取种子数量
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -98,13 +93,12 @@ class CUserSeedDB(CSqlManager):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
async with cls.m_pDB.execute(
|
async with cls.m_pDB.execute(
|
||||||
"SELECT count FROM userSeed WHERE uid = ? AND seed = ?",
|
"SELECT count FROM userSeed WHERE uid = ? AND seed = ?", (uid, seed)
|
||||||
(uid, seed)
|
|
||||||
) as cursor:
|
) as cursor:
|
||||||
row = await cursor.fetchone()
|
row = await cursor.fetchone()
|
||||||
return row[0] if row else None
|
return row[0] if row else None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"getUserSeedByName 查询失败!", e=e)
|
logger.warning("getUserSeedByName 查询失败!", e=e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -119,8 +113,7 @@ class CUserSeedDB(CSqlManager):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
cursor = await cls.m_pDB.execute(
|
cursor = await cls.m_pDB.execute(
|
||||||
"SELECT seed, count FROM userSeed WHERE uid=?",
|
"SELECT seed, count FROM userSeed WHERE uid=?", (uid,)
|
||||||
(uid,)
|
|
||||||
)
|
)
|
||||||
rows = await cursor.fetchall()
|
rows = await cursor.fetchall()
|
||||||
return {row["seed"]: row["count"] for row in rows}
|
return {row["seed"]: row["count"] for row in rows}
|
||||||
@ -144,11 +137,11 @@ class CUserSeedDB(CSqlManager):
|
|||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?",
|
"UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?",
|
||||||
(count, uid, seed)
|
(count, uid, seed),
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"updateUserSeedByName失败!", e=e)
|
logger.warning("updateUserSeedByName失败!", e=e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -170,11 +163,11 @@ class CUserSeedDB(CSqlManager):
|
|||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?",
|
"UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?",
|
||||||
(count, uid, seed)
|
(count, uid, seed),
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"updateUserSeedByName失败!", e=e)
|
logger.warning("updateUserSeedByName失败!", e=e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -191,12 +184,11 @@ class CUserSeedDB(CSqlManager):
|
|||||||
try:
|
try:
|
||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"DELETE FROM userSeed WHERE uid = ? AND seed = ?",
|
"DELETE FROM userSeed WHERE uid = ? AND seed = ?", (uid, seed)
|
||||||
(uid, seed)
|
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"deleteUserSeedByName 删除失败!", e=e)
|
logger.warning("deleteUserSeedByName 删除失败!", e=e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -212,10 +204,9 @@ class CUserSeedDB(CSqlManager):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"DELETE FROM userSeed WHERE uid = ? AND seed = ?",
|
"DELETE FROM userSeed WHERE uid = ? AND seed = ?", (uid, seed)
|
||||||
(uid, seed)
|
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"deleteUserSeedByName 删除失败!", e=e)
|
logger.warning("deleteUserSeedByName 删除失败!", e=e)
|
||||||
return False
|
return False
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import calendar
|
import calendar
|
||||||
import random
|
import random
|
||||||
from datetime import date, datetime, timedelta
|
from datetime import timedelta
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
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
|
||||||
@ -16,27 +15,27 @@ from .database import CSqlManager
|
|||||||
class CUserSignDB(CSqlManager):
|
class CUserSignDB(CSqlManager):
|
||||||
@classmethod
|
@classmethod
|
||||||
async def initDB(cls):
|
async def initDB(cls):
|
||||||
#userSignLog 表结构,每条为一次签到事件
|
# userSignLog 表结构,每条为一次签到事件
|
||||||
userSignLog = {
|
userSignLog = {
|
||||||
"uid": "TEXT NOT NULL", #用户ID
|
"uid": "TEXT NOT NULL", # 用户ID
|
||||||
"signDate": "DATE NOT NULL", #签到日期
|
"signDate": "DATE NOT NULL", # 签到日期
|
||||||
"isSupplement": "TINYINT NOT NULL DEFAULT 0", #是否补签
|
"isSupplement": "TINYINT NOT NULL DEFAULT 0", # 是否补签
|
||||||
"exp": "INT NOT NULL DEFAULT 0", #当天签到经验
|
"exp": "INT NOT NULL DEFAULT 0", # 当天签到经验
|
||||||
"point": "INT NOT NULL DEFAULT 0", #当天签到金币
|
"point": "INT NOT NULL DEFAULT 0", # 当天签到金币
|
||||||
"createdAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime'))",#创建时间
|
"createdAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime'))", # 创建时间
|
||||||
"PRIMARY KEY": "(uid, signDate)"
|
"PRIMARY KEY": "(uid, signDate)",
|
||||||
}
|
}
|
||||||
|
|
||||||
#userSignSummary 表结构,每用户一行用于缓存签到状态
|
# userSignSummary 表结构,每用户一行用于缓存签到状态
|
||||||
userSignSummary = {
|
userSignSummary = {
|
||||||
"uid": "TEXT PRIMARY KEY NOT NULL", #用户ID
|
"uid": "TEXT PRIMARY KEY NOT NULL", # 用户ID
|
||||||
"totalSignDays": "INT NOT NULL DEFAULT 0", #累计签到天数
|
"totalSignDays": "INT NOT NULL DEFAULT 0", # 累计签到天数
|
||||||
"currentMonth": "CHAR(7) NOT NULL DEFAULT ''", #当前月份(如2025-05)
|
"currentMonth": "CHAR(7) NOT NULL DEFAULT ''", # 当前月份(如2025-05)
|
||||||
"monthSignDays": "INT NOT NULL DEFAULT 0", #本月签到次数
|
"monthSignDays": "INT NOT NULL DEFAULT 0", # 本月签到次数
|
||||||
"lastSignDate": "DATE DEFAULT NULL", #上次签到日期
|
"lastSignDate": "DATE DEFAULT NULL", # 上次签到日期
|
||||||
"continuousDays": "INT NOT NULL DEFAULT 0", #连续签到天数
|
"continuousDays": "INT NOT NULL DEFAULT 0", # 连续签到天数
|
||||||
"supplementCount": "INT NOT NULL DEFAULT 0", #补签次数
|
"supplementCount": "INT NOT NULL DEFAULT 0", # 补签次数
|
||||||
"updatedAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime'))"#更新时间
|
"updatedAt": "DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime'))", # 更新时间
|
||||||
}
|
}
|
||||||
|
|
||||||
await cls.ensureTableSchema("userSignLog", userSignLog)
|
await cls.ensureTableSchema("userSignLog", userSignLog)
|
||||||
@ -57,15 +56,15 @@ class CUserSignDB(CSqlManager):
|
|||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
async with cls.m_pDB.execute(
|
async with cls.m_pDB.execute(
|
||||||
"SELECT exp, point FROM userSignLog WHERE uid=? AND signDate=?",
|
"SELECT exp, point FROM userSignLog WHERE uid=? AND signDate=?",
|
||||||
(uid, date)
|
(uid, date),
|
||||||
) as cursor:
|
) as cursor:
|
||||||
row = await cursor.fetchone()
|
row = await cursor.fetchone()
|
||||||
|
|
||||||
if row is None:
|
if row is None:
|
||||||
return 0, 0
|
return 0, 0
|
||||||
|
|
||||||
exp = row['exp']
|
exp = row["exp"]
|
||||||
point = row['point']
|
point = row["point"]
|
||||||
|
|
||||||
return exp, point
|
return exp, point
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -114,7 +113,7 @@ class CUserSignDB(CSqlManager):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def sign(cls, uid: str, signDate: str = '') -> int:
|
async def sign(cls, uid: str, signDate: str = "") -> int:
|
||||||
"""签到
|
"""签到
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -151,20 +150,35 @@ class CUserSignDB(CSqlManager):
|
|||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"INSERT INTO userSignLog (uid, signDate, isSupplement, exp, point) VALUES (?, ?, ?, ?, ?)",
|
"INSERT INTO userSignLog (uid, signDate, isSupplement, exp, point) VALUES (?, ?, ?, ?, ?)",
|
||||||
(uid, signDate, isSupplement, exp, point)
|
(uid, signDate, isSupplement, exp, point),
|
||||||
)
|
)
|
||||||
|
|
||||||
cursor = await cls.m_pDB.execute("SELECT * FROM userSignSummary WHERE uid=?", (uid,))
|
cursor = await cls.m_pDB.execute(
|
||||||
|
"SELECT * FROM userSignSummary WHERE uid=?", (uid,)
|
||||||
|
)
|
||||||
row = await cursor.fetchone()
|
row = await cursor.fetchone()
|
||||||
|
|
||||||
currentMonth = signDate[:7]
|
currentMonth = signDate[:7]
|
||||||
if row:
|
if row:
|
||||||
monthSignDays = row['monthSignDays'] + 1 if row['currentMonth'] == currentMonth else 1
|
monthSignDays = (
|
||||||
totalSignDays = row['totalSignDays']
|
row["monthSignDays"] + 1
|
||||||
lastDate = row['lastSignDate']
|
if row["currentMonth"] == currentMonth
|
||||||
prevDate = (g_pToolManager.dateTime().strptime(signDate, "%Y-%m-%d") - timedelta(days=1)).strftime("%Y-%m-%d")
|
else 1
|
||||||
continuousDays = row['continuousDays'] + 1 if lastDate == prevDate else 1
|
)
|
||||||
supplementCount = row['supplementCount'] + 1 if isSupplement else row['supplementCount']
|
totalSignDays = row["totalSignDays"]
|
||||||
|
lastDate = row["lastSignDate"]
|
||||||
|
prevDate = (
|
||||||
|
g_pToolManager.dateTime().strptime(signDate, "%Y-%m-%d")
|
||||||
|
- timedelta(days=1)
|
||||||
|
).strftime("%Y-%m-%d")
|
||||||
|
continuousDays = (
|
||||||
|
row["continuousDays"] + 1 if lastDate == prevDate else 1
|
||||||
|
)
|
||||||
|
supplementCount = (
|
||||||
|
row["supplementCount"] + 1
|
||||||
|
if isSupplement
|
||||||
|
else row["supplementCount"]
|
||||||
|
)
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"""
|
"""
|
||||||
UPDATE userSignSummary
|
UPDATE userSignSummary
|
||||||
@ -176,7 +190,14 @@ class CUserSignDB(CSqlManager):
|
|||||||
supplementCount=?
|
supplementCount=?
|
||||||
WHERE uid=?
|
WHERE uid=?
|
||||||
""",
|
""",
|
||||||
(currentMonth, monthSignDays, signDate, continuousDays, supplementCount, uid)
|
(
|
||||||
|
currentMonth,
|
||||||
|
monthSignDays,
|
||||||
|
signDate,
|
||||||
|
continuousDays,
|
||||||
|
supplementCount,
|
||||||
|
uid,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
totalSignDays = 1
|
totalSignDays = 1
|
||||||
@ -186,18 +207,26 @@ class CUserSignDB(CSqlManager):
|
|||||||
(uid, totalSignDays, currentMonth, monthSignDays, lastSignDate, continuousDays, supplementCount)
|
(uid, totalSignDays, currentMonth, monthSignDays, lastSignDate, continuousDays, supplementCount)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(uid, 1, currentMonth, 1, signDate, 1, 1 if isSupplement else 0)
|
(
|
||||||
|
uid,
|
||||||
|
1,
|
||||||
|
currentMonth,
|
||||||
|
1,
|
||||||
|
signDate,
|
||||||
|
1,
|
||||||
|
1 if isSupplement else 0,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
#计算累签奖励
|
# 计算累签奖励
|
||||||
reward = g_pJsonManager.m_pSign['continuou'].get(f"{totalSignDays}", None)
|
reward = g_pJsonManager.m_pSign["continuou"].get(f"{totalSignDays}", None)
|
||||||
|
|
||||||
if reward:
|
if reward:
|
||||||
point += reward.get('point', 0)
|
point += reward.get("point", 0)
|
||||||
exp += reward.get('exp', 0)
|
exp += reward.get("exp", 0)
|
||||||
vipPoint = reward.get('vipPoint', 0)
|
vipPoint = reward.get("vipPoint", 0)
|
||||||
|
|
||||||
plant = reward.get('plant', {})
|
plant = reward.get("plant", {})
|
||||||
|
|
||||||
if plant:
|
if plant:
|
||||||
for key, value in plant.items():
|
for key, value in plant.items():
|
||||||
@ -206,7 +235,7 @@ class CUserSignDB(CSqlManager):
|
|||||||
if g_bIsDebug:
|
if g_bIsDebug:
|
||||||
exp += 9999
|
exp += 9999
|
||||||
|
|
||||||
#向数据库更新
|
# 向数据库更新
|
||||||
currentExp = await g_pDBService.user.getUserExpByUid(uid)
|
currentExp = await g_pDBService.user.getUserExpByUid(uid)
|
||||||
await g_pDBService.user.updateUserExpByUid(uid, currentExp + exp)
|
await g_pDBService.user.updateUserExpByUid(uid, currentExp + exp)
|
||||||
|
|
||||||
@ -215,7 +244,9 @@ class CUserSignDB(CSqlManager):
|
|||||||
|
|
||||||
if vipPoint > 0:
|
if vipPoint > 0:
|
||||||
currentVipPoint = await g_pDBService.user.getUserVipPointByUid(uid)
|
currentVipPoint = await g_pDBService.user.getUserVipPointByUid(uid)
|
||||||
await g_pDBService.user.updateUserVipPointByUid(uid, currentVipPoint + vipPoint)
|
await g_pDBService.user.updateUserVipPointByUid(
|
||||||
|
uid, currentVipPoint + vipPoint
|
||||||
|
)
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -224,7 +255,7 @@ class CUserSignDB(CSqlManager):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def drawSignCalendarImage(cls, uid: str, year: int, month: int):
|
async def drawSignCalendarImage(cls, uid: str, year: int, month: int):
|
||||||
#绘制签到图,自动提取数据库中该用户该月的签到天数
|
# 绘制签到图,自动提取数据库中该用户该月的签到天数
|
||||||
cellSize = 80
|
cellSize = 80
|
||||||
padding = 40
|
padding = 40
|
||||||
titleHeight = 80
|
titleHeight = 80
|
||||||
|
|||||||
@ -1,10 +1,7 @@
|
|||||||
from typing import Optional
|
|
||||||
|
|
||||||
from zhenxun.services.log import logger
|
from zhenxun.services.log import logger
|
||||||
|
|
||||||
from ..config import g_bIsDebug
|
from ..config import g_bIsDebug
|
||||||
from ..dbService import g_pDBService
|
from ..dbService import g_pDBService
|
||||||
from ..json import g_pJsonManager
|
|
||||||
from ..tool import g_pToolManager
|
from ..tool import g_pToolManager
|
||||||
from .database import CSqlManager
|
from .database import CSqlManager
|
||||||
|
|
||||||
@ -14,17 +11,17 @@ class CUserSoilDB(CSqlManager):
|
|||||||
async def initDB(cls):
|
async def initDB(cls):
|
||||||
userSoil = {
|
userSoil = {
|
||||||
"uid": "TEXT NOT NULL",
|
"uid": "TEXT NOT NULL",
|
||||||
"soilIndex": "INTEGER NOT NULL", #地块索引从1开始
|
"soilIndex": "INTEGER NOT NULL", # 地块索引从1开始
|
||||||
"plantName": "TEXT DEFAULT ''", #作物名称
|
"plantName": "TEXT DEFAULT ''", # 作物名称
|
||||||
"plantTime": "INTEGER DEFAULT 0", #播种时间
|
"plantTime": "INTEGER DEFAULT 0", # 播种时间
|
||||||
"matureTime": "INTEGER DEFAULT 0", #成熟时间
|
"matureTime": "INTEGER DEFAULT 0", # 成熟时间
|
||||||
"soilLevel": "INTEGER DEFAULT 0", #土地等级 0=普通地,1=红土地,2=黑土地,3=金土地
|
"soilLevel": "INTEGER DEFAULT 0", # 土地等级 0=普通地,1=红土地,2=黑土地,3=金土地
|
||||||
"wiltStatus": "INTEGER DEFAULT 0", #枯萎状态 0=未枯萎,1=枯萎
|
"wiltStatus": "INTEGER DEFAULT 0", # 枯萎状态 0=未枯萎,1=枯萎
|
||||||
"fertilizerStatus": "INTEGER DEFAULT 0",#施肥状态 0=未施肥,1=施肥 2=增肥
|
"fertilizerStatus": "INTEGER DEFAULT 0", # 施肥状态 0=未施肥,1=施肥 2=增肥
|
||||||
"bugStatus": "INTEGER DEFAULT 0", #虫害状态 0=无虫害,1=有虫害
|
"bugStatus": "INTEGER DEFAULT 0", # 虫害状态 0=无虫害,1=有虫害
|
||||||
"weedStatus": "INTEGER DEFAULT 0", #杂草状态 0=无杂草,1=有杂草
|
"weedStatus": "INTEGER DEFAULT 0", # 杂草状态 0=无杂草,1=有杂草
|
||||||
"waterStatus": "INTEGER DEFAULT 0", #缺水状态 0=不缺水,1=缺水
|
"waterStatus": "INTEGER DEFAULT 0", # 缺水状态 0=不缺水,1=缺水
|
||||||
"harvestCount": "INTEGER DEFAULT 0", #收获次数
|
"harvestCount": "INTEGER DEFAULT 0", # 收获次数
|
||||||
"PRIMARY KEY": "(uid, soilIndex)",
|
"PRIMARY KEY": "(uid, soilIndex)",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,30 +42,30 @@ class CUserSoilDB(CSqlManager):
|
|||||||
if not soilInfo:
|
if not soilInfo:
|
||||||
return
|
return
|
||||||
|
|
||||||
plantInfo = await g_pDBService.plant.getPlantByName(soilInfo['plantName'])
|
plantInfo = await g_pDBService.plant.getPlantByName(soilInfo["plantName"])
|
||||||
|
|
||||||
if not plantInfo:
|
if not plantInfo:
|
||||||
return
|
return
|
||||||
|
|
||||||
currentTime = g_pToolManager.dateTime().now().timestamp()
|
currentTime = g_pToolManager.dateTime().now().timestamp()
|
||||||
phaseList = await g_pDBService.plant.getPlantPhaseByName(soilInfo['plantName'])
|
phaseList = await g_pDBService.plant.getPlantPhaseByName(soilInfo["plantName"])
|
||||||
|
|
||||||
if currentTime >= soilInfo['matureTime']:
|
if currentTime >= soilInfo["matureTime"]:
|
||||||
return
|
return
|
||||||
|
|
||||||
elapsedTime = currentTime - soilInfo['plantTime']
|
elapsedTime = currentTime - soilInfo["plantTime"]
|
||||||
currentStage = currentStage = sum(1 for thr in phaseList if elapsedTime >= thr)
|
currentStage = currentStage = sum(1 for thr in phaseList if elapsedTime >= thr)
|
||||||
|
|
||||||
t = int(soilInfo['plantTime']) - phaseList[currentStage]
|
t = int(soilInfo["plantTime"]) - phaseList[currentStage]
|
||||||
s = int(soilInfo['matureTime']) - phaseList[currentStage]
|
s = int(soilInfo["matureTime"]) - phaseList[currentStage]
|
||||||
|
|
||||||
await cls.updateUserSoilFields(uid, soilIndex,
|
await cls.updateUserSoilFields(
|
||||||
{
|
uid, soilIndex, {"plantTime": t, "matureTime": s}
|
||||||
"plantTime": t,
|
)
|
||||||
"matureTime": s
|
|
||||||
})
|
|
||||||
|
|
||||||
logger.debug(f"当前阶段{currentStage}, 阶段时间{phaseList[currentStage]}, 播种时间{t}, 收获时间{s}")
|
logger.debug(
|
||||||
|
f"当前阶段{currentStage}, 阶段时间{phaseList[currentStage]}, 播种时间{t}, 收获时间{s}"
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def getUserFarmByUid(cls, uid: str) -> dict:
|
async def getUserFarmByUid(cls, uid: str) -> dict:
|
||||||
@ -95,7 +92,7 @@ class CUserSoilDB(CSqlManager):
|
|||||||
Returns:
|
Returns:
|
||||||
bool: 如果旧表不存在则返回 False,否则迁移并删除后返回 True
|
bool: 如果旧表不存在则返回 False,否则迁移并删除后返回 True
|
||||||
"""
|
"""
|
||||||
#检查旧表是否存在
|
# 检查旧表是否存在
|
||||||
cursor = await cls.m_pDB.execute(
|
cursor = await cls.m_pDB.execute(
|
||||||
"SELECT name FROM sqlite_master WHERE type='table' AND name='soil'"
|
"SELECT name FROM sqlite_master WHERE type='table' AND name='soil'"
|
||||||
)
|
)
|
||||||
@ -208,7 +205,7 @@ class CUserSoilDB(CSqlManager):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def getUserSoil(cls, uid: str, soilIndex: int) -> Optional[dict]:
|
async def getUserSoil(cls, uid: str, soilIndex: int) -> dict | None:
|
||||||
"""获取指定用户某块土地的详细信息
|
"""获取指定用户某块土地的详细信息
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -230,7 +227,7 @@ class CUserSoilDB(CSqlManager):
|
|||||||
return dict(zip(columns, row))
|
return dict(zip(columns, row))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def _getUserSoil(cls, uid: str, soilIndex: int) -> Optional[dict]:
|
async def _getUserSoil(cls, uid: str, soilIndex: int) -> dict | None:
|
||||||
"""获取指定用户某块土地的详细信息
|
"""获取指定用户某块土地的详细信息
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -288,7 +285,9 @@ class CUserSoilDB(CSqlManager):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def updateUserSoilFields(cls, uid: str, soilIndex: int, updates: dict) -> bool:
|
async def updateUserSoilFields(
|
||||||
|
cls, uid: str, soilIndex: int, updates: dict
|
||||||
|
) -> bool:
|
||||||
"""批量更新指定用户土地的多个字段
|
"""批量更新指定用户土地的多个字段
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -299,11 +298,18 @@ class CUserSoilDB(CSqlManager):
|
|||||||
Returns:
|
Returns:
|
||||||
bool: 如果无可更新字段则返回 False,否则更新成功返回 True
|
bool: 如果无可更新字段则返回 False,否则更新成功返回 True
|
||||||
"""
|
"""
|
||||||
#允许更新的列白名单
|
# 允许更新的列白名单
|
||||||
allowedFields = {
|
allowedFields = {
|
||||||
"plantName", "plantTime", "matureTime", "soilLevel",
|
"plantName",
|
||||||
"wiltStatus", "fertilizerStatus", "bugStatus",
|
"plantTime",
|
||||||
"weedStatus", "waterStatus", "harvestCount"
|
"matureTime",
|
||||||
|
"soilLevel",
|
||||||
|
"wiltStatus",
|
||||||
|
"fertilizerStatus",
|
||||||
|
"bugStatus",
|
||||||
|
"weedStatus",
|
||||||
|
"waterStatus",
|
||||||
|
"harvestCount",
|
||||||
}
|
}
|
||||||
setClauses = []
|
setClauses = []
|
||||||
values = []
|
values = []
|
||||||
@ -316,7 +322,7 @@ class CUserSoilDB(CSqlManager):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
values.extend([uid, soilIndex])
|
values.extend([uid, soilIndex])
|
||||||
sql = f'UPDATE userSoil SET {", ".join(setClauses)} WHERE uid = ? AND soilIndex = ?'
|
sql = f"UPDATE userSoil SET {', '.join(setClauses)} WHERE uid = ? AND soilIndex = ?"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
@ -386,12 +392,12 @@ class CUserSoilDB(CSqlManager):
|
|||||||
Returns:
|
Returns:
|
||||||
bool: 播种成功返回 True,否则返回 False
|
bool: 播种成功返回 True,否则返回 False
|
||||||
"""
|
"""
|
||||||
#校验土地区是否已种植
|
# 校验土地区是否已种植
|
||||||
soilRecord = await cls.getUserSoil(uid, soilIndex)
|
soilRecord = await cls.getUserSoil(uid, soilIndex)
|
||||||
if soilRecord and soilRecord.get("plantName"):
|
if soilRecord and soilRecord.get("plantName"):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
#获取植物配置
|
# 获取植物配置
|
||||||
plantCfg = await g_pDBService.plant.getPlantByName(plantName)
|
plantCfg = await g_pDBService.plant.getPlantByName(plantName)
|
||||||
if not plantCfg:
|
if not plantCfg:
|
||||||
logger.error(f"未知植物: {plantName}")
|
logger.error(f"未知植物: {plantName}")
|
||||||
@ -417,12 +423,12 @@ class CUserSoilDB(CSqlManager):
|
|||||||
"bugStatus": prev.get("bugStatus", 0),
|
"bugStatus": prev.get("bugStatus", 0),
|
||||||
"weedStatus": prev.get("weedStatus", 0),
|
"weedStatus": prev.get("weedStatus", 0),
|
||||||
"waterStatus": prev.get("waterStatus", 0),
|
"waterStatus": prev.get("waterStatus", 0),
|
||||||
"harvestCount": 0
|
"harvestCount": 0,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"播种失败!", e=e)
|
logger.error("播种失败!", e=e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@ -7,17 +7,19 @@ class CUserStealDB(CSqlManager):
|
|||||||
@classmethod
|
@classmethod
|
||||||
async def initDB(cls):
|
async def initDB(cls):
|
||||||
userSteal = {
|
userSteal = {
|
||||||
"uid": "TEXT NOT NULL", #被偷用户Uid
|
"uid": "TEXT NOT NULL", # 被偷用户Uid
|
||||||
"soilIndex": "INTEGER NOT NULL", #被偷的地块索引 从1开始
|
"soilIndex": "INTEGER NOT NULL", # 被偷的地块索引 从1开始
|
||||||
"stealerUid": "TEXT NOT NULL", #偷菜用户Uid
|
"stealerUid": "TEXT NOT NULL", # 偷菜用户Uid
|
||||||
"stealCount": "INTEGER NOT NULL", #被偷数量
|
"stealCount": "INTEGER NOT NULL", # 被偷数量
|
||||||
"stealTime": "INTEGER NOT NULL", #被偷时间
|
"stealTime": "INTEGER NOT NULL", # 被偷时间
|
||||||
"PRIMARY KEY": "(uid, soilIndex, stealerUid)"
|
"PRIMARY KEY": "(uid, soilIndex, stealerUid)",
|
||||||
}
|
}
|
||||||
await cls.ensureTableSchema("userSteal", userSteal)
|
await cls.ensureTableSchema("userSteal", userSteal)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def addStealRecord(cls, uid: str, soilIndex: int, stealerUid: str, stealCount: int, stealTime: int) -> bool:
|
async def addStealRecord(
|
||||||
|
cls, uid: str, soilIndex: int, stealerUid: str, stealCount: int, stealTime: int
|
||||||
|
) -> bool:
|
||||||
"""添加偷菜记录
|
"""添加偷菜记录
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -34,7 +36,7 @@ class CUserStealDB(CSqlManager):
|
|||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
'INSERT INTO "userSteal"(uid, soilIndex, stealerUid, stealCount, stealTime) VALUES(?, ?, ?, ?, ?);',
|
'INSERT INTO "userSteal"(uid, soilIndex, stealerUid, stealCount, stealTime) VALUES(?, ?, ?, ?, ?);',
|
||||||
(uid, soilIndex, stealerUid, stealCount, stealTime)
|
(uid, soilIndex, stealerUid, stealCount, stealTime),
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -55,7 +57,7 @@ class CUserStealDB(CSqlManager):
|
|||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
cursor = await cls.m_pDB.execute(
|
cursor = await cls.m_pDB.execute(
|
||||||
'SELECT soilIndex, stealerUid, stealCount, stealTime FROM "userSteal" WHERE uid=?;',
|
'SELECT soilIndex, stealerUid, stealCount, stealTime FROM "userSteal" WHERE uid=?;',
|
||||||
(uid,)
|
(uid,),
|
||||||
)
|
)
|
||||||
rows = await cursor.fetchall()
|
rows = await cursor.fetchall()
|
||||||
return [
|
return [
|
||||||
@ -64,7 +66,7 @@ class CUserStealDB(CSqlManager):
|
|||||||
"soilIndex": row[0],
|
"soilIndex": row[0],
|
||||||
"stealerUid": row[1],
|
"stealerUid": row[1],
|
||||||
"stealCount": row[2],
|
"stealCount": row[2],
|
||||||
"stealTime": row[3]
|
"stealTime": row[3],
|
||||||
}
|
}
|
||||||
for row in rows
|
for row in rows
|
||||||
]
|
]
|
||||||
@ -87,7 +89,7 @@ class CUserStealDB(CSqlManager):
|
|||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
cursor = await cls.m_pDB.execute(
|
cursor = await cls.m_pDB.execute(
|
||||||
'SELECT stealerUid, stealCount, stealTime FROM "userSteal" WHERE uid=? AND soilIndex=?;',
|
'SELECT stealerUid, stealCount, stealTime FROM "userSteal" WHERE uid=? AND soilIndex=?;',
|
||||||
(uid, soilIndex)
|
(uid, soilIndex),
|
||||||
)
|
)
|
||||||
rows = await cursor.fetchall()
|
rows = await cursor.fetchall()
|
||||||
return [
|
return [
|
||||||
@ -96,7 +98,7 @@ class CUserStealDB(CSqlManager):
|
|||||||
"soilIndex": soilIndex,
|
"soilIndex": soilIndex,
|
||||||
"stealerUid": row[0],
|
"stealerUid": row[0],
|
||||||
"stealCount": row[1],
|
"stealCount": row[1],
|
||||||
"stealTime": row[2]
|
"stealTime": row[2],
|
||||||
}
|
}
|
||||||
for row in rows
|
for row in rows
|
||||||
]
|
]
|
||||||
@ -119,7 +121,7 @@ class CUserStealDB(CSqlManager):
|
|||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
cursor = await cls.m_pDB.execute(
|
cursor = await cls.m_pDB.execute(
|
||||||
'SELECT SUM(stealCount) FROM "userSteal" WHERE uid=? AND soilIndex=?;',
|
'SELECT SUM(stealCount) FROM "userSteal" WHERE uid=? AND soilIndex=?;',
|
||||||
(uid, soilIndex)
|
(uid, soilIndex),
|
||||||
)
|
)
|
||||||
row = await cursor.fetchone()
|
row = await cursor.fetchone()
|
||||||
return row[0] or 0 # type: ignore
|
return row[0] or 0 # type: ignore
|
||||||
@ -142,7 +144,7 @@ class CUserStealDB(CSqlManager):
|
|||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
cursor = await cls.m_pDB.execute(
|
cursor = await cls.m_pDB.execute(
|
||||||
'SELECT COUNT(DISTINCT stealerUid) FROM "userSteal" WHERE uid=? AND soilIndex=?;',
|
'SELECT COUNT(DISTINCT stealerUid) FROM "userSteal" WHERE uid=? AND soilIndex=?;',
|
||||||
(uid, soilIndex)
|
(uid, soilIndex),
|
||||||
)
|
)
|
||||||
row = await cursor.fetchone()
|
row = await cursor.fetchone()
|
||||||
return row[0] or 0 # type: ignore
|
return row[0] or 0 # type: ignore
|
||||||
@ -166,7 +168,7 @@ class CUserStealDB(CSqlManager):
|
|||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
cursor = await cls.m_pDB.execute(
|
cursor = await cls.m_pDB.execute(
|
||||||
'SELECT 1 FROM "userSteal" WHERE uid=? AND soilIndex=? AND stealerUid=? LIMIT 1;',
|
'SELECT 1 FROM "userSteal" WHERE uid=? AND soilIndex=? AND stealerUid=? LIMIT 1;',
|
||||||
(uid, soilIndex, stealerUid)
|
(uid, soilIndex, stealerUid),
|
||||||
)
|
)
|
||||||
row = await cursor.fetchone()
|
row = await cursor.fetchone()
|
||||||
return bool(row)
|
return bool(row)
|
||||||
@ -175,7 +177,9 @@ class CUserStealDB(CSqlManager):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def updateStealRecord(cls, uid: str, soilIndex: int, stealerUid: str, stealCount: int, stealTime: int) -> bool:
|
async def updateStealRecord(
|
||||||
|
cls, uid: str, soilIndex: int, stealerUid: str, stealCount: int, stealTime: int
|
||||||
|
) -> bool:
|
||||||
"""更新偷菜记录的数量和时间
|
"""更新偷菜记录的数量和时间
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -192,7 +196,7 @@ class CUserStealDB(CSqlManager):
|
|||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
'UPDATE "userSteal" SET stealCount=?, stealTime=? WHERE uid=? AND soilIndex=? AND stealerUid=?;',
|
'UPDATE "userSteal" SET stealCount=?, stealTime=? WHERE uid=? AND soilIndex=? AND stealerUid=?;',
|
||||||
(stealCount, stealTime, uid, soilIndex, stealerUid)
|
(stealCount, stealTime, uid, soilIndex, stealerUid),
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -214,7 +218,7 @@ class CUserStealDB(CSqlManager):
|
|||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
'DELETE FROM "userSteal" WHERE uid=? AND soilIndex=?;',
|
'DELETE FROM "userSteal" WHERE uid=? AND soilIndex=?;',
|
||||||
(uid, soilIndex)
|
(uid, soilIndex),
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@ -1,6 +1,3 @@
|
|||||||
from typing import Optional
|
|
||||||
|
|
||||||
|
|
||||||
class CDBService:
|
class CDBService:
|
||||||
@classmethod
|
@classmethod
|
||||||
async def init(cls):
|
async def init(cls):
|
||||||
@ -37,11 +34,12 @@ class CDBService:
|
|||||||
cls.userSign = CUserSignDB()
|
cls.userSign = CUserSignDB()
|
||||||
await cls.userSign.initDB()
|
await cls.userSign.initDB()
|
||||||
|
|
||||||
#迁移旧数据库
|
# 迁移旧数据库
|
||||||
await cls.userSoil.migrateOldFarmData()
|
await cls.userSoil.migrateOldFarmData()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def cleanup(cls):
|
async def cleanup(cls):
|
||||||
await cls.plant.cleanup()
|
await cls.plant.cleanup()
|
||||||
|
|
||||||
|
|
||||||
g_pDBService = CDBService()
|
g_pDBService = CDBService()
|
||||||
|
|||||||
@ -6,8 +6,8 @@ from zhenxun.services.log import logger
|
|||||||
|
|
||||||
class Signal:
|
class Signal:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._slots = [] #绑定的槽函数列表
|
self._slots = [] # 绑定的槽函数列表
|
||||||
self._onceSlots = [] #只触发一次的槽函数列表
|
self._onceSlots = [] # 只触发一次的槽函数列表
|
||||||
|
|
||||||
def connect(self, slot, priority=0):
|
def connect(self, slot, priority=0):
|
||||||
if callable(slot) and not any(s[0] == slot for s in self._slots):
|
if callable(slot) and not any(s[0] == slot for s in self._slots):
|
||||||
@ -41,10 +41,8 @@ class Signal:
|
|||||||
logger.warning(f"事件槽 {slot.__name__} 触发异常: {e}")
|
logger.warning(f"事件槽 {slot.__name__} 触发异常: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class FarmEventManager:
|
class FarmEventManager:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.m_beforePlant = Signal()
|
self.m_beforePlant = Signal()
|
||||||
"""播种前信号
|
"""播种前信号
|
||||||
|
|
||||||
@ -100,4 +98,5 @@ class FarmEventManager:
|
|||||||
self.m_beforeSteal = Signal()
|
self.m_beforeSteal = Signal()
|
||||||
self.m_afterSteal = Signal()
|
self.m_afterSteal = Signal()
|
||||||
|
|
||||||
|
|
||||||
g_pEventManager = FarmEventManager()
|
g_pEventManager = FarmEventManager()
|
||||||
|
|||||||
537
farm/farm.py
537
farm/farm.py
@ -1,7 +1,5 @@
|
|||||||
import asyncio
|
|
||||||
import math
|
import math
|
||||||
import random
|
import random
|
||||||
from typing import Dict, List, Tuple
|
|
||||||
|
|
||||||
from zhenxun.configs.config import Config
|
from zhenxun.configs.config import Config
|
||||||
from zhenxun.models.user_console import UserConsole
|
from zhenxun.models.user_console import UserConsole
|
||||||
@ -11,7 +9,7 @@ from zhenxun.utils.enum import GoldHandle
|
|||||||
from zhenxun.utils.image_utils import ImageTemplate
|
from zhenxun.utils.image_utils import ImageTemplate
|
||||||
from zhenxun.utils.platform import PlatformUtils
|
from zhenxun.utils.platform import PlatformUtils
|
||||||
|
|
||||||
from ..config import g_bIsDebug, g_sResourcePath
|
from ..config import g_bIsDebug, g_sResourcePath, g_sTranslation
|
||||||
from ..dbService import g_pDBService
|
from ..dbService import g_pDBService
|
||||||
from ..event.event import g_pEventManager
|
from ..event.event import g_pEventManager
|
||||||
from ..json import g_pJsonManager
|
from ..json import g_pJsonManager
|
||||||
@ -29,16 +27,20 @@ class CFarmManager:
|
|||||||
pro = float(Config.get_config("zhenxun_plugin_farm", "兑换倍数"))
|
pro = float(Config.get_config("zhenxun_plugin_farm", "兑换倍数"))
|
||||||
tax = float(Config.get_config("zhenxun_plugin_farm", "手续费"))
|
tax = float(Config.get_config("zhenxun_plugin_farm", "手续费"))
|
||||||
|
|
||||||
#计算手续费
|
# 计算手续费
|
||||||
fee = math.floor(num * tax)
|
fee = math.floor(num * tax)
|
||||||
#实际扣费金额
|
# 实际扣费金额
|
||||||
deduction = num + fee
|
deduction = num + fee
|
||||||
|
|
||||||
if user.gold < deduction:
|
if user.gold < deduction:
|
||||||
return f"你的金币不足或不足承担手续费。当前手续费为{fee}"
|
return f"你的金币不足或不足承担手续费。当前手续费为{fee}"
|
||||||
|
|
||||||
await UserConsole.reduce_gold(uid, num, GoldHandle.PLUGIN , 'zhenxun_plugin_farm') # type: ignore
|
await UserConsole.reduce_gold(
|
||||||
await UserConsole.reduce_gold(uid, fee, GoldHandle.PLUGIN , 'zhenxun_plugin_farm') # type: ignore
|
uid, num, GoldHandle.PLUGIN, "zhenxun_plugin_farm"
|
||||||
|
) # type: ignore
|
||||||
|
await UserConsole.reduce_gold(
|
||||||
|
uid, fee, GoldHandle.PLUGIN, "zhenxun_plugin_farm"
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
point = num * pro
|
point = num * pro
|
||||||
|
|
||||||
@ -59,48 +61,59 @@ class CFarmManager:
|
|||||||
Returns:
|
Returns:
|
||||||
bytes: 返回绘制结果
|
bytes: 返回绘制结果
|
||||||
"""
|
"""
|
||||||
img = BuildImage(background = g_sResourcePath / "background/background.jpg")
|
img = BuildImage(background=g_sResourcePath / "background/background.jpg")
|
||||||
|
|
||||||
soilSize = g_pJsonManager.m_pSoil['size']
|
soilSize = g_pJsonManager.m_pSoil["size"]
|
||||||
|
|
||||||
#TODO 缺少判断用户土地资源状况
|
# TODO 缺少判断用户土地资源状况
|
||||||
soil = BuildImage(background = g_sResourcePath / "soil/普通土地.png")
|
soil = BuildImage(background=g_sResourcePath / "soil/普通土地.png")
|
||||||
await soil.resize(0, soilSize[0], soilSize[1])
|
await soil.resize(0, soilSize[0], soilSize[1])
|
||||||
|
|
||||||
grass = BuildImage(background = g_sResourcePath / "soil/草土地.png")
|
grass = BuildImage(background=g_sResourcePath / "soil/草土地.png")
|
||||||
await grass.resize(0, soilSize[0], soilSize[1])
|
await grass.resize(0, soilSize[0], soilSize[1])
|
||||||
|
|
||||||
soilPos = g_pJsonManager.m_pSoil['soil']
|
soilPos = g_pJsonManager.m_pSoil["soil"]
|
||||||
|
|
||||||
userInfo = await g_pDBService.user.getUserInfoByUid(uid)
|
userInfo = await g_pDBService.user.getUserInfoByUid(uid)
|
||||||
soilUnlock = int(userInfo['soil'])
|
soilUnlock = int(userInfo["soil"])
|
||||||
|
|
||||||
x = 0
|
x = 0
|
||||||
y = 0
|
y = 0
|
||||||
isFirstExpansion = True #首次添加扩建图片
|
isFirstExpansion = True # 首次添加扩建图片
|
||||||
isFirstRipe = True
|
isFirstRipe = True
|
||||||
plant = None
|
plant = None
|
||||||
for index in range(0, 30):
|
for index in range(0, 30):
|
||||||
x = soilPos[str(index + 1)]['x']
|
x = soilPos[str(index + 1)]["x"]
|
||||||
y = soilPos[str(index + 1)]['y']
|
y = soilPos[str(index + 1)]["y"]
|
||||||
|
|
||||||
#如果土地已经到达对应等级
|
# 如果土地已经到达对应等级
|
||||||
if index < soilUnlock:
|
if index < soilUnlock:
|
||||||
await img.paste(soil, (x, y))
|
await img.paste(soil, (x, y))
|
||||||
|
|
||||||
isPlant, plant, isRipe, offsetX, offsetY = await cls.drawSoilPlant(uid, index + 1)
|
isPlant, plant, isRipe, offsetX, offsetY = await cls.drawSoilPlant(
|
||||||
|
uid, index + 1
|
||||||
|
)
|
||||||
|
|
||||||
if isPlant:
|
if isPlant:
|
||||||
await img.paste(plant, (x + soilSize[0] // 2 - plant.width // 2 + offsetX,
|
await img.paste(
|
||||||
y + soilSize[1] // 2 - plant.height // 2 + offsetY))
|
plant,
|
||||||
|
(
|
||||||
|
x + soilSize[0] // 2 - plant.width // 2 + offsetX,
|
||||||
|
y + soilSize[1] // 2 - plant.height // 2 + offsetY,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
#1700 275
|
# 1700 275
|
||||||
#首次添加可收获图片
|
# 首次添加可收获图片
|
||||||
if isRipe and isFirstRipe:
|
if isRipe and isFirstRipe:
|
||||||
ripe = BuildImage(background = g_sResourcePath / "background/ripe.png")
|
ripe = BuildImage(
|
||||||
|
background=g_sResourcePath / "background/ripe.png"
|
||||||
|
)
|
||||||
|
|
||||||
await img.paste(ripe, (x + soilSize[0] // 2 - ripe.width // 2,
|
await img.paste(
|
||||||
y - ripe.height // 2))
|
ripe,
|
||||||
|
(x + soilSize[0] // 2 - ripe.width // 2, y - ripe.height // 2),
|
||||||
|
)
|
||||||
|
|
||||||
isFirstRipe = False
|
isFirstRipe = False
|
||||||
else:
|
else:
|
||||||
@ -109,54 +122,71 @@ class CFarmManager:
|
|||||||
if isFirstExpansion:
|
if isFirstExpansion:
|
||||||
isFirstExpansion = False
|
isFirstExpansion = False
|
||||||
|
|
||||||
#首次添加扩建图片
|
# 首次添加扩建图片
|
||||||
expansion = BuildImage(background = g_sResourcePath / "background/expansion.png")
|
expansion = BuildImage(
|
||||||
|
background=g_sResourcePath / "background/expansion.png"
|
||||||
|
)
|
||||||
await expansion.resize(0, 69, 69)
|
await expansion.resize(0, 69, 69)
|
||||||
await img.paste(expansion, (x + soilSize[0] // 2 - expansion.width // 2,
|
await img.paste(
|
||||||
y + soilSize[1] // 2 - expansion.height))
|
expansion,
|
||||||
|
(
|
||||||
|
x + soilSize[0] // 2 - expansion.width // 2,
|
||||||
|
y + soilSize[1] // 2 - expansion.height,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
#左上角绘制用户信息
|
# 左上角绘制用户信息
|
||||||
#头像
|
# 头像
|
||||||
image = await PlatformUtils.get_user_avatar(uid, "qq")
|
image = await PlatformUtils.get_user_avatar(uid, "qq")
|
||||||
|
|
||||||
if image:
|
if image:
|
||||||
avatar = BuildImage(background = image)
|
avatar = BuildImage(background=image)
|
||||||
|
|
||||||
await img.paste(avatar, (125, 85))
|
await img.paste(avatar, (125, 85))
|
||||||
|
|
||||||
#头像框
|
# 头像框
|
||||||
frame = BuildImage(background = g_sResourcePath / "background/frame.png")
|
frame = BuildImage(background=g_sResourcePath / "background/frame.png")
|
||||||
await img.paste(frame, (75, 44))
|
await img.paste(frame, (75, 44))
|
||||||
|
|
||||||
#用户名
|
# 用户名
|
||||||
nameImg = await BuildImage.build_text_image(userInfo['name'], size = 24, font_color = (77, 35, 4))
|
nameImg = await BuildImage.build_text_image(
|
||||||
|
userInfo["name"], size=24, font_color=(77, 35, 4)
|
||||||
|
)
|
||||||
await img.paste(nameImg, (300, 92))
|
await img.paste(nameImg, (300, 92))
|
||||||
|
|
||||||
#经验值
|
# 经验值
|
||||||
level = await g_pDBService.user.getUserLevelByUid(uid)
|
level = await g_pDBService.user.getUserLevelByUid(uid)
|
||||||
|
|
||||||
beginX = 309
|
beginX = 309
|
||||||
endX = 627
|
endX = 627
|
||||||
#绘制宽度计算公式为 (当前经验值 / 经验值上限) * 宽度
|
# 绘制宽度计算公式为 (当前经验值 / 经验值上限) * 宽度
|
||||||
width = int((level[2] / level[1]) * (endX - beginX))
|
width = int((level[2] / level[1]) * (endX - beginX))
|
||||||
await img.rectangle((beginX, 188, beginX + width, 222), (171, 194, 41))
|
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))
|
expImg = await BuildImage.build_text_image(
|
||||||
|
f"{level[2]} / {level[1]}", size=24, font_color=(102, 120, 19)
|
||||||
|
)
|
||||||
await img.paste(expImg, (390, 193))
|
await img.paste(expImg, (390, 193))
|
||||||
|
|
||||||
#等级
|
# 等级
|
||||||
levelImg = await BuildImage.build_text_image(str(level[0]), size = 32, font_color = (214, 111, 1))
|
levelImg = await BuildImage.build_text_image(
|
||||||
|
str(level[0]), size=32, font_color=(214, 111, 1)
|
||||||
|
)
|
||||||
await img.paste(levelImg, (660, 187))
|
await img.paste(levelImg, (660, 187))
|
||||||
|
|
||||||
#金币
|
# 金币
|
||||||
pointImg = await BuildImage.build_text_image(str(userInfo['point']), size = 24, font_color = (253, 253, 253))
|
pointImg = await BuildImage.build_text_image(
|
||||||
|
str(userInfo["point"]), size=24, font_color=(253, 253, 253)
|
||||||
|
)
|
||||||
await img.paste(pointImg, (330, 255))
|
await img.paste(pointImg, (330, 255))
|
||||||
|
|
||||||
#点券 TODO
|
# 点券 TODO
|
||||||
bondsImg = await BuildImage.build_text_image("0", size = 24, font_color = (253, 253, 253))
|
bondsImg = await BuildImage.build_text_image(
|
||||||
|
"0", size=24, font_color=(253, 253, 253)
|
||||||
|
)
|
||||||
await img.paste(bondsImg, (570, 255))
|
await img.paste(bondsImg, (570, 255))
|
||||||
|
|
||||||
#清晰度
|
# 清晰度
|
||||||
definition = Config.get_config("zhenxun_plugin_farm", "绘制农场清晰度")
|
definition = Config.get_config("zhenxun_plugin_farm", "绘制农场清晰度")
|
||||||
if definition == "medium":
|
if definition == "medium":
|
||||||
await img.resize(0.6)
|
await img.resize(0.6)
|
||||||
@ -196,9 +226,9 @@ class CFarmManager:
|
|||||||
|
|
||||||
if soilInfo:
|
if soilInfo:
|
||||||
if soilInfo["soilLevel"] == 1:
|
if soilInfo["soilLevel"] == 1:
|
||||||
iconPath = g_sResourcePath / f"soil/TODO.png"
|
iconPath = g_sResourcePath / "soil/TODO.png"
|
||||||
else:
|
else:
|
||||||
iconPath = g_sResourcePath / f"soil/普通土地.png"
|
iconPath = g_sResourcePath / "soil/普通土地.png"
|
||||||
|
|
||||||
if iconPath.exists():
|
if iconPath.exists():
|
||||||
icon = (iconPath, 33, 33)
|
icon = (iconPath, 33, 33)
|
||||||
@ -211,14 +241,20 @@ class CFarmManager:
|
|||||||
totalNumber = "-"
|
totalNumber = "-"
|
||||||
plantNumber = "-"
|
plantNumber = "-"
|
||||||
else:
|
else:
|
||||||
matureTime = g_pToolManager.dateTime().fromtimestamp(int(soilInfo.get("matureTime", 0))).strftime("%Y-%m-%d %H:%M:%S")
|
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)
|
soilStatus = await g_pDBService.userSoil.getUserSoilStatus(uid, i)
|
||||||
|
|
||||||
totalNumber = await g_pDBService.userSteal.getTotalStolenCount(uid, i)
|
totalNumber = await g_pDBService.userSteal.getTotalStolenCount(
|
||||||
|
uid, i
|
||||||
|
)
|
||||||
planInfo = await g_pDBService.plant.getPlantByName(plantName)
|
planInfo = await g_pDBService.plant.getPlantByName(plantName)
|
||||||
|
|
||||||
if not planInfo:
|
if not planInfo:
|
||||||
plantNumber = f"None"
|
plantNumber = "None"
|
||||||
else:
|
else:
|
||||||
plantNumber = f"{planInfo['harvest'] - totalNumber}"
|
plantNumber = f"{planInfo['harvest'] - totalNumber}"
|
||||||
|
|
||||||
@ -231,7 +267,8 @@ class CFarmManager:
|
|||||||
soilStatus,
|
soilStatus,
|
||||||
totalNumber,
|
totalNumber,
|
||||||
plantNumber,
|
plantNumber,
|
||||||
])
|
]
|
||||||
|
)
|
||||||
|
|
||||||
if len(dataList) >= 15:
|
if len(dataList) >= 15:
|
||||||
result = await ImageTemplate.table_page(
|
result = await ImageTemplate.table_page(
|
||||||
@ -258,7 +295,9 @@ class CFarmManager:
|
|||||||
return info
|
return info
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def drawSoilPlant(cls, uid: str, soilIndex: int) -> tuple[bool, BuildImage, bool, int, int]:
|
async def drawSoilPlant(
|
||||||
|
cls, uid: str, soilIndex: int
|
||||||
|
) -> tuple[bool, BuildImage, bool, int, int]:
|
||||||
"""绘制植物资源
|
"""绘制植物资源
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -273,54 +312,64 @@ class CFarmManager:
|
|||||||
soilInfo = await g_pDBService.userSoil.getUserSoil(uid, soilIndex)
|
soilInfo = await g_pDBService.userSoil.getUserSoil(uid, soilIndex)
|
||||||
|
|
||||||
if not soilInfo:
|
if not soilInfo:
|
||||||
return False, None, False, 0, 0 #type: ignore
|
return False, None, False, 0, 0 # type: ignore
|
||||||
|
|
||||||
#是否枯萎
|
# 是否枯萎
|
||||||
if int(soilInfo.get("wiltStatus", 0)) == 1:
|
if int(soilInfo.get("wiltStatus", 0)) == 1:
|
||||||
plant = BuildImage(background = g_sResourcePath / f"plant/basic/9.png")
|
plant = BuildImage(background=g_sResourcePath / "plant/basic/9.png")
|
||||||
await plant.resize(0, 150, 212)
|
await plant.resize(0, 150, 212)
|
||||||
return True, plant, False, 0, 0
|
return True, plant, False, 0, 0
|
||||||
|
|
||||||
#获取作物详细信息
|
# 获取作物详细信息
|
||||||
plantInfo = await g_pDBService.plant.getPlantByName(soilInfo['plantName'])
|
plantInfo = await g_pDBService.plant.getPlantByName(soilInfo["plantName"])
|
||||||
if not plantInfo:
|
if not plantInfo:
|
||||||
logger.error(f"绘制植物资源失败: {soilInfo['plantName']}")
|
logger.error(f"绘制植物资源失败: {soilInfo['plantName']}")
|
||||||
return False, None, False, 0, 0 #type: ignore
|
return False, None, False, 0, 0 # type: ignore
|
||||||
|
|
||||||
offsetX = plantInfo.get('officX', 0)
|
offsetX = plantInfo.get("officX", 0)
|
||||||
offsetY = plantInfo.get('officY', 0)
|
offsetY = plantInfo.get("officY", 0)
|
||||||
offsetW = plantInfo.get('officW', 0)
|
offsetW = plantInfo.get("officW", 0)
|
||||||
offsetH = plantInfo.get('officH', 0)
|
offsetH = plantInfo.get("officH", 0)
|
||||||
|
|
||||||
currentTime = g_pToolManager.dateTime().now().timestamp()
|
currentTime = g_pToolManager.dateTime().now().timestamp()
|
||||||
phaseList = await g_pDBService.plant.getPlantPhaseByName(soilInfo['plantName'])
|
phaseList = await g_pDBService.plant.getPlantPhaseByName(soilInfo["plantName"])
|
||||||
|
|
||||||
#如果当前时间大于成熟时间 说明作物成熟
|
# 如果当前时间大于成熟时间 说明作物成熟
|
||||||
if currentTime >= soilInfo['matureTime']:
|
if currentTime >= soilInfo["matureTime"]:
|
||||||
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{len(phaseList)}.png")
|
plant = BuildImage(
|
||||||
|
background=g_sResourcePath
|
||||||
|
/ f"plant/{soilInfo['plantName']}/{len(phaseList)}.png"
|
||||||
|
)
|
||||||
|
|
||||||
return True, plant, True, offsetX, offsetY
|
return True, plant, True, offsetX, offsetY
|
||||||
else:
|
else:
|
||||||
#如果是多阶段作物 且没有成熟 #早期思路 多阶段作物 直接是倒数第二阶段图片
|
# 如果是多阶段作物 且没有成熟 #早期思路 多阶段作物 直接是倒数第二阶段图片
|
||||||
# if soilInfo['harvestCount'] >= 1:
|
# if soilInfo['harvestCount'] >= 1:
|
||||||
# plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{plantInfo['phase'] - 1s}.png")
|
# plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{plantInfo['phase'] - 1s}.png")
|
||||||
|
|
||||||
# return True, plant, False, offsetX, offsetY
|
# return True, plant, False, offsetX, offsetY
|
||||||
|
|
||||||
#如果没有成熟 则根据当前阶段进行绘制
|
# 如果没有成熟 则根据当前阶段进行绘制
|
||||||
|
elapsedTime = currentTime - soilInfo["plantTime"]
|
||||||
elapsedTime = currentTime - soilInfo['plantTime']
|
currentStage = currentStage = sum(
|
||||||
currentStage = sum(1 for thr in phaseList if elapsedTime >= thr)
|
1 for thr in phaseList if elapsedTime >= thr
|
||||||
|
)
|
||||||
|
|
||||||
if currentStage <= 0:
|
if currentStage <= 0:
|
||||||
if plantInfo['general'] == False:
|
if not plantInfo["general"]:
|
||||||
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/0.png")
|
plant = BuildImage(
|
||||||
|
background=g_sResourcePath
|
||||||
|
/ f"plant/{soilInfo['plantName']}/0.png"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
plant = BuildImage(background = g_sResourcePath / f"plant/basic/0.png")
|
plant = BuildImage(background=g_sResourcePath / "plant/basic/0.png")
|
||||||
|
|
||||||
await plant.resize(0, 35 + offsetW, 58 + offsetH)
|
await plant.resize(0, 35 + offsetW, 58 + offsetH)
|
||||||
else:
|
else:
|
||||||
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo['plantName']}/{currentStage}.png")
|
plant = BuildImage(
|
||||||
|
background=g_sResourcePath
|
||||||
|
/ f"plant/{soilInfo['plantName']}/{currentStage}.png"
|
||||||
|
)
|
||||||
|
|
||||||
return True, plant, False, offsetX, offsetY
|
return True, plant, False, offsetX, offsetY
|
||||||
|
|
||||||
@ -336,10 +385,10 @@ class CFarmManager:
|
|||||||
"收获数量",
|
"收获数量",
|
||||||
"成熟时间(小时)",
|
"成熟时间(小时)",
|
||||||
"收获次数",
|
"收获次数",
|
||||||
"是否可以上架交易行"
|
"是否可以上架交易行",
|
||||||
]
|
]
|
||||||
|
|
||||||
#从数据库获取结构化数据
|
# 从数据库获取结构化数据
|
||||||
seedRecords = await g_pDBService.userSeed.getUserSeedByUid(uid) or {}
|
seedRecords = await g_pDBService.userSeed.getUserSeedByUid(uid) or {}
|
||||||
|
|
||||||
if not seedRecords:
|
if not seedRecords:
|
||||||
@ -359,18 +408,20 @@ class CFarmManager:
|
|||||||
|
|
||||||
iconPath = g_sResourcePath / f"plant/{seedName}/icon.png"
|
iconPath = g_sResourcePath / f"plant/{seedName}/icon.png"
|
||||||
icon = (iconPath, 33, 33) if iconPath.exists() else ""
|
icon = (iconPath, 33, 33) if iconPath.exists() else ""
|
||||||
sellable = "可以" if plantInfo['sell'] else "不可以"
|
sellable = "可以" if plantInfo["sell"] else "不可以"
|
||||||
|
|
||||||
dataList.append([
|
dataList.append(
|
||||||
|
[
|
||||||
icon,
|
icon,
|
||||||
seedName,
|
seedName,
|
||||||
count,
|
count,
|
||||||
plantInfo['experience'],
|
plantInfo["experience"],
|
||||||
plantInfo['harvest'],
|
plantInfo["harvest"],
|
||||||
plantInfo['time'],
|
plantInfo["time"],
|
||||||
plantInfo['crop'],
|
plantInfo["crop"],
|
||||||
sellable
|
sellable,
|
||||||
])
|
]
|
||||||
|
)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -395,58 +446,61 @@ class CFarmManager:
|
|||||||
str: 返回结果
|
str: 返回结果
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
#获取用户的种子数量
|
# 获取用户的种子数量
|
||||||
count = await g_pDBService.userSeed.getUserSeedByName(uid, name)
|
count = await g_pDBService.userSeed.getUserSeedByName(uid, name)
|
||||||
if count is None:
|
if count is None:
|
||||||
count = 0 #如果返回 None,则视为没有种子
|
count = 0 # 如果返回 None,则视为没有种子
|
||||||
|
|
||||||
if count <= 0:
|
if count <= 0:
|
||||||
return f"没有在你的仓库发现{name}种子,快去买点吧!"
|
return g_sTranslation["sowing"]["noSeed"].format(name=name)
|
||||||
|
|
||||||
#如果播种数量超过仓库种子数量
|
# 如果播种数量超过仓库种子数量
|
||||||
if count < num and num != -1:
|
if count < num and num != -1:
|
||||||
return f"仓库中的{name}种子数量不足,当前剩余{count}个种子"
|
return g_sTranslation["sowing"]["noNum"].format(name=name, num=count)
|
||||||
|
|
||||||
#获取用户土地数量
|
# 获取用户土地数量
|
||||||
soilNumber = await g_pDBService.user.getUserSoilByUid(uid)
|
soilNumber = await g_pDBService.user.getUserSoilByUid(uid)
|
||||||
|
|
||||||
#如果播种数量为 -1,表示播种所有可播种的土地
|
# 如果播种数量为 -1,表示播种所有可播种的土地
|
||||||
if num == -1:
|
if num == -1:
|
||||||
num = count
|
num = count
|
||||||
|
|
||||||
#发送播种前信号
|
# 发送播种前信号
|
||||||
await g_pEventManager.m_beforePlant.emit(uid=uid, name=name, num=num)
|
await g_pEventManager.m_beforePlant.emit(uid=uid, name=name, num=num)
|
||||||
|
|
||||||
#记录是否成功播种
|
# 记录是否成功播种
|
||||||
successCount = 0
|
successCount = 0
|
||||||
for i in range(1, soilNumber + 1):
|
for i in range(1, soilNumber + 1):
|
||||||
if count > 0 and num > 0:
|
if count > 0 and num > 0:
|
||||||
success = await g_pDBService.userSoil.sowingByPlantName(uid, i, name)
|
success = await g_pDBService.userSoil.sowingByPlantName(
|
||||||
|
uid, i, name
|
||||||
|
)
|
||||||
if success:
|
if success:
|
||||||
#更新种子数量
|
# 更新种子数量
|
||||||
num -= 1
|
num -= 1
|
||||||
count -= 1
|
count -= 1
|
||||||
|
|
||||||
#记录种子消耗数量
|
# 记录种子消耗数量
|
||||||
successCount += 1
|
successCount += 1
|
||||||
|
|
||||||
#发送播种后信号
|
# 发送播种后信号
|
||||||
await g_pEventManager.m_afterPlant.emit(uid=uid, name=name, soilIndex=i)
|
await g_pEventManager.m_afterPlant.emit(
|
||||||
|
uid=uid, name=name, soilIndex=i
|
||||||
|
)
|
||||||
|
|
||||||
|
# 确保用户仓库数量更新
|
||||||
#确保用户仓库数量更新
|
|
||||||
if successCount > 0:
|
if successCount > 0:
|
||||||
await g_pDBService.userSeed.updateUserSeedByName(uid, name, count)
|
await g_pDBService.userSeed.updateUserSeedByName(uid, name, count)
|
||||||
|
|
||||||
#根据播种结果给出反馈
|
# 根据播种结果给出反馈
|
||||||
if num == 0:
|
if num == 0:
|
||||||
return f"播种{name}成功!仓库剩余{count}个种子"
|
return g_sTranslation["sowing"]["success"].format(name=name, num=count)
|
||||||
else:
|
else:
|
||||||
return f"播种数量超出开垦土地数量,已将可播种土地成功播种{name}!仓库剩余{count}个种子"
|
return g_sTranslation["sowing"]["success2"].format(name=name, num=count)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"播种操作失败!", e=e)
|
logger.warning("播种操作失败!", e=e)
|
||||||
return "播种失败,请稍后重试!"
|
return g_sTranslation["sowing"]["error"]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def harvest(cls, uid: str) -> str:
|
async def harvest(cls, uid: str) -> str:
|
||||||
@ -463,12 +517,12 @@ class CFarmManager:
|
|||||||
|
|
||||||
soilNumber = await g_pDBService.user.getUserSoilByUid(uid)
|
soilNumber = await g_pDBService.user.getUserSoilByUid(uid)
|
||||||
|
|
||||||
harvestRecords = [] #收获日志记录
|
harvestRecords = [] # 收获日志记录
|
||||||
experience = 0 #总经验值
|
experience = 0 # 总经验值
|
||||||
harvestCount = 0 #成功收获数量
|
harvestCount = 0 # 成功收获数量
|
||||||
|
|
||||||
for i in range(1, soilNumber + 1):
|
for i in range(1, soilNumber + 1):
|
||||||
#如果没有种植
|
# 如果没有种植
|
||||||
if not await g_pDBService.userSoil.isSoilPlanted(uid, i):
|
if not await g_pDBService.userSoil.isSoilPlanted(uid, i):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -476,21 +530,25 @@ class CFarmManager:
|
|||||||
if not soilInfo:
|
if not soilInfo:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
#如果是枯萎状态
|
# 如果是枯萎状态
|
||||||
if soilInfo.get("wiltStatus", 1) == 1:
|
if soilInfo.get("wiltStatus", 1) == 1:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
plantInfo = await g_pDBService.plant.getPlantByName(soilInfo['plantName'])
|
plantInfo = await g_pDBService.plant.getPlantByName(
|
||||||
|
soilInfo["plantName"]
|
||||||
|
)
|
||||||
if not plantInfo:
|
if not plantInfo:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
currentTime = g_pToolManager.dateTime().now()
|
currentTime = g_pToolManager.dateTime().now()
|
||||||
matureTime = g_pToolManager.dateTime().fromtimestamp(int(soilInfo['matureTime']))
|
matureTime = g_pToolManager.dateTime().fromtimestamp(
|
||||||
|
int(soilInfo["matureTime"])
|
||||||
|
)
|
||||||
|
|
||||||
if currentTime >= matureTime:
|
if currentTime >= matureTime:
|
||||||
number = plantInfo['harvest']
|
number = plantInfo["harvest"]
|
||||||
|
|
||||||
#处理偷菜扣除数量
|
# 处理偷菜扣除数量
|
||||||
stealNum = await g_pDBService.userSteal.getTotalStolenCount(uid, i)
|
stealNum = await g_pDBService.userSteal.getTotalStolenCount(uid, i)
|
||||||
|
|
||||||
number -= stealNum
|
number -= stealNum
|
||||||
@ -499,44 +557,67 @@ class CFarmManager:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
harvestCount += 1
|
harvestCount += 1
|
||||||
experience += plantInfo['experience']
|
experience += plantInfo["experience"]
|
||||||
|
|
||||||
harvestRecords.append(f"收获作物:{soilInfo['plantName']},数量为:{number},经验为:{plantInfo['experience']}")
|
harvestRecords.append(
|
||||||
|
g_sTranslation["harvest"]["append"].format(
|
||||||
|
name=soilInfo["plantName"],
|
||||||
|
num=number,
|
||||||
|
exp=plantInfo["experience"],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
await g_pDBService.userPlant.addUserPlantByUid(uid, soilInfo['plantName'], number)
|
await g_pDBService.userPlant.addUserPlantByUid(
|
||||||
|
uid, soilInfo["plantName"], number
|
||||||
|
)
|
||||||
|
|
||||||
#如果到达收获次数上限
|
# 如果到达收获次数上限
|
||||||
if soilInfo['harvestCount'] + 1 >= plantInfo['crop']:
|
if soilInfo["harvestCount"] + 1 >= plantInfo["crop"]:
|
||||||
await g_pDBService.userSoil.updateUserSoil(uid, i, "wiltStatus", 1)
|
await g_pDBService.userSoil.updateUserSoil(
|
||||||
|
uid, i, "wiltStatus", 1
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
phase = await g_pDBService.plant.getPlantPhaseByName(soilInfo['plantName'])
|
phase = await g_pDBService.plant.getPlantPhaseByName(
|
||||||
|
soilInfo["plantName"]
|
||||||
|
)
|
||||||
|
|
||||||
ts, hc = int(currentTime.timestamp()), soilInfo["harvestCount"] + 1
|
ts, hc = (
|
||||||
|
int(currentTime.timestamp()),
|
||||||
|
soilInfo["harvestCount"] + 1,
|
||||||
|
)
|
||||||
p1, p2, *rest = phase
|
p1, p2, *rest = phase
|
||||||
|
|
||||||
await g_pDBService.userSoil.updateUserSoilFields(uid, i,
|
await g_pDBService.userSoil.updateUserSoilFields(
|
||||||
|
uid,
|
||||||
|
i,
|
||||||
{
|
{
|
||||||
"harvestCount": hc,
|
"harvestCount": hc,
|
||||||
"plantTime": ts - p1 - p2,
|
"plantTime": ts - p1 - p2,
|
||||||
"matureTime": ts + p2 + sum(rest),
|
"matureTime": ts + p2 + sum(rest),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
await g_pEventManager.m_afterHarvest.emit(uid=uid, name=soilInfo['plantName'], num=number, soilIndex=i)
|
await g_pEventManager.m_afterHarvest.emit(
|
||||||
|
uid=uid, name=soilInfo["plantName"], num=number, soilIndex=i
|
||||||
|
)
|
||||||
|
|
||||||
if experience > 0:
|
if experience > 0:
|
||||||
exp = await g_pDBService.user.getUserExpByUid(uid)
|
exp = await g_pDBService.user.getUserExpByUid(uid)
|
||||||
await g_pDBService.user.updateUserExpByUid(uid, exp + experience)
|
await g_pDBService.user.updateUserExpByUid(uid, exp + experience)
|
||||||
harvestRecords.append(f"\t累计获得经验:{experience}")
|
harvestRecords.append(
|
||||||
|
g_sTranslation["harvest"]["exp"].format(
|
||||||
|
exp=experience,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if harvestCount <= 0:
|
if harvestCount <= 0:
|
||||||
return "没有可收获的作物哦~ 不要试图拔苗助长"
|
return g_sTranslation["harvest"]["no"]
|
||||||
else:
|
else:
|
||||||
return "\n".join(harvestRecords)
|
return "\n".join(harvestRecords)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"收获操作失败!", e=e)
|
logger.warning("收获操作失败!", e=e)
|
||||||
return "收获失败,请稍后重试!"
|
return g_sTranslation["harvest"]["error"]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def eradicate(cls, uid: str) -> str:
|
async def eradicate(cls, uid: str) -> str:
|
||||||
@ -554,7 +635,7 @@ class CFarmManager:
|
|||||||
|
|
||||||
experience = 0
|
experience = 0
|
||||||
for i in range(1, soilNumber + 1):
|
for i in range(1, soilNumber + 1):
|
||||||
#如果没有种植
|
# 如果没有种植
|
||||||
if not await g_pDBService.userSoil.isSoilPlanted(uid, i):
|
if not await g_pDBService.userSoil.isSoilPlanted(uid, i):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -562,7 +643,7 @@ class CFarmManager:
|
|||||||
if not soilInfo:
|
if not soilInfo:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
#如果不是枯萎状态
|
# 如果不是枯萎状态
|
||||||
if soilInfo.get("wiltStatus", 0) == 0:
|
if soilInfo.get("wiltStatus", 0) == 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -571,10 +652,10 @@ class CFarmManager:
|
|||||||
if g_bIsDebug:
|
if g_bIsDebug:
|
||||||
experience += 999
|
experience += 999
|
||||||
|
|
||||||
#批量更新数据库操作
|
# 批量更新数据库操作
|
||||||
await g_pDBService.userSoil.deleteUserSoil(uid, i)
|
await g_pDBService.userSoil.deleteUserSoil(uid, i)
|
||||||
|
|
||||||
#铲除作物会将偷菜记录清空
|
# 铲除作物会将偷菜记录清空
|
||||||
await g_pDBService.userSteal.deleteStealRecord(uid, i)
|
await g_pDBService.userSteal.deleteStealRecord(uid, i)
|
||||||
|
|
||||||
await g_pEventManager.m_afterEradicate.emit(uid=uid, soilIndex=i)
|
await g_pEventManager.m_afterEradicate.emit(uid=uid, soilIndex=i)
|
||||||
@ -583,9 +664,9 @@ class CFarmManager:
|
|||||||
exp = await g_pDBService.user.getUserExpByUid(uid)
|
exp = await g_pDBService.user.getUserExpByUid(uid)
|
||||||
await g_pDBService.user.updateUserExpByUid(uid, exp + experience)
|
await g_pDBService.user.updateUserExpByUid(uid, exp + experience)
|
||||||
|
|
||||||
return f"成功铲除荒废作物,累计获得经验:{experience}"
|
return g_sTranslation["eradicate"]["success"].format(exp=experience)
|
||||||
else:
|
else:
|
||||||
return "没有可以铲除的作物"
|
return g_sTranslation["eradicate"]["error"]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def getUserPlantByUid(cls, uid: str) -> bytes:
|
async def getUserPlantByUid(cls, uid: str) -> bytes:
|
||||||
@ -598,14 +679,7 @@ class CFarmManager:
|
|||||||
bytes: 返回图片
|
bytes: 返回图片
|
||||||
"""
|
"""
|
||||||
data_list = []
|
data_list = []
|
||||||
column_name = [
|
column_name = ["-", "作物名称", "数量", "单价", "总价", "是否可以上架交易行"]
|
||||||
"-",
|
|
||||||
"作物名称",
|
|
||||||
"数量",
|
|
||||||
"单价",
|
|
||||||
"总价",
|
|
||||||
"是否可以上架交易行"
|
|
||||||
]
|
|
||||||
|
|
||||||
plant = await g_pDBService.userPlant.getUserPlantByUid(uid)
|
plant = await g_pDBService.userPlant.getUserPlantByUid(uid)
|
||||||
|
|
||||||
@ -629,23 +703,14 @@ class CFarmManager:
|
|||||||
if icon_path.exists():
|
if icon_path.exists():
|
||||||
icon = (icon_path, 33, 33)
|
icon = (icon_path, 33, 33)
|
||||||
|
|
||||||
if plantInfo['sell'] == True:
|
if plantInfo["sell"] == True:
|
||||||
sell = "可以"
|
sell = "可以"
|
||||||
else:
|
else:
|
||||||
sell = "不可以"
|
sell = "不可以"
|
||||||
|
|
||||||
number = int(count) * plantInfo['price']
|
number = int(count) * plantInfo["price"]
|
||||||
|
|
||||||
data_list.append(
|
data_list.append([icon, name, count, plantInfo["price"], number, sell])
|
||||||
[
|
|
||||||
icon,
|
|
||||||
name,
|
|
||||||
count,
|
|
||||||
plantInfo['price'],
|
|
||||||
number,
|
|
||||||
sell
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
result = await ImageTemplate.table_page(
|
result = await ImageTemplate.table_page(
|
||||||
"作物仓库",
|
"作物仓库",
|
||||||
@ -667,30 +732,33 @@ class CFarmManager:
|
|||||||
Returns:
|
Returns:
|
||||||
str: 返回
|
str: 返回
|
||||||
"""
|
"""
|
||||||
#用户信息
|
# 用户信息
|
||||||
userInfo = await g_pDBService.user.getUserInfoByUid(uid)
|
userInfo = await g_pDBService.user.getUserInfoByUid(uid)
|
||||||
|
|
||||||
stealTime = userInfo.get('stealTime', "")
|
stealTime = userInfo.get("stealTime", "")
|
||||||
stealCount = int(userInfo['stealCount'])
|
stealCount = int(userInfo["stealCount"])
|
||||||
|
|
||||||
if stealTime == "" or not stealTime:
|
if stealTime == "" or not stealTime:
|
||||||
stealTime = g_pToolManager.dateTime().date().today().strftime('%Y-%m-%d')
|
stealTime = g_pToolManager.dateTime().date().today().strftime("%Y-%m-%d")
|
||||||
stealCount = 5
|
stealCount = 5
|
||||||
elif g_pToolManager.dateTime().date().fromisoformat(stealTime) != g_pToolManager.dateTime().date().today():
|
elif (
|
||||||
stealTime = g_pToolManager.dateTime().date().today().strftime('%Y-%m-%d')
|
g_pToolManager.dateTime().date().fromisoformat(stealTime)
|
||||||
|
!= g_pToolManager.dateTime().date().today()
|
||||||
|
):
|
||||||
|
stealTime = g_pToolManager.dateTime().date().today().strftime("%Y-%m-%d")
|
||||||
stealCount = 5
|
stealCount = 5
|
||||||
|
|
||||||
if stealCount <= 0:
|
if stealCount <= 0:
|
||||||
return "你今天可偷次数到达上限啦,手下留情吧"
|
return g_sTranslation["stealing"]["max"]
|
||||||
|
|
||||||
#获取用户解锁地块数量
|
# 获取用户解锁地块数量
|
||||||
soilNumber = await g_pDBService.user.getUserSoilByUid(target)
|
soilNumber = await g_pDBService.user.getUserSoilByUid(target)
|
||||||
harvestRecords: List[str] = []
|
harvestRecords: list[str] = []
|
||||||
isStealingNumber = 0
|
isStealingNumber = 0
|
||||||
isStealingPlant = 0
|
isStealingPlant = 0
|
||||||
|
|
||||||
for i in range(1, soilNumber + 1):
|
for i in range(1, soilNumber + 1):
|
||||||
#如果没有种植
|
# 如果没有种植
|
||||||
if not await g_pDBService.userSoil.isSoilPlanted(target, i):
|
if not await g_pDBService.userSoil.isSoilPlanted(target, i):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -698,123 +766,162 @@ class CFarmManager:
|
|||||||
if not soilInfo:
|
if not soilInfo:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
#如果是枯萎状态
|
# 如果是枯萎状态
|
||||||
if soilInfo.get("wiltStatus", 1) == 1:
|
if soilInfo.get("wiltStatus", 1) == 1:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
#作物信息
|
# 作物信息
|
||||||
plantInfo = await g_pDBService.plant.getPlantByName(soilInfo['plantName'])
|
plantInfo = await g_pDBService.plant.getPlantByName(soilInfo["plantName"])
|
||||||
if not plantInfo:
|
if not plantInfo:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
currentTime = g_pToolManager.dateTime().now()
|
currentTime = g_pToolManager.dateTime().now()
|
||||||
matureTime = g_pToolManager.dateTime().fromtimestamp(int(soilInfo['matureTime']))
|
matureTime = g_pToolManager.dateTime().fromtimestamp(
|
||||||
|
int(soilInfo["matureTime"])
|
||||||
|
)
|
||||||
|
|
||||||
if currentTime >= matureTime:
|
if currentTime >= matureTime:
|
||||||
#如果偷过,则跳过该土地
|
# 如果偷过,则跳过该土地
|
||||||
if await g_pDBService.userSteal.hasStealed(target, i, uid):
|
if await g_pDBService.userSteal.hasStealed(target, i, uid):
|
||||||
|
isStealingNumber += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
stealingNumber = plantInfo['harvest'] - await g_pDBService.userSteal.getTotalStolenCount(target, i)
|
stealingNumber = plantInfo[
|
||||||
|
"harvest"
|
||||||
|
] - await g_pDBService.userSteal.getTotalStolenCount(target, i)
|
||||||
randomNumber = random.choice([1, 2])
|
randomNumber = random.choice([1, 2])
|
||||||
randomNumber = min(randomNumber, stealingNumber)
|
randomNumber = min(randomNumber, stealingNumber)
|
||||||
|
|
||||||
if randomNumber > 0:
|
if randomNumber > 0:
|
||||||
await g_pDBService.userPlant.addUserPlantByUid(uid, soilInfo['plantName'], randomNumber)
|
await g_pDBService.userPlant.addUserPlantByUid(
|
||||||
|
uid, soilInfo["plantName"], randomNumber
|
||||||
|
)
|
||||||
|
|
||||||
harvestRecords.append(f"成功偷到作物:{soilInfo['plantName']},数量为:{randomNumber}")
|
harvestRecords.append(
|
||||||
|
g_sTranslation["stealing"]["info"].format(
|
||||||
|
name=soilInfo["plantName"], num=randomNumber
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
isStealingPlant += 1
|
isStealingPlant += 1
|
||||||
|
|
||||||
#如果将作物偷完,就直接更新状态 并记录用户偷取过
|
# 如果将作物偷完,就直接更新状态 并记录用户偷取过
|
||||||
if plantInfo['harvest'] - randomNumber + stealingNumber == 0:
|
if plantInfo["harvest"] - randomNumber + stealingNumber == 0:
|
||||||
#如果作物 是最后一阶段作物且偷完 则直接枯萎
|
# 如果作物 是最后一阶段作物且偷完 则直接枯萎
|
||||||
if soilInfo['harvestCount'] + 1 >= plantInfo['crop']:
|
if soilInfo["harvestCount"] + 1 >= plantInfo["crop"]:
|
||||||
await g_pDBService.userSoil.updateUserSoil(target, i, "wiltStatus", 1)
|
await g_pDBService.userSoil.updateUserSoil(
|
||||||
|
target, i, "wiltStatus", 1
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
phase = await g_pDBService.plant.getPlantPhaseByName(soilInfo['plantName'])
|
phase = await g_pDBService.plant.getPlantPhaseByName(
|
||||||
|
soilInfo["plantName"]
|
||||||
|
)
|
||||||
|
|
||||||
ts, hc = int(currentTime.timestamp()), soilInfo["harvestCount"] + 1
|
ts, hc = (
|
||||||
|
int(currentTime.timestamp()),
|
||||||
|
soilInfo["harvestCount"] + 1,
|
||||||
|
)
|
||||||
p1, p2, *rest = phase
|
p1, p2, *rest = phase
|
||||||
|
|
||||||
await g_pDBService.userSoil.updateUserSoilFields(uid, i,
|
await g_pDBService.userSoil.updateUserSoilFields(
|
||||||
|
uid,
|
||||||
|
i,
|
||||||
{
|
{
|
||||||
"harvestCount": hc,
|
"harvestCount": hc,
|
||||||
"plantTime": ts - p1 - p2,
|
"plantTime": ts - p1 - p2,
|
||||||
"matureTime": ts + p2 + sum(rest),
|
"matureTime": ts + p2 + sum(rest),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
await g_pDBService.userSteal.addStealRecord(target, i, uid, randomNumber, int(g_pToolManager.dateTime().now().timestamp()))
|
await g_pDBService.userSteal.addStealRecord(
|
||||||
|
target,
|
||||||
|
i,
|
||||||
|
uid,
|
||||||
|
randomNumber,
|
||||||
|
int(g_pToolManager.dateTime().now().timestamp()),
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
await g_pDBService.userSteal.addStealRecord(target, i, uid, randomNumber, int(g_pToolManager.dateTime().now().timestamp()))
|
await g_pDBService.userSteal.addStealRecord(
|
||||||
|
target,
|
||||||
|
i,
|
||||||
|
uid,
|
||||||
|
randomNumber,
|
||||||
|
int(g_pToolManager.dateTime().now().timestamp()),
|
||||||
|
)
|
||||||
|
|
||||||
if isStealingPlant <= 0 and isStealingNumber <= 0:
|
if isStealingPlant <= 0 and isStealingNumber <= 0:
|
||||||
return "目标没有作物可以被偷"
|
return g_sTranslation["stealing"]["noPlant"]
|
||||||
elif isStealingPlant <= 0 and isStealingNumber > 0:
|
elif isStealingPlant <= 0 and isStealingNumber > 0:
|
||||||
return "你已经偷过目标啦,请手下留情"
|
return g_sTranslation["stealing"]["repeat"]
|
||||||
else:
|
else:
|
||||||
stealCount -= 1
|
stealCount -= 1
|
||||||
|
|
||||||
await g_pDBService.user.updateStealCountByUid(uid, stealCount)
|
await g_pDBService.user.updateStealCountByUid(uid, stealTime, stealCount)
|
||||||
|
|
||||||
return "\n".join(harvestRecords)
|
return "\n".join(harvestRecords)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def reclamationCondition(cls, uid: str) -> str:
|
async def reclamationCondition(cls, uid: str) -> str:
|
||||||
userInfo = await g_pDBService.user.getUserInfoByUid(uid)
|
userInfo = await g_pDBService.user.getUserInfoByUid(uid)
|
||||||
rec = g_pJsonManager.m_pLevel['reclamation']
|
rec = g_pJsonManager.m_pLevel["reclamation"]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if userInfo['soil'] >= 30:
|
if userInfo["soil"] >= 30:
|
||||||
return "你已经开垦了全部土地"
|
return g_sTranslation["reclamation"]["perfect"]
|
||||||
|
|
||||||
rec = rec[f"{userInfo['soil'] + 1}"]
|
rec = rec[f"{userInfo['soil'] + 1}"]
|
||||||
|
|
||||||
level = rec['level']
|
level = rec["level"]
|
||||||
point = rec['point']
|
point = rec["point"]
|
||||||
item = rec['item']
|
item = rec["item"]
|
||||||
|
|
||||||
str = ""
|
str = ""
|
||||||
if len(item) == 0:
|
if len(item) == 0:
|
||||||
str = f"下次开垦所需条件:等级:{level},农场币:{point}"
|
str = g_sTranslation["reclamation"]["next"].format(
|
||||||
|
level=level, num=point
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
str = f"下次开垦所需条件:等级:{level},农场币:{point},物品:{item}"
|
str = g_sTranslation["reclamation"]["next2"].format(
|
||||||
|
level=level, num=point, item=item
|
||||||
|
)
|
||||||
|
|
||||||
return str
|
return str
|
||||||
except Exception as e:
|
except Exception:
|
||||||
return "获取开垦土地条件失败!"
|
return g_sTranslation["reclamation"]["error"]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def reclamation(cls, uid: str) -> str:
|
async def reclamation(cls, uid: str) -> str:
|
||||||
userInfo = await g_pDBService.user.getUserInfoByUid(uid)
|
userInfo = await g_pDBService.user.getUserInfoByUid(uid)
|
||||||
level = await g_pDBService.user.getUserLevelByUid(uid)
|
level = await g_pDBService.user.getUserLevelByUid(uid)
|
||||||
|
|
||||||
rec = g_pJsonManager.m_pLevel['reclamation']
|
rec = g_pJsonManager.m_pLevel["reclamation"]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if userInfo['soil'] >= 30:
|
if userInfo["soil"] >= 30:
|
||||||
return "你已经开垦了全部土地"
|
return g_sTranslation["reclamation"]["perfect"]
|
||||||
|
|
||||||
rec = rec[f"{userInfo['soil'] + 1}"]
|
rec = rec[f"{userInfo['soil'] + 1}"]
|
||||||
|
|
||||||
levelFileter = rec['level']
|
levelFileter = rec["level"]
|
||||||
point = rec['point']
|
point = rec["point"]
|
||||||
item = rec['item']
|
item = rec["item"]
|
||||||
|
|
||||||
if level[0] < levelFileter:
|
if level[0] < levelFileter:
|
||||||
return f"当前用户等级{level[0]},升级所需等级为{levelFileter}"
|
return g_sTranslation["reclamation"]["nextLevel"].format(
|
||||||
|
level=level[0], next=levelFileter
|
||||||
|
)
|
||||||
|
|
||||||
if userInfo['point'] < point:
|
if userInfo["point"] < point:
|
||||||
return f"当前用户农场币不足,升级所需农场币为{point}"
|
return g_sTranslation["reclamation"]["noNum"].format(num=point)
|
||||||
|
|
||||||
#TODO 缺少判断消耗的item
|
# TODO 缺少判断消耗的item
|
||||||
await g_pDBService.user.updateUserPointByUid(uid, userInfo['point'] - point)
|
await g_pDBService.user.updateUserPointByUid(uid, userInfo["point"] - point)
|
||||||
await g_pDBService.user.updateUserSoilByUid(uid, userInfo['soil'] + 1)
|
await g_pDBService.user.updateUserSoilByUid(uid, userInfo["soil"] + 1)
|
||||||
|
|
||||||
|
return g_sTranslation["reclamation"]["success"]
|
||||||
|
except Exception:
|
||||||
|
return g_sTranslation["reclamation"]["error1"]
|
||||||
|
|
||||||
return "开垦土地成功!"
|
|
||||||
except Exception as e:
|
|
||||||
return "执行开垦失败!"
|
|
||||||
|
|
||||||
g_pFarmManager = CFarmManager()
|
g_pFarmManager = CFarmManager()
|
||||||
|
|||||||
90
farm/shop.py
90
farm/shop.py
@ -1,19 +1,15 @@
|
|||||||
import math
|
import math
|
||||||
import plistlib
|
|
||||||
from itertools import islice
|
|
||||||
|
|
||||||
from zhenxun.services.log import logger
|
from zhenxun.services.log import logger
|
||||||
from zhenxun.utils._build_image import BuildImage
|
|
||||||
from zhenxun.utils.image_utils import ImageTemplate
|
from zhenxun.utils.image_utils import ImageTemplate
|
||||||
|
|
||||||
from ..config import g_sResourcePath
|
from ..config import g_sResourcePath, g_sTranslation
|
||||||
from ..dbService import g_pDBService
|
from ..dbService import g_pDBService
|
||||||
from ..json import g_pJsonManager
|
|
||||||
|
|
||||||
|
|
||||||
class CShopManager:
|
class CShopManager:
|
||||||
@classmethod
|
@classmethod
|
||||||
async def getSeedShopImage(cls, filterKey: str|int = 1, num: int = 1) -> bytes:
|
async def getSeedShopImage(cls, filterKey: str | int = 1, num: int = 1) -> bytes:
|
||||||
"""获取商店页面
|
"""获取商店页面
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -44,7 +40,7 @@ class CShopManager:
|
|||||||
"收获数量",
|
"收获数量",
|
||||||
"成熟时间(小时)",
|
"成熟时间(小时)",
|
||||||
"收获次数",
|
"收获次数",
|
||||||
"是否可以上架交易行"
|
"是否可以上架交易行",
|
||||||
]
|
]
|
||||||
|
|
||||||
# 查询所有可购买作物,并根据筛选关键字过滤
|
# 查询所有可购买作物,并根据筛选关键字过滤
|
||||||
@ -52,10 +48,10 @@ class CShopManager:
|
|||||||
filteredPlants = []
|
filteredPlants = []
|
||||||
for plant in plants:
|
for plant in plants:
|
||||||
# 跳过未解锁购买的种子
|
# 跳过未解锁购买的种子
|
||||||
if plant['isBuy'] == 0:
|
if plant["isBuy"] == 0:
|
||||||
continue
|
continue
|
||||||
# 字符串筛选
|
# 字符串筛选
|
||||||
if filterStr and filterStr not in plant['name']:
|
if filterStr and filterStr not in plant["name"]:
|
||||||
continue
|
continue
|
||||||
filteredPlants.append(plant)
|
filteredPlants.append(plant)
|
||||||
|
|
||||||
@ -63,7 +59,7 @@ class CShopManager:
|
|||||||
totalCount = len(filteredPlants)
|
totalCount = len(filteredPlants)
|
||||||
pageCount = math.ceil(totalCount / 15) if totalCount else 1
|
pageCount = math.ceil(totalCount / 15) if totalCount else 1
|
||||||
startIndex = (page - 1) * 15
|
startIndex = (page - 1) * 15
|
||||||
pageItems = filteredPlants[startIndex: startIndex + 15]
|
pageItems = filteredPlants[startIndex : startIndex + 15]
|
||||||
|
|
||||||
# 构建数据行
|
# 构建数据行
|
||||||
dataList = []
|
dataList = []
|
||||||
@ -75,20 +71,22 @@ class CShopManager:
|
|||||||
icon = (iconPath, 33, 33)
|
icon = (iconPath, 33, 33)
|
||||||
|
|
||||||
# 交易行标记
|
# 交易行标记
|
||||||
sell = "可以" if plant['sell'] else "不可以"
|
sell = "可以" if plant["sell"] else "不可以"
|
||||||
|
|
||||||
dataList.append([
|
dataList.append(
|
||||||
|
[
|
||||||
icon,
|
icon,
|
||||||
plant['name'], # 种子名称
|
plant["name"], # 种子名称
|
||||||
plant['buy'], # 种子单价
|
plant["buy"], # 种子单价
|
||||||
plant['level'], # 解锁等级
|
plant["level"], # 解锁等级
|
||||||
plant['price'], # 果实单价
|
plant["price"], # 果实单价
|
||||||
plant['experience'], # 收获经验
|
plant["experience"], # 收获经验
|
||||||
plant['harvest'], # 收获数量
|
plant["harvest"], # 收获数量
|
||||||
plant['time'], # 成熟时间(小时)
|
plant["time"], # 成熟时间(小时)
|
||||||
plant['crop'], # 收获次数
|
plant["crop"], # 收获次数
|
||||||
sell # 是否可上架交易行
|
sell, # 是否可上架交易行
|
||||||
])
|
]
|
||||||
|
)
|
||||||
|
|
||||||
# 页码标题
|
# 页码标题
|
||||||
title = f"种子商店 页数: {page}/{pageCount}"
|
title = f"种子商店 页数: {page}/{pageCount}"
|
||||||
@ -102,7 +100,6 @@ class CShopManager:
|
|||||||
)
|
)
|
||||||
return result.pic2bytes()
|
return result.pic2bytes()
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def buySeed(cls, uid: str, name: str, num: int = 1) -> str:
|
async def buySeed(cls, uid: str, name: str, num: int = 1) -> str:
|
||||||
"""购买种子
|
"""购买种子
|
||||||
@ -117,31 +114,35 @@ class CShopManager:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if num <= 0:
|
if num <= 0:
|
||||||
return "请输入购买数量!"
|
return g_sTranslation["buySeed"]["notNum"]
|
||||||
|
|
||||||
plantInfo = await g_pDBService.plant.getPlantByName(name)
|
plantInfo = await g_pDBService.plant.getPlantByName(name)
|
||||||
if not plantInfo:
|
if not plantInfo:
|
||||||
return "购买出错!请检查需购买的种子名称!"
|
return g_sTranslation["buySeed"]["error"]
|
||||||
|
|
||||||
level = await g_pDBService.user.getUserLevelByUid(uid)
|
level = await g_pDBService.user.getUserLevelByUid(uid)
|
||||||
|
|
||||||
if level[0] < int(plantInfo['level']):
|
if level[0] < int(plantInfo["level"]):
|
||||||
return "你的等级不够哦,努努力吧"
|
return g_sTranslation["buySeed"]["noLevel"]
|
||||||
|
|
||||||
point = await g_pDBService.user.getUserPointByUid(uid)
|
point = await g_pDBService.user.getUserPointByUid(uid)
|
||||||
total = int(plantInfo['buy']) * num
|
total = int(plantInfo["buy"]) * num
|
||||||
|
|
||||||
logger.debug(f"用户:{uid}购买{name},数量为{num}。用户农场币为{point},购买需要{total}")
|
logger.debug(
|
||||||
|
f"用户:{uid}购买{name},数量为{num}。用户农场币为{point},购买需要{total}"
|
||||||
|
)
|
||||||
|
|
||||||
if point < total:
|
if point < total:
|
||||||
return "你的农场币不够哦~ 快速速氪金吧!"
|
return g_sTranslation["buySeed"]["noPoint"]
|
||||||
else:
|
else:
|
||||||
await g_pDBService.user.updateUserPointByUid(uid, point - total)
|
await g_pDBService.user.updateUserPointByUid(uid, point - total)
|
||||||
|
|
||||||
if not await g_pDBService.userSeed.addUserSeedByUid(uid, name, num):
|
if not await g_pDBService.userSeed.addUserSeedByUid(uid, name, num):
|
||||||
return "购买失败,执行数据库错误!"
|
return g_sTranslation["buySeed"]["errorSql"]
|
||||||
|
|
||||||
return f"成功购买{name},花费{total}农场币, 剩余{point - total}农场币"
|
return g_sTranslation["buySeed"]["success"].format(
|
||||||
|
name=name, total=total, point=point - total
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def sellPlantByUid(cls, uid: str, name: str = "", num: int = 1) -> str:
|
async def sellPlantByUid(cls, uid: str, name: str = "", num: int = 1) -> str:
|
||||||
@ -158,11 +159,11 @@ class CShopManager:
|
|||||||
|
|
||||||
plant = await g_pDBService.userPlant.getUserPlantByUid(uid)
|
plant = await g_pDBService.userPlant.getUserPlantByUid(uid)
|
||||||
if not plant:
|
if not plant:
|
||||||
return "你仓库没有可以出售的作物"
|
return g_sTranslation["sellPlant"]["no"]
|
||||||
|
|
||||||
point = 0
|
point = 0
|
||||||
totalSold = 0
|
totalSold = 0
|
||||||
isAll = (num == -1)
|
isAll = num == -1
|
||||||
|
|
||||||
if name == "":
|
if name == "":
|
||||||
for plantName, count in plant.items():
|
for plantName, count in plant.items():
|
||||||
@ -170,16 +171,18 @@ class CShopManager:
|
|||||||
if not plantInfo:
|
if not plantInfo:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
point += plantInfo['price'] * count
|
point += plantInfo["price"] * count
|
||||||
await g_pDBService.userPlant.updateUserPlantByName(uid, plantName, 0)
|
await g_pDBService.userPlant.updateUserPlantByName(uid, plantName, 0)
|
||||||
else:
|
else:
|
||||||
if name not in plant:
|
if name not in plant:
|
||||||
return f"出售作物{name}出错:仓库中不存在该作物"
|
return g_sTranslation["sellPlant"]["error"].format(name=name)
|
||||||
available = plant[name]
|
available = plant[name]
|
||||||
sellAmount = available if isAll else min(available, num)
|
sellAmount = available if isAll else min(available, num)
|
||||||
if sellAmount <= 0:
|
if sellAmount <= 0:
|
||||||
return f"出售作物{name}出错:数量不足"
|
return g_sTranslation["sellPlant"]["error1"].format(name=name)
|
||||||
await g_pDBService.userPlant.updateUserPlantByName(uid, name, available - sellAmount)
|
await g_pDBService.userPlant.updateUserPlantByName(
|
||||||
|
uid, name, available - sellAmount
|
||||||
|
)
|
||||||
totalSold = sellAmount
|
totalSold = sellAmount
|
||||||
|
|
||||||
if name == "":
|
if name == "":
|
||||||
@ -189,7 +192,7 @@ class CShopManager:
|
|||||||
if not plantInfo:
|
if not plantInfo:
|
||||||
price = 0
|
price = 0
|
||||||
else:
|
else:
|
||||||
price = plantInfo['price']
|
price = plantInfo["price"]
|
||||||
|
|
||||||
totalPoint = totalSold * price
|
totalPoint = totalSold * price
|
||||||
|
|
||||||
@ -197,8 +200,13 @@ class CShopManager:
|
|||||||
await g_pDBService.user.updateUserPointByUid(uid, currentPoint + totalPoint)
|
await g_pDBService.user.updateUserPointByUid(uid, currentPoint + totalPoint)
|
||||||
|
|
||||||
if name == "":
|
if name == "":
|
||||||
return f"成功出售所有作物,获得农场币:{totalPoint},当前农场币:{currentPoint + totalPoint}"
|
return g_sTranslation["sellPlant"]["success"].format(
|
||||||
|
point=totalPoint, num=currentPoint + totalPoint
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return f"成功出售{name},获得农场币:{totalPoint},当前农场币:{currentPoint + totalPoint}"
|
return g_sTranslation["sellPlant"]["success1"].format(
|
||||||
|
name=name, point=totalPoint, num=currentPoint + totalPoint
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
g_pShopManager = CShopManager()
|
g_pShopManager = CShopManager()
|
||||||
|
|||||||
2
json.py
2
json.py
@ -1,5 +1,4 @@
|
|||||||
import json
|
import json
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from zhenxun.services.log import logger
|
from zhenxun.services.log import logger
|
||||||
|
|
||||||
@ -98,4 +97,5 @@ class CJsonManager:
|
|||||||
logger.warning(f"sign_in.json JSON格式错误: {e}")
|
logger.warning(f"sign_in.json JSON格式错误: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
g_pJsonManager = CJsonManager()
|
g_pJsonManager = CJsonManager()
|
||||||
|
|||||||
27
request.py
27
request.py
@ -1,6 +1,5 @@
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
@ -15,12 +14,14 @@ class CRequestManager:
|
|||||||
m_sTokens = "xZ%?z5LtWV7H:0-Xnwp+bNRNQ-jbfrxG"
|
m_sTokens = "xZ%?z5LtWV7H:0-Xnwp+bNRNQ-jbfrxG"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def download(cls,
|
async def download(
|
||||||
|
cls,
|
||||||
url: str,
|
url: str,
|
||||||
savePath: str,
|
savePath: str,
|
||||||
fileName: str,
|
fileName: str,
|
||||||
params: dict | None = None,
|
params: dict | None = None,
|
||||||
jsonData: dict | None = None) -> bool:
|
jsonData: dict | None = None,
|
||||||
|
) -> bool:
|
||||||
"""下载文件到指定路径并覆盖已存在的文件
|
"""下载文件到指定路径并覆盖已存在的文件
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -51,7 +52,9 @@ class CRequestManager:
|
|||||||
f.write(response.content)
|
f.write(response.content)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
logger.warning(f"文件下载失败: HTTP {response.status_code} {response.text}")
|
logger.warning(
|
||||||
|
f"文件下载失败: HTTP {response.status_code} {response.text}"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -84,7 +87,9 @@ class CRequestManager:
|
|||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
return response.json()
|
return response.json()
|
||||||
else:
|
else:
|
||||||
logger.warning(f"{name}请求失败: HTTP {response.status_code} {response.text}")
|
logger.warning(
|
||||||
|
f"{name}请求失败: HTTP {response.status_code} {response.text}"
|
||||||
|
)
|
||||||
return {}
|
return {}
|
||||||
except httpx.RequestError as e:
|
except httpx.RequestError as e:
|
||||||
logger.warning(f"{name}请求异常", e=e)
|
logger.warning(f"{name}请求异常", e=e)
|
||||||
@ -115,7 +120,9 @@ class CRequestManager:
|
|||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
return response.json()
|
return response.json()
|
||||||
else:
|
else:
|
||||||
logger.warning(f"{name}请求失败: HTTP {response.status_code} {response.text}")
|
logger.warning(
|
||||||
|
f"{name}请求失败: HTTP {response.status_code} {response.text}"
|
||||||
|
)
|
||||||
return {}
|
return {}
|
||||||
except httpx.RequestError as e:
|
except httpx.RequestError as e:
|
||||||
logger.warning(f"{name}请求异常", e=e)
|
logger.warning(f"{name}请求异常", e=e)
|
||||||
@ -128,7 +135,7 @@ class CRequestManager:
|
|||||||
async def initSignInFile(cls) -> bool:
|
async def initSignInFile(cls) -> bool:
|
||||||
if os.path.exists(g_sSignInPath):
|
if os.path.exists(g_sSignInPath):
|
||||||
try:
|
try:
|
||||||
with open(g_sSignInPath, "r", encoding="utf-8") as f:
|
with open(g_sSignInPath, encoding="utf-8") as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
sign = json.loads(content)
|
sign = json.loads(content)
|
||||||
|
|
||||||
@ -141,8 +148,8 @@ class CRequestManager:
|
|||||||
else:
|
else:
|
||||||
logger.warning("真寻农场签到文件检查失败, 即将下载")
|
logger.warning("真寻农场签到文件检查失败, 即将下载")
|
||||||
return await cls.downloadSignInFile()
|
return await cls.downloadSignInFile()
|
||||||
except json.JSONDecodeError as e:
|
except json.JSONDecodeError:
|
||||||
logger.warning(f"真寻农场签到文件格式错误, 即将下载")
|
logger.warning("真寻农场签到文件格式错误, 即将下载")
|
||||||
return await cls.downloadSignInFile()
|
return await cls.downloadSignInFile()
|
||||||
else:
|
else:
|
||||||
return await cls.downloadSignInFile()
|
return await cls.downloadSignInFile()
|
||||||
@ -156,7 +163,7 @@ class CRequestManager:
|
|||||||
path = str(g_sSignInPath.parent.resolve(strict=False))
|
path = str(g_sSignInPath.parent.resolve(strict=False))
|
||||||
yearMonth = g_pToolManager.dateTime().now().strftime("%Y%m")
|
yearMonth = g_pToolManager.dateTime().now().strftime("%Y%m")
|
||||||
|
|
||||||
await cls.download(url, path, "signTemp.json", jsonData={'date':yearMonth})
|
await cls.download(url, path, "signTemp.json", jsonData={"date": yearMonth})
|
||||||
g_pToolManager.renameFile(f"{path}/signTemp.json", "sign_in.json")
|
g_pToolManager.renameFile(f"{path}/signTemp.json", "sign_in.json")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|||||||
138
tool.py
138
tool.py
@ -3,9 +3,146 @@ from datetime import datetime
|
|||||||
from zoneinfo import ZoneInfo
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
from zhenxun.services.log import logger
|
from zhenxun.services.log import logger
|
||||||
|
from zhenxun.utils.message import MessageUtils
|
||||||
|
|
||||||
|
from .dbService import g_pDBService
|
||||||
|
|
||||||
|
|
||||||
class CToolManager:
|
class CToolManager:
|
||||||
|
@classmethod
|
||||||
|
async def isRegisteredByUid(cls, uid: str) -> bool:
|
||||||
|
result = await g_pDBService.user.isUserExist(uid)
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
await MessageUtils.build_message(
|
||||||
|
"尚未开通农场,快at我发送 开通农场 开通吧"
|
||||||
|
).send()
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def sanitize_username(cls, username: str, max_length: int = 15) -> str:
|
||||||
|
"""
|
||||||
|
安全处理用户名
|
||||||
|
功能:
|
||||||
|
1. 移除首尾空白
|
||||||
|
2. 过滤危险字符
|
||||||
|
3. 转义单引号
|
||||||
|
4. 处理空值
|
||||||
|
5. 限制长度
|
||||||
|
"""
|
||||||
|
# 处理空值
|
||||||
|
if not username:
|
||||||
|
return "神秘农夫"
|
||||||
|
|
||||||
|
# 基础清洗
|
||||||
|
cleaned = username.strip()
|
||||||
|
|
||||||
|
# 允许的字符白名单(可自定义扩展)
|
||||||
|
safe_chars = {
|
||||||
|
"_",
|
||||||
|
"-",
|
||||||
|
"!",
|
||||||
|
"@",
|
||||||
|
"#",
|
||||||
|
"$",
|
||||||
|
"%",
|
||||||
|
"^",
|
||||||
|
"&",
|
||||||
|
"*",
|
||||||
|
"(",
|
||||||
|
")",
|
||||||
|
"+",
|
||||||
|
"=",
|
||||||
|
".",
|
||||||
|
",",
|
||||||
|
"~",
|
||||||
|
"·",
|
||||||
|
" ",
|
||||||
|
"a",
|
||||||
|
"b",
|
||||||
|
"c",
|
||||||
|
"d",
|
||||||
|
"e",
|
||||||
|
"f",
|
||||||
|
"g",
|
||||||
|
"h",
|
||||||
|
"i",
|
||||||
|
"j",
|
||||||
|
"k",
|
||||||
|
"l",
|
||||||
|
"m",
|
||||||
|
"n",
|
||||||
|
"o",
|
||||||
|
"p",
|
||||||
|
"q",
|
||||||
|
"r",
|
||||||
|
"s",
|
||||||
|
"t",
|
||||||
|
"u",
|
||||||
|
"v",
|
||||||
|
"w",
|
||||||
|
"x",
|
||||||
|
"y",
|
||||||
|
"z",
|
||||||
|
"A",
|
||||||
|
"B",
|
||||||
|
"C",
|
||||||
|
"D",
|
||||||
|
"E",
|
||||||
|
"F",
|
||||||
|
"G",
|
||||||
|
"H",
|
||||||
|
"I",
|
||||||
|
"J",
|
||||||
|
"K",
|
||||||
|
"L",
|
||||||
|
"M",
|
||||||
|
"N",
|
||||||
|
"O",
|
||||||
|
"P",
|
||||||
|
"Q",
|
||||||
|
"R",
|
||||||
|
"S",
|
||||||
|
"T",
|
||||||
|
"U",
|
||||||
|
"V",
|
||||||
|
"W",
|
||||||
|
"X",
|
||||||
|
"Y",
|
||||||
|
"Z",
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
"5",
|
||||||
|
"6",
|
||||||
|
"7",
|
||||||
|
"8",
|
||||||
|
"9",
|
||||||
|
}
|
||||||
|
# 添加常用中文字符(Unicode范围)
|
||||||
|
safe_chars.update(chr(c) for c in range(0x4E00, 0x9FFF + 1))
|
||||||
|
|
||||||
|
# 过滤危险字符
|
||||||
|
filtered = [
|
||||||
|
c if c in safe_chars or 0x4E00 <= ord(c) <= 0x9FFF else "" for c in cleaned
|
||||||
|
]
|
||||||
|
|
||||||
|
# 合并处理结果
|
||||||
|
safe_str = "".join(filtered)
|
||||||
|
|
||||||
|
# 转义单引号(双重保障)
|
||||||
|
escaped = safe_str.replace("'", "''")
|
||||||
|
|
||||||
|
# 处理空结果
|
||||||
|
if not escaped:
|
||||||
|
return "神秘农夫"
|
||||||
|
|
||||||
|
# 长度限制
|
||||||
|
return escaped[:max_length]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def renameFile(cls, currentFilePath: str, newFileName: str) -> bool:
|
def renameFile(cls, currentFilePath: str, newFileName: str) -> bool:
|
||||||
@ -36,4 +173,5 @@ class CToolManager:
|
|||||||
tz = ZoneInfo("Asia/Shanghai")
|
tz = ZoneInfo("Asia/Shanghai")
|
||||||
return datetime.now(tz)
|
return datetime.now(tz)
|
||||||
|
|
||||||
|
|
||||||
g_pToolManager = CToolManager()
|
g_pToolManager = CToolManager()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user