nonebot-plugin-fishing2 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nonebot_plugin_fishing/__init__.py +165 -0
- nonebot_plugin_fishing/config.py +95 -0
- nonebot_plugin_fishing/data_source.py +463 -0
- nonebot_plugin_fishing/migrations/1be1c9b715a9_add_achievements.py +39 -0
- nonebot_plugin_fishing/migrations/7609e6d106dd_init_db.py +44 -0
- nonebot_plugin_fishing/migrations/c5ab992c9af3_add_achievements.py +39 -0
- nonebot_plugin_fishing/migrations/e9015df43907_add_special_fishes_field.py +39 -0
- nonebot_plugin_fishing/migrations/f70bdeaec7a4_add_specialfishes_table.py +41 -0
- nonebot_plugin_fishing/model.py +20 -0
- nonebot_plugin_fishing2-0.0.1.dist-info/METADATA +144 -0
- nonebot_plugin_fishing2-0.0.1.dist-info/RECORD +14 -0
- nonebot_plugin_fishing2-0.0.1.dist-info/WHEEL +5 -0
- nonebot_plugin_fishing2-0.0.1.dist-info/licenses/LICENSE +21 -0
- nonebot_plugin_fishing2-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,165 @@
|
|
1
|
+
from nonebot import on_command, require
|
2
|
+
|
3
|
+
require("nonebot_plugin_orm") # noqa
|
4
|
+
|
5
|
+
from nonebot.plugin import PluginMetadata
|
6
|
+
from nonebot.adapters import Event, Message
|
7
|
+
from nonebot.params import CommandArg
|
8
|
+
from nonebot.permission import SUPERUSER
|
9
|
+
|
10
|
+
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, PrivateMessageEvent, Message, MessageSegment, ActionFailed
|
11
|
+
|
12
|
+
import asyncio
|
13
|
+
|
14
|
+
from typing import Union
|
15
|
+
|
16
|
+
from .config import Config, config
|
17
|
+
from .data_source import (
|
18
|
+
choice,
|
19
|
+
can_fishing,
|
20
|
+
can_catch_special_fish,
|
21
|
+
can_free_fish,
|
22
|
+
get_stats,
|
23
|
+
save_fish,
|
24
|
+
save_special_fish,
|
25
|
+
get_backpack,
|
26
|
+
sell_fish,
|
27
|
+
get_balance,
|
28
|
+
free_fish,
|
29
|
+
random_get_a_special_fish,
|
30
|
+
lottery,
|
31
|
+
give,
|
32
|
+
check_achievement,
|
33
|
+
get_achievements,
|
34
|
+
get_board
|
35
|
+
)
|
36
|
+
|
37
|
+
fishing_coin_name = config.fishing_coin_name
|
38
|
+
|
39
|
+
__plugin_meta__ = PluginMetadata(
|
40
|
+
name="赛博钓鱼",
|
41
|
+
description="你甚至可以电子钓鱼",
|
42
|
+
usage=f'''钓鱼帮助
|
43
|
+
▶ 钓鱼:有 {config.fishing_limit}s 的冷却,时间随上一条鱼稀有度变化
|
44
|
+
▶ 卖鱼 [鱼名] [数量]:卖鱼获得{fishing_coin_name}
|
45
|
+
▶ 放生 [鱼名]:给一条鱼取名并放生
|
46
|
+
▶ 祈愿:向神祈愿,随机获取/损失{fishing_coin_name}
|
47
|
+
▶ 背包:查看背包中的{fishing_coin_name}与物品
|
48
|
+
▶ 成就:查看拥有的成就
|
49
|
+
▶ 钓鱼排行榜:查看{fishing_coin_name}排行榜
|
50
|
+
''',
|
51
|
+
type="application",
|
52
|
+
homepage="https://github.com/ALittleBot/nonebot-plugin-fishing",
|
53
|
+
config=Config,
|
54
|
+
supported_adapters=None,
|
55
|
+
)
|
56
|
+
|
57
|
+
fishing_help = on_command("fishing_help", aliases={"钓鱼帮助"}, priority=3,block=True)
|
58
|
+
fishing = on_command("fishing", aliases={"钓鱼"}, priority=5)
|
59
|
+
backpack = on_command("backpack", aliases={"背包", "钓鱼背包"}, priority=5)
|
60
|
+
sell = on_command("sell", aliases={"卖鱼", "出售"}, priority=5)
|
61
|
+
free_fish_cmd = on_command("free_fish", aliases={"放生", "钓鱼放生"}, priority=5)
|
62
|
+
lottery_cmd = on_command("lottery", aliases={"祈愿"}, priority=5)
|
63
|
+
achievement_cmd = on_command("achievement", aliases={"成就", "钓鱼成就"}, priority=5)
|
64
|
+
give_cmd = on_command("give", aliases={"赐予"}, permission=SUPERUSER, priority=5)
|
65
|
+
board_cmd = on_command("board", aliases={"排行榜", "钓鱼排行榜"}, priority=5)
|
66
|
+
|
67
|
+
|
68
|
+
@fishing_help.handle()
|
69
|
+
async def _():
|
70
|
+
await fishing_help.finish(__plugin_meta__.usage)
|
71
|
+
|
72
|
+
@fishing.handle()
|
73
|
+
async def _(event: Event):
|
74
|
+
user_id = event.get_user_id()
|
75
|
+
if not await can_fishing(user_id):
|
76
|
+
await fishing.finish("河累了, 休息一下吧")
|
77
|
+
await fishing.send("正在钓鱼…")
|
78
|
+
if await can_catch_special_fish():
|
79
|
+
special_fish_name = await random_get_a_special_fish()
|
80
|
+
result = f"你钓到了别人放生的 {special_fish_name}"
|
81
|
+
await save_special_fish(user_id, special_fish_name)
|
82
|
+
await fishing.finish(result)
|
83
|
+
choice_result = choice()
|
84
|
+
fish = choice_result[0]
|
85
|
+
sleep_time = choice_result[1]
|
86
|
+
result = f"钓到了一条{fish}, 你把它收进了背包里"
|
87
|
+
await save_fish(user_id, fish)
|
88
|
+
await asyncio.sleep(sleep_time)
|
89
|
+
achievements = await check_achievement(user_id)
|
90
|
+
if achievements is not None:
|
91
|
+
for achievement in achievements:
|
92
|
+
await fishing.send(achievement)
|
93
|
+
await fishing.finish(MessageSegment.at(user_id) + " " + result)
|
94
|
+
|
95
|
+
|
96
|
+
@backpack.handle()
|
97
|
+
async def _(event: Event):
|
98
|
+
user_id = event.get_user_id()
|
99
|
+
await backpack.finish(MessageSegment.at(user_id) + " \n" + await get_stats(user_id) + "\n" + await get_balance(user_id) + "\n" + await get_backpack(user_id))
|
100
|
+
|
101
|
+
|
102
|
+
@sell.handle()
|
103
|
+
async def _(event: Event, arg: Message = CommandArg()):
|
104
|
+
fish_info = arg.extract_plain_text()
|
105
|
+
user_id = event.get_user_id()
|
106
|
+
if fish_info == "":
|
107
|
+
await sell.finish(MessageSegment.at(user_id) + " " + "请输入要卖出的鱼的名字和数量 (数量为1时可省略), 如 /卖鱼 小鱼 1")
|
108
|
+
if len(fish_info.split()) == 1:
|
109
|
+
await sell.finish(MessageSegment.at(user_id) + " " + await sell_fish(user_id, fish_info))
|
110
|
+
else:
|
111
|
+
fish_name, fish_quantity = fish_info.split()
|
112
|
+
await sell.finish(MessageSegment.at(user_id) + " " + await sell_fish(user_id, fish_name, int(fish_quantity)))
|
113
|
+
|
114
|
+
|
115
|
+
@free_fish_cmd.handle()
|
116
|
+
async def _(event: Event, arg: Message = CommandArg()):
|
117
|
+
if not can_free_fish():
|
118
|
+
await free_fish_cmd.finish("未开启此功能, 请联系机器人管理员")
|
119
|
+
fish_name = arg.extract_plain_text()
|
120
|
+
user_id = event.get_user_id()
|
121
|
+
if fish_name == "":
|
122
|
+
await free_fish_cmd.finish(MessageSegment.at(user_id) + " " + "请输入要放生的鱼的名字, 如 /放生 测试鱼")
|
123
|
+
await free_fish_cmd.finish(MessageSegment.at(user_id) + " " + await free_fish(user_id, fish_name))
|
124
|
+
|
125
|
+
|
126
|
+
@lottery_cmd.handle()
|
127
|
+
async def _(event: Event):
|
128
|
+
user_id = event.get_user_id()
|
129
|
+
await lottery_cmd.finish(MessageSegment.at(user_id) + " " + await lottery(user_id))
|
130
|
+
|
131
|
+
|
132
|
+
@achievement_cmd.handle()
|
133
|
+
async def _(event: Event):
|
134
|
+
user_id = event.get_user_id()
|
135
|
+
await achievement_cmd.finish(MessageSegment.at(user_id) + " " + await get_achievements(user_id))
|
136
|
+
|
137
|
+
|
138
|
+
@give_cmd.handle()
|
139
|
+
async def _(arg: Message = CommandArg()):
|
140
|
+
info = arg.extract_plain_text().split()
|
141
|
+
if len(info) < 2 or len(info) > 3:
|
142
|
+
await give_cmd.finish("请输入用户的 id 和鱼的名字和数量 (数量为1时可省略), 如 /give 114514 开发鱼 1")
|
143
|
+
else:
|
144
|
+
quantity = int(info[2]) if len(info) == 3 else 1
|
145
|
+
await give_cmd.finish(await give(info[0], info[1], quantity))
|
146
|
+
|
147
|
+
|
148
|
+
@board_cmd.handle()
|
149
|
+
async def _(bot: Bot, event: GroupMessageEvent):
|
150
|
+
group_id = event.group_id
|
151
|
+
top_users_list = await get_board()
|
152
|
+
msg = '钓鱼富豪排行榜:'
|
153
|
+
for index, user in enumerate(top_users_list):
|
154
|
+
try:
|
155
|
+
user_info = await bot.get_group_member_info(group_id=group_id, user_id=user[0])
|
156
|
+
username = user_info['card'] if user_info['card'] is not None and user_info['card'] != '' else user_info['nickname']
|
157
|
+
except ActionFailed:
|
158
|
+
username = "[神秘富豪]"
|
159
|
+
|
160
|
+
msg += f'\n{index + 1}. {username}: {user[1]} {fishing_coin_name}'
|
161
|
+
|
162
|
+
await board_cmd.finish(msg)
|
163
|
+
|
164
|
+
|
165
|
+
|
@@ -0,0 +1,95 @@
|
|
1
|
+
from pydantic import BaseModel
|
2
|
+
from typing import List, Dict
|
3
|
+
|
4
|
+
try:
|
5
|
+
# pydantic v2
|
6
|
+
from nonebot import get_plugin_config
|
7
|
+
except ImportError:
|
8
|
+
# pydantic v1
|
9
|
+
from nonebot import get_driver
|
10
|
+
|
11
|
+
|
12
|
+
class Config(BaseModel):
|
13
|
+
fishes: List[Dict] = [
|
14
|
+
{
|
15
|
+
"name": "小鱼",
|
16
|
+
"frequency": 2,
|
17
|
+
"weight": 100,
|
18
|
+
"price": 10
|
19
|
+
},
|
20
|
+
{
|
21
|
+
"name": "尚方宝剑",
|
22
|
+
"frequency": 2,
|
23
|
+
"weight": 50,
|
24
|
+
"price": 20
|
25
|
+
},
|
26
|
+
{
|
27
|
+
"name": "小杂鱼~♡",
|
28
|
+
"frequency": 10,
|
29
|
+
"weight": 10,
|
30
|
+
"price": 100
|
31
|
+
},
|
32
|
+
{
|
33
|
+
"name": "烤激光鱼",
|
34
|
+
"frequency": 20,
|
35
|
+
"weight": 1,
|
36
|
+
"price": 1000
|
37
|
+
},
|
38
|
+
{
|
39
|
+
"name": "大傻",
|
40
|
+
"frequency": 30,
|
41
|
+
"weight": 1,
|
42
|
+
"price": 2000
|
43
|
+
}
|
44
|
+
]
|
45
|
+
|
46
|
+
fishing_limit: int = 30
|
47
|
+
|
48
|
+
fishing_coin_name: str = "绿宝石" # It means Fishing Coin.
|
49
|
+
|
50
|
+
special_fish_enabled: bool = True
|
51
|
+
|
52
|
+
special_fish_price: int = 200
|
53
|
+
|
54
|
+
special_fish_probability: float = 0.01
|
55
|
+
|
56
|
+
fishing_achievement: List[Dict] = [
|
57
|
+
{
|
58
|
+
"type": "fishing_frequency",
|
59
|
+
"name": "腥味十足的生意",
|
60
|
+
"data": 1,
|
61
|
+
"description": "钓到一条鱼。"
|
62
|
+
},
|
63
|
+
{
|
64
|
+
"type": "fishing_frequency",
|
65
|
+
"name": "还是钓鱼大佬",
|
66
|
+
"data": 100,
|
67
|
+
"description": "累计钓鱼一百次。"
|
68
|
+
},
|
69
|
+
{
|
70
|
+
"type": "fish_type",
|
71
|
+
"name": "那是鱼吗?",
|
72
|
+
"data": "小杂鱼~♡",
|
73
|
+
"description": "获得#####。[原文如此]"
|
74
|
+
},
|
75
|
+
{
|
76
|
+
"type": "fish_type",
|
77
|
+
"name": "那一晚, 激光鱼和便携式烤炉都喝醉了",
|
78
|
+
"data": "烤激光鱼",
|
79
|
+
"description": "获得烤激光鱼。"
|
80
|
+
},
|
81
|
+
{
|
82
|
+
"type": "fish_type",
|
83
|
+
"name": "你怎么把 Fufu 钓上来了",
|
84
|
+
"data": "大傻",
|
85
|
+
"description": "获得大傻"
|
86
|
+
}
|
87
|
+
]
|
88
|
+
|
89
|
+
|
90
|
+
try:
|
91
|
+
# pydantic v2
|
92
|
+
config = get_plugin_config(Config)
|
93
|
+
except:
|
94
|
+
# pydantic v1
|
95
|
+
config = Config.parse_obj(get_driver().config)
|
@@ -0,0 +1,463 @@
|
|
1
|
+
import random
|
2
|
+
import time
|
3
|
+
import json
|
4
|
+
|
5
|
+
from sqlalchemy import select, update, delete
|
6
|
+
from sqlalchemy.sql.expression import func
|
7
|
+
from nonebot_plugin_orm import get_session
|
8
|
+
|
9
|
+
from .config import config
|
10
|
+
from .model import FishingRecord, SpecialFishes
|
11
|
+
|
12
|
+
fishing_coin_name = config.fishing_coin_name
|
13
|
+
fish_list = [fish["name"] for fish in config.fishes]
|
14
|
+
|
15
|
+
def choice() -> tuple:
|
16
|
+
config_fishes = config.fishes
|
17
|
+
weights = [weight["weight"] for weight in config_fishes]
|
18
|
+
choices = random.choices(
|
19
|
+
config_fishes,
|
20
|
+
weights=weights,
|
21
|
+
)
|
22
|
+
return choices[0]["name"], choices[0]["frequency"]
|
23
|
+
|
24
|
+
|
25
|
+
def get_price(fish_name: str) -> int:
|
26
|
+
"""获取鱼的价格"""
|
27
|
+
config_fishes = config.fishes
|
28
|
+
return next(
|
29
|
+
(
|
30
|
+
fish["price"]
|
31
|
+
for fish in config_fishes
|
32
|
+
if fish["name"] == fish_name
|
33
|
+
),
|
34
|
+
0
|
35
|
+
)
|
36
|
+
|
37
|
+
|
38
|
+
async def random_get_a_special_fish() -> str:
|
39
|
+
"""随机返回一条别人放生的鱼"""
|
40
|
+
session = get_session()
|
41
|
+
async with session.begin():
|
42
|
+
random_select = select(SpecialFishes).order_by(func.random())
|
43
|
+
data = await session.scalar(random_select)
|
44
|
+
return data.fish
|
45
|
+
|
46
|
+
|
47
|
+
async def can_fishing(user_id: str) -> bool:
|
48
|
+
"""判断是否可以钓鱼"""
|
49
|
+
time_now = int(time.time())
|
50
|
+
session = get_session()
|
51
|
+
async with session.begin():
|
52
|
+
select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
|
53
|
+
record = await session.scalar(select_user)
|
54
|
+
return True if not record else record.time < time_now
|
55
|
+
|
56
|
+
|
57
|
+
def can_free_fish() -> bool:
|
58
|
+
return config.special_fish_enabled
|
59
|
+
|
60
|
+
|
61
|
+
async def check_achievement(user_id: str) -> str | None:
|
62
|
+
session = get_session()
|
63
|
+
async with session.begin():
|
64
|
+
record = await session.scalar(select(FishingRecord).where(FishingRecord.user_id == user_id))
|
65
|
+
if not record:
|
66
|
+
return None
|
67
|
+
fishing_frequency = record.frequency
|
68
|
+
user_fishes = json.loads(record.fishes)
|
69
|
+
achievements = config.fishing_achievement
|
70
|
+
result_list = []
|
71
|
+
for achievement in achievements:
|
72
|
+
achievement_name = achievement["name"]
|
73
|
+
if await is_exists_achievement(user_id, achievement_name):
|
74
|
+
continue
|
75
|
+
if (achievement["type"] == "fishing_frequency" and achievement["data"] <= fishing_frequency) or \
|
76
|
+
(achievement["type"] == "fish_type" and achievement["data"] in user_fishes):
|
77
|
+
await save_achievement(user_id, achievement_name)
|
78
|
+
result_list.append(f"""达成成就: {achievement_name}\n{achievement["description"]}""")
|
79
|
+
return result_list if result_list != [] else None
|
80
|
+
|
81
|
+
|
82
|
+
async def is_exists_achievement(user_id: str, achievement_name: str) -> bool:
|
83
|
+
session = get_session()
|
84
|
+
async with session.begin():
|
85
|
+
select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
|
86
|
+
record = await session.scalar(select_user)
|
87
|
+
if record:
|
88
|
+
loads_achievements = json.loads(record.achievements)
|
89
|
+
return achievement_name in loads_achievements
|
90
|
+
return False
|
91
|
+
|
92
|
+
|
93
|
+
async def save_achievement(user_id: str, achievement_name: str):
|
94
|
+
time_now = int(time.time())
|
95
|
+
session = get_session()
|
96
|
+
async with session.begin():
|
97
|
+
select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
|
98
|
+
record = await session.scalar(select_user)
|
99
|
+
if record:
|
100
|
+
loads_achievements = json.loads(record.achievements)
|
101
|
+
loads_achievements.append(achievement_name)
|
102
|
+
dump_achievements = json.dumps(loads_achievements)
|
103
|
+
user_update = update(FishingRecord).where(
|
104
|
+
FishingRecord.user_id == user_id
|
105
|
+
).values(
|
106
|
+
achievements=dump_achievements
|
107
|
+
)
|
108
|
+
await session.execute(user_update)
|
109
|
+
await session.commit()
|
110
|
+
return
|
111
|
+
data = []
|
112
|
+
dump_achievements = json.dumps(data)
|
113
|
+
new_record = FishingRecord(
|
114
|
+
user_id=user_id,
|
115
|
+
time=time_now,
|
116
|
+
frequency=0,
|
117
|
+
fishes="{}",
|
118
|
+
special_fishes="{}",
|
119
|
+
coin=0,
|
120
|
+
achievements=dump_achievements
|
121
|
+
)
|
122
|
+
session.add(new_record)
|
123
|
+
await session.commit()
|
124
|
+
|
125
|
+
|
126
|
+
async def save_fish(user_id: str, fish_name: str) -> None:
|
127
|
+
"""向数据库写入鱼以持久化保存"""
|
128
|
+
time_now = int(time.time())
|
129
|
+
fishing_limit = config.fishing_limit
|
130
|
+
session = get_session()
|
131
|
+
async with session.begin():
|
132
|
+
select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
|
133
|
+
record = await session.scalar(select_user)
|
134
|
+
if record:
|
135
|
+
loads_fishes = json.loads(record.fishes)
|
136
|
+
try:
|
137
|
+
loads_fishes[fish_name] += 1
|
138
|
+
except KeyError:
|
139
|
+
loads_fishes[fish_name] = 1
|
140
|
+
dump_fishes = json.dumps(loads_fishes)
|
141
|
+
new_frequency = record.frequency + 1
|
142
|
+
user_update = update(FishingRecord).where(
|
143
|
+
FishingRecord.user_id == user_id
|
144
|
+
).values(
|
145
|
+
time=time_now + fishing_limit,
|
146
|
+
frequency=new_frequency,
|
147
|
+
fishes=dump_fishes
|
148
|
+
)
|
149
|
+
await session.execute(user_update)
|
150
|
+
await session.commit()
|
151
|
+
return
|
152
|
+
data = {
|
153
|
+
fish_name: 1
|
154
|
+
}
|
155
|
+
dump_fishes = json.dumps(data)
|
156
|
+
new_record = FishingRecord(
|
157
|
+
user_id=user_id,
|
158
|
+
time=time_now + fishing_limit,
|
159
|
+
frequency=1,
|
160
|
+
fishes=dump_fishes,
|
161
|
+
special_fishes="{}",
|
162
|
+
coin=0,
|
163
|
+
achievements="[]"
|
164
|
+
)
|
165
|
+
session.add(new_record)
|
166
|
+
await session.commit()
|
167
|
+
|
168
|
+
|
169
|
+
async def can_catch_special_fish():
|
170
|
+
session = get_session()
|
171
|
+
async with session.begin():
|
172
|
+
records = await session.execute(select(SpecialFishes))
|
173
|
+
return len(records.all()) != 0 and random.random() <= config.special_fish_probability
|
174
|
+
|
175
|
+
|
176
|
+
async def save_special_fish(user_id: str, fish_name: str) -> None:
|
177
|
+
time_now = int(time.time())
|
178
|
+
fishing_limit = config.fishing_limit
|
179
|
+
session = get_session()
|
180
|
+
async with session.begin():
|
181
|
+
select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
|
182
|
+
record = await session.scalar(select_user)
|
183
|
+
if record:
|
184
|
+
loads_fishes = json.loads(record.special_fishes)
|
185
|
+
try:
|
186
|
+
loads_fishes[fish_name] += 1
|
187
|
+
except KeyError:
|
188
|
+
loads_fishes[fish_name] = 1
|
189
|
+
dump_fishes = json.dumps(loads_fishes)
|
190
|
+
user_update = update(FishingRecord).where(
|
191
|
+
FishingRecord.user_id == user_id
|
192
|
+
).values(
|
193
|
+
time=time_now + fishing_limit,
|
194
|
+
frequency=record.frequency + 1,
|
195
|
+
special_fishes=dump_fishes
|
196
|
+
)
|
197
|
+
await session.execute(user_update)
|
198
|
+
else:
|
199
|
+
data = {
|
200
|
+
fish_name: 1
|
201
|
+
}
|
202
|
+
dump_fishes = json.dumps(data)
|
203
|
+
new_record = FishingRecord(
|
204
|
+
user_id=user_id,
|
205
|
+
time=time_now + fishing_limit,
|
206
|
+
frequency=1,
|
207
|
+
fishes="{}",
|
208
|
+
special_fishes=dump_fishes,
|
209
|
+
coin=0,
|
210
|
+
achievements=[]
|
211
|
+
)
|
212
|
+
session.add(new_record)
|
213
|
+
select_fish = select(SpecialFishes).where(
|
214
|
+
SpecialFishes.fish == fish_name
|
215
|
+
).order_by(SpecialFishes.id).limit(1)
|
216
|
+
record = await session.scalar(select_fish)
|
217
|
+
fish_id = record.id
|
218
|
+
delete_fishes = delete(SpecialFishes).where(SpecialFishes.id == fish_id)
|
219
|
+
await session.execute(delete_fishes)
|
220
|
+
await session.commit()
|
221
|
+
|
222
|
+
|
223
|
+
async def get_stats(user_id: str) -> str:
|
224
|
+
"""获取钓鱼统计信息"""
|
225
|
+
session = get_session()
|
226
|
+
async with session.begin():
|
227
|
+
select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
|
228
|
+
fishing_record = await session.scalar(select_user)
|
229
|
+
if fishing_record:
|
230
|
+
return f"🐟你钓鱼了 {fishing_record.frequency} 次"
|
231
|
+
return "🐟你还没有钓过鱼,快去钓鱼吧"
|
232
|
+
|
233
|
+
|
234
|
+
def print_backpack(backpack: dict, special_backpack=None) -> str:
|
235
|
+
"""输出背包内容"""
|
236
|
+
result = [
|
237
|
+
f"{fish_name}×{str(quantity)}"
|
238
|
+
for fish_name, quantity in backpack.items()
|
239
|
+
]
|
240
|
+
if special_backpack:
|
241
|
+
special_result = [
|
242
|
+
f"{fish_name}×{str(quantity)}"
|
243
|
+
for fish_name, quantity in special_backpack.items()
|
244
|
+
]
|
245
|
+
return "🎒背包:\n" + "\n".join(result) + "\n\n特殊鱼:\n" + "\n".join(special_result)
|
246
|
+
return "🎒背包:\n" + "\n".join(result)
|
247
|
+
|
248
|
+
|
249
|
+
async def get_backpack(user_id: str) -> str:
|
250
|
+
"""从数据库查询背包内容"""
|
251
|
+
session = get_session()
|
252
|
+
async with session.begin():
|
253
|
+
select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
|
254
|
+
fishes_record = await session.scalar(select_user)
|
255
|
+
if fishes_record:
|
256
|
+
load_fishes = json.loads(fishes_record.fishes)
|
257
|
+
load_special_fishes = json.loads(fishes_record.special_fishes)
|
258
|
+
if load_special_fishes:
|
259
|
+
return print_backpack(load_fishes, load_special_fishes)
|
260
|
+
return "🎒你的背包里空无一物" if load_fishes == {} else print_backpack(load_fishes)
|
261
|
+
return "🎒你的背包里空无一物"
|
262
|
+
|
263
|
+
|
264
|
+
async def sell_fish(user_id: str, fish_name: str, quantity: int = 1) -> str:
|
265
|
+
"""
|
266
|
+
卖鱼
|
267
|
+
|
268
|
+
参数:
|
269
|
+
- user_id: 用户标识符
|
270
|
+
- fish_name: 将要卖鱼的鱼名称
|
271
|
+
- quantity: 卖出鱼的数量
|
272
|
+
|
273
|
+
返回:
|
274
|
+
- (str): 回复的文本
|
275
|
+
"""
|
276
|
+
if quantity <= 0:
|
277
|
+
return "你在卖什么 w(゚Д゚)w"
|
278
|
+
session = get_session()
|
279
|
+
async with session.begin():
|
280
|
+
select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
|
281
|
+
fishes_record = await session.scalar(select_user)
|
282
|
+
if fishes_record := fishes_record:
|
283
|
+
loads_fishes = json.loads(fishes_record.fishes)
|
284
|
+
spec_fishes = json.loads(fishes_record.special_fishes)
|
285
|
+
if fish_name in loads_fishes and loads_fishes[fish_name] > 0:
|
286
|
+
fish_price = get_price(fish_name)
|
287
|
+
if loads_fishes[fish_name] < quantity:
|
288
|
+
return f"{fish_name} 太少了!"
|
289
|
+
loads_fishes[fish_name] -= quantity
|
290
|
+
if loads_fishes[fish_name] == 0:
|
291
|
+
del loads_fishes[fish_name]
|
292
|
+
dump_fishes = json.dumps(loads_fishes)
|
293
|
+
user_update = update(FishingRecord).where(
|
294
|
+
FishingRecord.user_id == user_id
|
295
|
+
).values(
|
296
|
+
coin=fishes_record.coin + fish_price * quantity,
|
297
|
+
fishes=dump_fishes
|
298
|
+
)
|
299
|
+
await session.execute(user_update)
|
300
|
+
await session.commit()
|
301
|
+
return (f"你以 {fish_price} {fishing_coin_name} / 条的价格卖出了 {quantity} 条 {fish_name}, "
|
302
|
+
f"你获得了 {fish_price * quantity} {fishing_coin_name}")
|
303
|
+
elif fish_name in spec_fishes and spec_fishes[fish_name] > 0:
|
304
|
+
fish_price = config.special_fish_price
|
305
|
+
if spec_fishes[fish_name] < quantity:
|
306
|
+
return f"{fish_name} 太少了!"
|
307
|
+
spec_fishes[fish_name] -= quantity
|
308
|
+
if spec_fishes[fish_name] == 0:
|
309
|
+
del spec_fishes[fish_name]
|
310
|
+
dump_fishes = json.dumps(spec_fishes)
|
311
|
+
user_update = update(FishingRecord).where(
|
312
|
+
FishingRecord.user_id == user_id
|
313
|
+
).values(
|
314
|
+
coin=fishes_record.coin + fish_price * quantity,
|
315
|
+
special_fishes=dump_fishes
|
316
|
+
)
|
317
|
+
await session.execute(user_update)
|
318
|
+
await session.commit()
|
319
|
+
return (f"你以 {fish_price} {fishing_coin_name} / 条的价格卖出了 {quantity} 条 {fish_name}, "
|
320
|
+
f"你获得了 {fish_price * quantity} {fishing_coin_name}")
|
321
|
+
else:
|
322
|
+
return "查无此鱼"
|
323
|
+
else:
|
324
|
+
return "还没钓鱼就想卖鱼?"
|
325
|
+
|
326
|
+
|
327
|
+
async def get_balance(user_id: str) -> str:
|
328
|
+
"""获取余额"""
|
329
|
+
session = get_session()
|
330
|
+
async with session.begin():
|
331
|
+
select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
|
332
|
+
fishes_record = await session.scalar(select_user)
|
333
|
+
if fishes_record:
|
334
|
+
return f"🪙你有 {fishes_record.coin} {fishing_coin_name}"
|
335
|
+
return "🪙你什么也没有 :)"
|
336
|
+
|
337
|
+
|
338
|
+
async def free_fish(user_id: str, fish_name: str) -> str:
|
339
|
+
session = get_session()
|
340
|
+
async with session.begin():
|
341
|
+
select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
|
342
|
+
fishes_record = await session.scalar(select_user)
|
343
|
+
if fishes_record:
|
344
|
+
user_coin = fishes_record.coin
|
345
|
+
spec_fishes = fishes_record.special_fishes
|
346
|
+
if fish_name in spec_fishes and spec_fishes[fish_name] > 0:
|
347
|
+
spec_fishes[fish_name] -= 1
|
348
|
+
if spec_fishes[fish_name] == 0:
|
349
|
+
del spec_fishes[fish_name]
|
350
|
+
dump_fishes = json.dumps(spec_fishes)
|
351
|
+
user_update = update(FishingRecord).where(
|
352
|
+
FishingRecord.user_id == user_id
|
353
|
+
).values(
|
354
|
+
special_fishes=dump_fishes
|
355
|
+
)
|
356
|
+
await session.execute(user_update)
|
357
|
+
await session.commit()
|
358
|
+
return f"你再次放生了 {fish_name}, 未来或许会被有缘人钓到呢"
|
359
|
+
else:
|
360
|
+
if user_coin < config.special_fish_price // 2:
|
361
|
+
special_fish_coin_less = str(config.special_fish_price // 2 - fishes_record.coin)
|
362
|
+
return f"你没有足够的 {fishing_coin_name}, 还需 {special_fish_coin_less} {fishing_coin_name}"
|
363
|
+
user_coin -= config.special_fish_price // 2
|
364
|
+
new_record = SpecialFishes(
|
365
|
+
user_id=user_id,
|
366
|
+
fish=fish_name
|
367
|
+
)
|
368
|
+
session.add(new_record)
|
369
|
+
user_update = update(FishingRecord).where(
|
370
|
+
FishingRecord.user_id == user_id
|
371
|
+
).values(
|
372
|
+
coin=user_coin
|
373
|
+
)
|
374
|
+
await session.execute(user_update)
|
375
|
+
await session.commit()
|
376
|
+
return f"你花费 {config.special_fish_price // 2} {fishing_coin_name} 放生了 {fish_name}, 未来或许会被有缘人钓到呢"
|
377
|
+
return "你甚至还没钓过鱼"
|
378
|
+
|
379
|
+
|
380
|
+
async def lottery(user_id: str) -> str:
|
381
|
+
"""算法来自于 https://github.com/fossifer/minesweeperbot/blob/master/cards.py"""
|
382
|
+
session = get_session()
|
383
|
+
async with session.begin():
|
384
|
+
select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
|
385
|
+
fishes_record = await session.scalar(select_user)
|
386
|
+
if fishes_record:
|
387
|
+
user_coin = fishes_record.coin
|
388
|
+
if user_coin <= 0:
|
389
|
+
return f"你只有 {user_coin} {fishing_coin_name}, 不足以祈愿"
|
390
|
+
new_coin = abs(user_coin) / 3
|
391
|
+
new_coin = random.randrange(5000, 15000) / 10000 * new_coin
|
392
|
+
new_coin = int(new_coin) if new_coin > 1 else 1
|
393
|
+
new_coin *= random.randrange(-1, 2, 2)
|
394
|
+
user_update = update(FishingRecord).where(
|
395
|
+
FishingRecord.user_id == user_id
|
396
|
+
).values(
|
397
|
+
coin=fishes_record.coin + new_coin,
|
398
|
+
)
|
399
|
+
await session.execute(user_update)
|
400
|
+
await session.commit()
|
401
|
+
return f'你{"获得" if new_coin >= 0 else "血亏"}了 {abs(new_coin)} {fishing_coin_name}'
|
402
|
+
|
403
|
+
|
404
|
+
async def give(user_id: str, fish_name: str, quantity: int = 1) -> str:
|
405
|
+
session = get_session()
|
406
|
+
async with session.begin():
|
407
|
+
select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
|
408
|
+
record = await session.scalar(select_user)
|
409
|
+
if record:
|
410
|
+
loads_fishes = json.loads(record.fishes)
|
411
|
+
spec_fishes = json.loads(record.special_fishes)
|
412
|
+
if fish_name in fish_list:
|
413
|
+
try:
|
414
|
+
loads_fishes[fish_name] += quantity
|
415
|
+
except KeyError:
|
416
|
+
loads_fishes[fish_name] = quantity
|
417
|
+
dump_fishes = json.dumps(loads_fishes)
|
418
|
+
user_update = update(FishingRecord).where(
|
419
|
+
FishingRecord.user_id == user_id
|
420
|
+
).values(
|
421
|
+
fishes=dump_fishes
|
422
|
+
)
|
423
|
+
await session.execute(user_update)
|
424
|
+
await session.commit()
|
425
|
+
else:
|
426
|
+
try:
|
427
|
+
spec_fishes[fish_name] += quantity
|
428
|
+
except KeyError:
|
429
|
+
spec_fishes[fish_name] = quantity
|
430
|
+
dump_fishes = json.dumps(spec_fishes)
|
431
|
+
user_update = update(FishingRecord).where(
|
432
|
+
FishingRecord.user_id == user_id
|
433
|
+
).values(
|
434
|
+
special_fishes=dump_fishes
|
435
|
+
)
|
436
|
+
await session.execute(user_update)
|
437
|
+
await session.commit()
|
438
|
+
return f"使用滥权之力成功使 {fish_name} 添加到 {user_id} 的背包之中 ヾ(≧▽≦*)o"
|
439
|
+
return "未查找到用户信息, 无法执行滥权操作 w(゚Д゚)w"
|
440
|
+
|
441
|
+
|
442
|
+
async def get_achievements(user_id: str) -> str:
|
443
|
+
session = get_session()
|
444
|
+
async with session.begin():
|
445
|
+
select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
|
446
|
+
record = await session.scalar(select_user)
|
447
|
+
if record:
|
448
|
+
achievements = json.loads(record.achievements)
|
449
|
+
return "已完成成就:\n" + "\n".join(achievements)
|
450
|
+
return "你甚至还没钓过鱼 (╬▔皿▔)╯"
|
451
|
+
|
452
|
+
async def get_board() -> list:
|
453
|
+
session = get_session()
|
454
|
+
async with session.begin():
|
455
|
+
select_users = select(FishingRecord).order_by(FishingRecord.coin.desc()).limit(10)
|
456
|
+
record = await session.scalars(select_users)
|
457
|
+
if record:
|
458
|
+
top_users_list = []
|
459
|
+
for user in record:
|
460
|
+
top_users_list.append((user.user_id, user.coin))
|
461
|
+
top_users_list.sort(key=lambda user: user[1], reverse=True)
|
462
|
+
return top_users_list
|
463
|
+
return []
|
@@ -0,0 +1,39 @@
|
|
1
|
+
"""add achievements
|
2
|
+
|
3
|
+
迁移 ID: 1be1c9b715a9
|
4
|
+
父迁移: e9015df43907
|
5
|
+
创建时间: 2024-09-22 17:12:51.193361
|
6
|
+
|
7
|
+
"""
|
8
|
+
from __future__ import annotations
|
9
|
+
|
10
|
+
from collections.abc import Sequence
|
11
|
+
|
12
|
+
from alembic import op
|
13
|
+
import sqlalchemy as sa
|
14
|
+
|
15
|
+
|
16
|
+
revision: str = '1be1c9b715a9'
|
17
|
+
down_revision: str | Sequence[str] | None = 'e9015df43907'
|
18
|
+
branch_labels: str | Sequence[str] | None = None
|
19
|
+
depends_on: str | Sequence[str] | None = None
|
20
|
+
|
21
|
+
|
22
|
+
def upgrade(name: str = "") -> None:
|
23
|
+
if name:
|
24
|
+
return
|
25
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
26
|
+
with op.batch_alter_table('nonebot_plugin_fishing_fishingrecord', schema=None) as batch_op:
|
27
|
+
batch_op.add_column(sa.Column('achievements', sa.TEXT(), nullable=False))
|
28
|
+
|
29
|
+
# ### end Alembic commands ###
|
30
|
+
|
31
|
+
|
32
|
+
def downgrade(name: str = "") -> None:
|
33
|
+
if name:
|
34
|
+
return
|
35
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
36
|
+
with op.batch_alter_table('nonebot_plugin_fishing_fishingrecord', schema=None) as batch_op:
|
37
|
+
batch_op.drop_column('achievements')
|
38
|
+
|
39
|
+
# ### end Alembic commands ###
|
@@ -0,0 +1,44 @@
|
|
1
|
+
"""init db
|
2
|
+
|
3
|
+
迁移 ID: 7609e6d106dd
|
4
|
+
父迁移:
|
5
|
+
创建时间: 2024-04-05 19:08:58.835014
|
6
|
+
|
7
|
+
"""
|
8
|
+
from __future__ import annotations
|
9
|
+
|
10
|
+
from collections.abc import Sequence
|
11
|
+
|
12
|
+
from alembic import op
|
13
|
+
import sqlalchemy as sa
|
14
|
+
|
15
|
+
|
16
|
+
revision: str = '7609e6d106dd'
|
17
|
+
down_revision: str | Sequence[str] | None = None
|
18
|
+
branch_labels: str | Sequence[str] | None = ('nonebot_plugin_fishing',)
|
19
|
+
depends_on: str | Sequence[str] | None = None
|
20
|
+
|
21
|
+
|
22
|
+
def upgrade(name: str = "") -> None:
|
23
|
+
if name:
|
24
|
+
return
|
25
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
26
|
+
op.create_table('nonebot_plugin_fishing_fishingrecord',
|
27
|
+
sa.Column('id', sa.Integer(), nullable=False),
|
28
|
+
sa.Column('user_id', sa.String(length=32), nullable=False),
|
29
|
+
sa.Column('time', sa.Integer(), nullable=False),
|
30
|
+
sa.Column('frequency', sa.Integer(), nullable=False),
|
31
|
+
sa.Column('fishes', sa.TEXT(), nullable=False),
|
32
|
+
sa.Column('coin', sa.Integer(), nullable=False),
|
33
|
+
sa.PrimaryKeyConstraint('id', name=op.f('pk_nonebot_plugin_fishing_fishingrecord')),
|
34
|
+
info={'bind_key': 'nonebot_plugin_fishing'}
|
35
|
+
)
|
36
|
+
# ### end Alembic commands ###
|
37
|
+
|
38
|
+
|
39
|
+
def downgrade(name: str = "") -> None:
|
40
|
+
if name:
|
41
|
+
return
|
42
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
43
|
+
op.drop_table('nonebot_plugin_fishing_fishingrecord')
|
44
|
+
# ### end Alembic commands ###
|
@@ -0,0 +1,39 @@
|
|
1
|
+
"""add achievements
|
2
|
+
|
3
|
+
迁移 ID: c5ab992c9af3
|
4
|
+
父迁移: e9015df43907
|
5
|
+
创建时间: 2024-09-22 16:44:24.934270
|
6
|
+
|
7
|
+
"""
|
8
|
+
from __future__ import annotations
|
9
|
+
|
10
|
+
from collections.abc import Sequence
|
11
|
+
|
12
|
+
from alembic import op
|
13
|
+
import sqlalchemy as sa
|
14
|
+
|
15
|
+
|
16
|
+
revision: str = 'c5ab992c9af3'
|
17
|
+
down_revision: str | Sequence[str] | None = 'e9015df43907'
|
18
|
+
branch_labels: str | Sequence[str] | None = None
|
19
|
+
depends_on: str | Sequence[str] | None = None
|
20
|
+
|
21
|
+
|
22
|
+
def upgrade(name: str = "") -> None:
|
23
|
+
if name:
|
24
|
+
return
|
25
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
26
|
+
with op.batch_alter_table('nonebot_plugin_fishing_fishingrecord', schema=None) as batch_op:
|
27
|
+
batch_op.add_column(sa.Column('achievements', sa.TEXT(), nullable=False))
|
28
|
+
|
29
|
+
# ### end Alembic commands ###
|
30
|
+
|
31
|
+
|
32
|
+
def downgrade(name: str = "") -> None:
|
33
|
+
if name:
|
34
|
+
return
|
35
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
36
|
+
with op.batch_alter_table('nonebot_plugin_fishing_fishingrecord', schema=None) as batch_op:
|
37
|
+
batch_op.drop_column('achievements')
|
38
|
+
|
39
|
+
# ### end Alembic commands ###
|
@@ -0,0 +1,39 @@
|
|
1
|
+
"""add special_fishes field
|
2
|
+
|
3
|
+
迁移 ID: e9015df43907
|
4
|
+
父迁移: f70bdeaec7a4
|
5
|
+
创建时间: 2024-04-20 12:43:35.168261
|
6
|
+
|
7
|
+
"""
|
8
|
+
from __future__ import annotations
|
9
|
+
|
10
|
+
from collections.abc import Sequence
|
11
|
+
|
12
|
+
from alembic import op
|
13
|
+
import sqlalchemy as sa
|
14
|
+
|
15
|
+
|
16
|
+
revision: str = 'e9015df43907'
|
17
|
+
down_revision: str | Sequence[str] | None = 'f70bdeaec7a4'
|
18
|
+
branch_labels: str | Sequence[str] | None = None
|
19
|
+
depends_on: str | Sequence[str] | None = None
|
20
|
+
|
21
|
+
|
22
|
+
def upgrade(name: str = "") -> None:
|
23
|
+
if name:
|
24
|
+
return
|
25
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
26
|
+
with op.batch_alter_table('nonebot_plugin_fishing_fishingrecord', schema=None) as batch_op:
|
27
|
+
batch_op.add_column(sa.Column('special_fishes', sa.TEXT(), nullable=False))
|
28
|
+
|
29
|
+
# ### end Alembic commands ###
|
30
|
+
|
31
|
+
|
32
|
+
def downgrade(name: str = "") -> None:
|
33
|
+
if name:
|
34
|
+
return
|
35
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
36
|
+
with op.batch_alter_table('nonebot_plugin_fishing_fishingrecord', schema=None) as batch_op:
|
37
|
+
batch_op.drop_column('special_fishes')
|
38
|
+
|
39
|
+
# ### end Alembic commands ###
|
@@ -0,0 +1,41 @@
|
|
1
|
+
"""add SpecialFishes table
|
2
|
+
|
3
|
+
迁移 ID: f70bdeaec7a4
|
4
|
+
父迁移: 68463f3e5f33
|
5
|
+
创建时间: 2024-04-11 12:59:25.138990
|
6
|
+
|
7
|
+
"""
|
8
|
+
from __future__ import annotations
|
9
|
+
|
10
|
+
from collections.abc import Sequence
|
11
|
+
|
12
|
+
from alembic import op
|
13
|
+
import sqlalchemy as sa
|
14
|
+
|
15
|
+
|
16
|
+
revision: str = 'f70bdeaec7a4'
|
17
|
+
down_revision: str | Sequence[str] | None = '68463f3e5f33'
|
18
|
+
branch_labels: str | Sequence[str] | None = None
|
19
|
+
depends_on: str | Sequence[str] | None = None
|
20
|
+
|
21
|
+
|
22
|
+
def upgrade(name: str = "") -> None:
|
23
|
+
if name:
|
24
|
+
return
|
25
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
26
|
+
op.create_table('nonebot_plugin_fishing_specialfishes',
|
27
|
+
sa.Column('id', sa.Integer(), nullable=False),
|
28
|
+
sa.Column('user_id', sa.String(length=32), nullable=False),
|
29
|
+
sa.Column('fish', sa.TEXT(), nullable=False),
|
30
|
+
sa.PrimaryKeyConstraint('id', name=op.f('pk_nonebot_plugin_fishing_specialfishes')),
|
31
|
+
info={'bind_key': 'nonebot_plugin_fishing'}
|
32
|
+
)
|
33
|
+
# ### end Alembic commands ###
|
34
|
+
|
35
|
+
|
36
|
+
def downgrade(name: str = "") -> None:
|
37
|
+
if name:
|
38
|
+
return
|
39
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
40
|
+
op.drop_table('nonebot_plugin_fishing_specialfishes')
|
41
|
+
# ### end Alembic commands ###
|
@@ -0,0 +1,20 @@
|
|
1
|
+
from nonebot_plugin_orm import Model
|
2
|
+
from sqlalchemy import String, TEXT
|
3
|
+
from sqlalchemy.orm import Mapped, mapped_column
|
4
|
+
|
5
|
+
|
6
|
+
class FishingRecord(Model):
|
7
|
+
id: Mapped[int] = mapped_column(primary_key=True)
|
8
|
+
user_id: Mapped[str] = mapped_column(String(32))
|
9
|
+
time: Mapped[int]
|
10
|
+
frequency: Mapped[int]
|
11
|
+
fishes: Mapped[str] = mapped_column(TEXT)
|
12
|
+
special_fishes: Mapped[str] = mapped_column(TEXT, default="{}")
|
13
|
+
coin: Mapped[int] = mapped_column(default=0)
|
14
|
+
achievements: Mapped[str] = mapped_column(TEXT, default="[]")
|
15
|
+
|
16
|
+
|
17
|
+
class SpecialFishes(Model):
|
18
|
+
id: Mapped[int] = mapped_column(primary_key=True)
|
19
|
+
user_id: Mapped[str] = mapped_column(String(32))
|
20
|
+
fish: Mapped[str] = mapped_column(TEXT, default="{}")
|
@@ -0,0 +1,144 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: nonebot-plugin-fishing2
|
3
|
+
Version: 0.0.1
|
4
|
+
Summary: 更好的电子钓鱼
|
5
|
+
Author-email: ALittleBot <160833462+C14H22O@users.noreply.github.com>, Polaris_Light <995905922@qq.com>
|
6
|
+
License-Expression: MIT
|
7
|
+
Project-URL: Homepage, https://github.com/FDCraft/nonebot-plugin-fishing2
|
8
|
+
Keywords: fishing
|
9
|
+
Requires-Python: >=3.8
|
10
|
+
Description-Content-Type: text/markdown
|
11
|
+
License-File: LICENSE
|
12
|
+
Requires-Dist: nonebot2>=2.2.1
|
13
|
+
Requires-Dist: nonebot-adapter-onebot>=2.0.0-beta.1
|
14
|
+
Requires-Dist: pydantic>=1.10
|
15
|
+
Requires-Dist: nonebot-plugin-localstore>=0.6.0
|
16
|
+
Requires-Dist: sqlalchemy>=2.0.27
|
17
|
+
Requires-Dist: aiosqlite>=0.20.0
|
18
|
+
Requires-Dist: nonebot-plugin-orm>=0.7.1
|
19
|
+
Dynamic: license-file
|
20
|
+
|
21
|
+
<div align="center">
|
22
|
+
<a href="https://v2.nonebot.dev/store"><img src="https://github.com/A-kirami/nonebot-plugin-template/blob/resources/nbp_logo.png" width="180" height="180" alt="NoneBotPluginLogo"></a>
|
23
|
+
<br>
|
24
|
+
<p><img src="https://github.com/A-kirami/nonebot-plugin-template/blob/resources/NoneBotPlugin.svg" width="240" alt="NoneBotPluginText"></p>
|
25
|
+
</div>
|
26
|
+
|
27
|
+
<div align="center">
|
28
|
+
|
29
|
+
# nonebot-plugin-fishing2
|
30
|
+
|
31
|
+
_✨ 更好的电子钓鱼 ✨_
|
32
|
+
|
33
|
+
<a href="./LICENSE">
|
34
|
+
<img src="https://img.shields.io/github/license/FDCraft/nonebot-plugin-fishing2.svg" alt="license">
|
35
|
+
</a>
|
36
|
+
<a href="https://pypi.python.org/pypi/nonebot-plugin-fishing2">
|
37
|
+
<img src="https://img.shields.io/pypi/v/nonebot-plugin-fishing2.svg" alt="pypi">
|
38
|
+
</a>
|
39
|
+
<img src="https://img.shields.io/badge/python-3.8+-blue.svg" alt="python">
|
40
|
+
|
41
|
+
</div>
|
42
|
+
|
43
|
+
## 💿 安装
|
44
|
+
|
45
|
+
<details open>
|
46
|
+
<summary>使用 nb-cli 安装</summary>
|
47
|
+
在 nonebot2 项目的根目录下打开命令行, 输入以下指令即可安装
|
48
|
+
|
49
|
+
nb plugin install nonebot-plugin-fishing2
|
50
|
+
|
51
|
+
</details>
|
52
|
+
|
53
|
+
<details>
|
54
|
+
<summary>使用包管理器安装</summary>
|
55
|
+
在 nonebot2 项目的插件目录下, 打开命令行, 根据你使用的包管理器, 输入相应的安装命令
|
56
|
+
|
57
|
+
<details>
|
58
|
+
<summary>pip</summary>
|
59
|
+
|
60
|
+
pip install nonebot-plugin-fishing2
|
61
|
+
</details>
|
62
|
+
<details>
|
63
|
+
<summary>pdm</summary>
|
64
|
+
|
65
|
+
pdm add nonebot-plugin-fishing2
|
66
|
+
</details>
|
67
|
+
<details>
|
68
|
+
<summary>poetry</summary>
|
69
|
+
|
70
|
+
poetry add nonebot-plugin-fishing2
|
71
|
+
</details>
|
72
|
+
<details>
|
73
|
+
<summary>conda</summary>
|
74
|
+
|
75
|
+
conda install nonebot-plugin-fishing2
|
76
|
+
</details>
|
77
|
+
|
78
|
+
打开 nonebot2 项目根目录下的 `pyproject.toml` 文件, 在 `[tool.nonebot]` 部分追加写入
|
79
|
+
|
80
|
+
plugins = ["nonebot_plugin_fishing2"]
|
81
|
+
|
82
|
+
</details>
|
83
|
+
|
84
|
+
注意:安装过后,需在控制台输入 `nb orm upgrade` 指令以初始化数据库。
|
85
|
+
|
86
|
+
## ⚙️ 配置
|
87
|
+
|
88
|
+
在 nonebot2 项目的`.env`文件中添加下表中的必填配置
|
89
|
+
|
90
|
+
| 配置项 | 必填 | 说明 |
|
91
|
+
|:-----:|:----:|:----:|
|
92
|
+
| fishes | 否 | 配置鱼塘内鱼们的名称、权重、等待时间和价格 |
|
93
|
+
| fishing_limit | 否 | 填入每次钓鱼后,限制钓鱼的秒数 |
|
94
|
+
| fishing_coin_name | 否 | 填入卖鱼获取的货币名称 |
|
95
|
+
| special_fish_enabled | 否 | 是否启用赛博放生功能(默认为否) |
|
96
|
+
| special_fish_price | 否 | 每放生一次所需的货币数量 |
|
97
|
+
| special_fish_probability | 否 | 钓鱼时钓到用户放生的鱼的概率 |
|
98
|
+
|
99
|
+
其中 `fishes` 配置项说明如下:
|
100
|
+
|
101
|
+
```dotenv
|
102
|
+
FISHES='
|
103
|
+
[
|
104
|
+
{
|
105
|
+
"name": "小鱼", # 鱼的名称
|
106
|
+
"frequency": 2, # 鱼上钩的时间
|
107
|
+
"weight": 100, # 权重
|
108
|
+
"price": 2 # 价格
|
109
|
+
}
|
110
|
+
]
|
111
|
+
'
|
112
|
+
```
|
113
|
+
|
114
|
+
## 🔨 更新
|
115
|
+
|
116
|
+
每一次更新后,需执行 `nb orm upgrade`。
|
117
|
+
|
118
|
+
## 🎉 使用
|
119
|
+
|
120
|
+
### 指令表
|
121
|
+
| 指令 | 范围 | 说明 |
|
122
|
+
|:-----:|:----:|:----:|
|
123
|
+
| 钓鱼 | 所有 | 放下鱼竿 |
|
124
|
+
| 卖鱼 | 所有 | 获取货币 |
|
125
|
+
| 放生 | 所有 | 赛博放生 |
|
126
|
+
| 祈愿 | 所有 | 向神祈愿 |
|
127
|
+
| 背包 | 所有 | 查看背包 |
|
128
|
+
| 成就 | 所有 | 查看成就 |
|
129
|
+
| 排行榜 | 所有 | 富翁排行 |
|
130
|
+
|
131
|
+
### 赛博放生
|
132
|
+
|
133
|
+
当用户使用货币放生由自己取名的一条鱼后,每个用户在钓鱼时都有机会钓到那一条鱼。但此功能开关 `special_fish_enabled` 默认关闭,原因是用户生成内容如果不符合规范,可能导致出现不可预料的情况,请谨慎开启。
|
134
|
+
|
135
|
+
|
136
|
+
## 📝 Todo
|
137
|
+
|
138
|
+
- [x] 重写数据库逻辑(改为使用 [nonebot/plugin-orm](https://github.com/nonebot/plugin-orm))
|
139
|
+
- [x] 增加系统商店,卖出钓到的鱼们
|
140
|
+
- [x] 赛博放生 [#4](https://github.com/C14H22O/nonebot-plugin-fishing/issues/4) (已基本完成)
|
141
|
+
- [ ] 使用 [nonebot_plugin_chikari_economy](https://github.com/mrqx0195/nonebot_plugin_chikari_economy) 经济系统
|
142
|
+
- [ ] 为鱼竿增加耐久度,耐久度为0时需重新购买鱼竿
|
143
|
+
- [ ] 为钓鱼背包添加排序
|
144
|
+
- [x] 添加成就系统
|
@@ -0,0 +1,14 @@
|
|
1
|
+
nonebot_plugin_fishing/__init__.py,sha256=u8T_bhDTSWlUOqv8GUchjJ0T-v-AwvenbZHtahYDt9Y,6334
|
2
|
+
nonebot_plugin_fishing/config.py,sha256=jJm-KORMyLhNMOhmxqdat381QeOi4CsHyvU3ZSgyO0o,2369
|
3
|
+
nonebot_plugin_fishing/data_source.py,sha256=4uHuquboXQHfKNbZmhJC2p3ASzAEZD8i_5a3Ck_qJnk,18938
|
4
|
+
nonebot_plugin_fishing/model.py,sha256=_DtmxiQhJDiIvY1XOMQZ0HA-ruWY0bexWX9frdhnk0Q,752
|
5
|
+
nonebot_plugin_fishing/migrations/1be1c9b715a9_add_achievements.py,sha256=NELMtqzBf1A1EMsypn83ZIUTaqN27lRmX0H-D2BrOTg,1119
|
6
|
+
nonebot_plugin_fishing/migrations/7609e6d106dd_init_db.py,sha256=tpuIfsS6yPsnGIeMPo16exsEfYZ_urgYAqlCyQ8aw-Y,1386
|
7
|
+
nonebot_plugin_fishing/migrations/c5ab992c9af3_add_achievements.py,sha256=KVj9ADeP03zfW4ZBDmnghbWdxLor3u1yKeho0GaddCI,1119
|
8
|
+
nonebot_plugin_fishing/migrations/e9015df43907_add_special_fishes_field.py,sha256=R4p9vPD5lgg4vmY2KUgF2qIlraxhPYkL93lM5l7wMZw,1094
|
9
|
+
nonebot_plugin_fishing/migrations/f70bdeaec7a4_add_specialfishes_table.py,sha256=DUqv9MTaOSZCBj_9oT2eY3pmWeMnyH0cPj9GyYa5Sag,1194
|
10
|
+
nonebot_plugin_fishing2-0.0.1.dist-info/licenses/LICENSE,sha256=yuLTg7OdKnH7rznCsJ31UJwI4B8_oEP4f_zE7bJS75w,1091
|
11
|
+
nonebot_plugin_fishing2-0.0.1.dist-info/METADATA,sha256=Jr-jeWY5HxDtca1GGRSL1X52guWKRaZBO4DIA3LlrBM,4667
|
12
|
+
nonebot_plugin_fishing2-0.0.1.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
|
13
|
+
nonebot_plugin_fishing2-0.0.1.dist-info/top_level.txt,sha256=vuWOK_pk0nchZlJtKePr16LLEgIEjBkPf9aQNSlSsoU,23
|
14
|
+
nonebot_plugin_fishing2-0.0.1.dist-info/RECORD,,
|
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 Polaris_Light
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
@@ -0,0 +1 @@
|
|
1
|
+
nonebot_plugin_fishing
|