Skip to content

Commit

Permalink
0.0.5 pre
Browse files Browse the repository at this point in the history
从多线程更改成异步以节约资源

抽奖更新以及加入连抽

bot_status.py 小更改
  • Loading branch information
HenryXiaoYang committed Jan 21, 2024
1 parent 5e88411 commit 9e1e273
Show file tree
Hide file tree
Showing 17 changed files with 202 additions and 116 deletions.
12 changes: 3 additions & 9 deletions database.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,14 @@

from loguru import logger

from singleton import singleton


# 2b queue没法获取返回值

@singleton
class BotDatabase:
_instance = None

def __new__(cls, *args, **kw):
if cls._instance is None:
cls._instance = object.__new__(cls, *args, **kw)
return cls._instance

def __init__(self):
super().__init__()

self.database = sqlite3.connect('userpoints.db', check_same_thread=False) # 连接数据库
self.wxid_list = self._get_wxid_list() # 获取已有用户列表

Expand Down
7 changes: 4 additions & 3 deletions main_config.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#Version 0.0.4
#Version 0.0.5 pre
bot_version: "v0.0.5 pre"

#如果不知道自己在干什么请别动这两行
ip: 127.0.0.1
port: 5555

admins: [ "" ]

# 建议:(cpu核心数)*5-4
max_thread: 16
max_worker: 25

command_prefix: "/"

Expand Down
2 changes: 2 additions & 0 deletions plans_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
import os

from plans_interface import PlansInterface
from singleton import singleton


@singleton
class PlansManager:
def __init__(self):
self.plans = {}
Expand Down
1 change: 0 additions & 1 deletion plugin_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#
# This program is licensed under the GNU General Public License v3.0.

# plugin_interface.py
class PluginInterface:
def run(self, recv):
raise NotImplementedError("Subclasses must implement the 'run' method.")
26 changes: 10 additions & 16 deletions plugin_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
# This program is licensed under the GNU General Public License v3.0.
#
# This program is licensed under the GNU General Public License v3.0.
#
# This program is licensed under the GNU General Public License v3.0.

import importlib
import os
Expand All @@ -13,19 +11,12 @@
from loguru import logger

from plugin_interface import PluginInterface
from singleton import singleton


@singleton
class PluginManager:
_instance = None

def __new__(cls, *args, **kw):
if cls._instance is None:
cls._instance = object.__new__(cls, *args, **kw)
return cls._instance

def __init__(self):
super().__init__()

self.plugins = {}
self.keywords = {}

Expand Down Expand Up @@ -62,7 +53,8 @@ def get_keywords(self):
return self.keywords

def load_plugin(self, plugin_name):
if plugin_name not in self.plugins:
if plugin_name not in self.plugins and plugin_name not in self.excluded_plugins and plugin_name != [
'manage_plugins']:
module = importlib.import_module(f'plugins.{plugin_name}')
plugin_class = getattr(module, plugin_name)
if issubclass(plugin_class, PluginInterface):
Expand All @@ -79,11 +71,10 @@ def load_plugins(self, plugin_dir):
for plugin_file in os.listdir(plugin_dir):
if plugin_file.endswith(".py") and plugin_file != "__init__.py" and not plugin_file.startswith('_'):
plugin_name = os.path.splitext(plugin_file)[0]
if plugin_name not in self.excluded_plugins:
self.load_plugin(plugin_name)
self.load_plugin(plugin_name)

def unload_plugin(self, plugin_name):
if plugin_name in self.plugins and plugin_name not in ['manage_plugins']:
if plugin_name in self.plugins and plugin_name != ['manage_plugins']:
del self.plugins[plugin_name]
self.refresh_keywords()
logger.debug('- 已卸载插件:{plugin_name}'.format(plugin_name=plugin_name))
Expand All @@ -92,13 +83,16 @@ def unload_plugin(self, plugin_name):
return False

def reload_plugin(self, plugin_name):
if self.unload_plugin(plugin_name):
if self.unload_plugin(plugin_name) and plugin_name != ['manage_plugins']:
if self.load_plugin(plugin_name):
logger.debug('! 已重载插件:{plugin_name}'.format(plugin_name=plugin_name))
return True
else:
logger.debug('! 重载插件失败:{plugin_name}'.format(plugin_name=plugin_name))
return False
else:
logger.debug('! 重载插件失败:{plugin_name}'.format(plugin_name=plugin_name))
return False


# 实例化插件管理器
Expand Down
3 changes: 1 addition & 2 deletions plugins/admin_points.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@ def __init__(self):
self.bot = pywxdll.Pywxdll(self.ip, self.port) # 机器人api

self.admin_list = main_config['admins']

def run(self, recv):
self.db = BotDatabase()

def run(self, recv):
if recv['id1']: # 用于判断是否为管理员
admin_wxid = recv['id1'] # 是群
else:
Expand Down
3 changes: 2 additions & 1 deletion plugins/bot_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ def __init__(self):
config = yaml.load(f.read(), Loader=yaml.FullLoader)

self.status_message = config['status_message']
self.bot_version = config['bot_version']

current_directory = os.path.dirname(os.path.abspath(__file__))
main_config_path = os.path.join(current_directory, '../main_config.yml')
with open(main_config_path, 'r', encoding='utf-8') as f: # 读取设置
main_config = yaml.load(f.read(), Loader=yaml.FullLoader)

self.bot_version = main_config['bot_version']

self.ip = main_config['ip']
self.port = main_config['port']
self.bot = pywxdll.Pywxdll(self.ip, self.port) # 机器人api
Expand Down
3 changes: 1 addition & 2 deletions plugins/bot_status.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
keywords: ["机器人状态","bottest"]
plugin_name: "bot_status"

status_message: "Bot Running😊"
bot_version: "v0.0.4"
status_message: "Bot Running😊"
2 changes: 0 additions & 2 deletions plugins/gpt.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
# This program is licensed under the GNU General Public License v3.0.
#
# This program is licensed under the GNU General Public License v3.0.
#
# This program is licensed under the GNU General Public License v3.0.

import os

Expand Down
2 changes: 0 additions & 2 deletions plugins/gpt4.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
# This program is licensed under the GNU General Public License v3.0.
#
# This program is licensed under the GNU General Public License v3.0.
#
# This program is licensed under the GNU General Public License v3.0.

import os

Expand Down
140 changes: 112 additions & 28 deletions plugins/lucky_draw.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def __init__(self):
config = yaml.load(f.read(), Loader=yaml.FullLoader)

self.lucky_draw_probability = config['lucky_draw_probability']
self.max_draw = config['max_draw']

current_directory = os.path.dirname(os.path.abspath(__file__))
main_config_path = os.path.join(current_directory, '../main_config.yml')
Expand All @@ -35,6 +36,10 @@ def __init__(self):
self.db = database.BotDatabase()

def run(self, recv):
global draw_count, draw_name

# -----初始化与消息格式监测-----

if recv['id1']: # 用于判断是否为管理员
target_wxid = recv['id1'] # 是群
else:
Expand All @@ -45,47 +50,84 @@ def run(self, recv):
target_points = self.db.get_points(target_wxid)

error = ''
if len(command) != 2:
error = '-----XYBot-----\n❌命令格式错误!请查看菜单获取正确命令格式'
else:

if len(command) == 2:
draw_name = command[1]
draw_count = 1

if not draw_name in self.lucky_draw_probability.keys():
if draw_name not in self.lucky_draw_probability.keys():
error = '-----XYBot-----\n❌抽奖种类未知或者无效'
elif draw_name in self.lucky_draw_probability.keys() and target_points < \
self.lucky_draw_probability[draw_name][
'cost']:
error = '-----XYBot-----\n❌积分不足!'

elif len(command) == 3:
draw_name = command[1]
draw_count = int(command[2])

if draw_name not in self.lucky_draw_probability.keys():
error = '-----XYBot-----\n❌抽奖种类未知或者无效'
elif draw_name in self.lucky_draw_probability.keys() and target_points < \
self.lucky_draw_probability[draw_name][
'cost'] * draw_count:
error = '-----XYBot-----\n❌积分不足!'
else:
error = '-----XYBot-----\n❌命令格式错误!请查看菜单获取正确命令格式'

if not error:

# -----抽奖核心部分-----

draw_probability = self.lucky_draw_probability[draw_name]['probability']
draw_cost = self.lucky_draw_probability[draw_name]['cost']
draw_cost = self.lucky_draw_probability[draw_name]['cost'] * draw_count

wins = []

self.db.add_points(target_wxid, -1 * draw_cost)

random_num = random.uniform(0, 1)
cumulative_probability = 0
for probability, prize_dict in draw_probability.items():
cumulative_probability += float(probability)
if random_num <= cumulative_probability:
win_name = prize_dict['name']
win_points = prize_dict['points']

logger.info(
'[抽奖] {target_wxid}在{draw_name}抽奖中抽到了{win_name} 抽到了{win_points}点积分'.format(
target_wxid=target_wxid, draw_name=draw_name, win_name=win_name, win_points=win_points))
self.db.add_points(target_wxid, win_points)
out_message = '-----XYBot-----\n🥳恭喜你在 {draw_name}抽奖 中抽到了 {win_name}!✌️你抽到了 {win_points} 点积分!\n🙏🏻谢谢惠顾!\n\n🥳你在抽 {draw_name}抽奖 ,{draw_name}抽奖 需要{draw_cost}点积分💰,中奖概率如下❗️\n\n'.format(
draw_name=draw_name, draw_cost=draw_cost, win_name=win_name, win_points=win_points)

for probability, prize_info in draw_probability.items():
message = '🤑{prize_name}:概率为{probability}%,奖励为{prize_points}点积分\n'.format(
prize_name=prize_info['name'], probability=int(float(probability) * 100),
prize_points=prize_info['points'])
out_message += message
self.send_friend_or_group(recv, out_message)

break
# 保底抽奖
min_guaranteed = draw_count // 10
for _ in range(min_guaranteed):
random_num = random.uniform(0, 0.4)
cumulative_probability = 0
for probability, prize_dict in draw_probability.items():
cumulative_probability += float(probability)
if random_num <= cumulative_probability:
win_name = prize_dict['name']
win_points = prize_dict['points']
win_symbol = prize_dict['symbol']

wins.append((win_name, win_points, win_symbol))
break

# 正常抽奖
for _ in range(draw_count - min_guaranteed):
random_num = random.uniform(0, 1)
cumulative_probability = 0
for probability, prize_dict in draw_probability.items():
cumulative_probability += float(probability)
if random_num <= cumulative_probability:
win_name = prize_dict['name']
win_points = prize_dict['points']
win_symbol = prize_dict['symbol']

wins.append((win_name, win_points, win_symbol))
break

# -----消息组建-----

total_win_points = 0
for win_name, win_points, win_symbol in wins:
total_win_points += win_points

self.db.add_points(target_wxid, total_win_points)
logger.info(
f'[抽奖] wxid: {target_wxid} | 抽奖名: {draw_name} | 次数: {draw_count} | 赢取积分: {total_win_points}')

message = self.make_message(wins, draw_name, draw_count, total_win_points, draw_cost)

self.send_friend_or_group(recv, message)

else:
self.send_friend_or_group(recv, error)
Expand All @@ -98,3 +140,45 @@ def send_friend_or_group(self, recv, out_message='null'):
else:
logger.info('[发送信息]{out_message}| [发送到] {wxid}'.format(out_message=out_message, wxid=recv['wxid']))
self.bot.send_txt_msg(recv['wxid'], out_message) # 发送

@staticmethod
def make_message(wins, draw_name, draw_count, total_win_points, draw_cost):
name_max_len = 0
for win_name, win_points, win_symbol in wins:
if len(win_name) > name_max_len:
name_max_len = len(win_name)

begin_message = f"----XYBot抽奖----\n🥳恭喜你在 {draw_count}{draw_name}抽奖 中抽到了:\n\n"
lines = []
for _ in range(name_max_len + 2):
lines.append('')

begin_line = 0

one_line_length = 0

for win_name, win_points, win_symbol in wins:
if one_line_length >= 10:
begin_line += name_max_len + 2
for _ in range(name_max_len + 2):
lines.append('')
one_line_length = 0

lines[begin_line] += win_symbol
for i in range(begin_line + 1, begin_line + name_max_len + 1):
if i % (name_max_len + 2) <= len(win_name):
lines[i] += "\u2004" + win_name[i % (name_max_len + 2) - 1]
else:
lines[i] += win_symbol
lines[begin_line + name_max_len + 1] += win_symbol

one_line_length += 1

message = ''
message += begin_message
for line in lines:
message += line + '\n'

message += f"\n\n🎉总计赢取积分: {total_win_points}🎉\n🎉共计消耗积分:{draw_cost}🎉\n\n概率请自行查询菜单⚙️"

return message
Loading

0 comments on commit 9e1e273

Please sign in to comment.