From 2bc0caf1e35ee48fc887d45c880659a8eb697e02 Mon Sep 17 00:00:00 2001 From: kcn3388 Date: Thu, 11 Aug 2022 11:45:38 +0800 Subject: [PATCH] fix for new version of hoshino --- __init__.py | 10 ++-- admin.py | 67 +++++++++++---------- authMS.py.example | 5 +- card.py | 62 +++++++++++-------- constant.py | 21 +++---- friend.py | 5 +- group.py | 47 ++++++++------- schedule.py | 17 +++--- util.py | 150 +++++++++++++++++++++++++--------------------- web_activate.py | 19 +++--- web_server.py | 21 +++---- 11 files changed, 230 insertions(+), 194 deletions(-) diff --git a/__init__.py b/__init__.py index a21c6c6..ef0e1d2 100644 --- a/__init__.py +++ b/__init__.py @@ -6,8 +6,6 @@ from .web_server import auth from .web_activate import activate - - if config.ENABLE_WEB: # 开启web请修改authMS.py app = get_bot().server_app @@ -15,14 +13,14 @@ app.register_blueprint(activate) -@on_command('充值帮助', aliases=('我要充钱','续费帮助','我要续费','👴要充钱'), only_to_me=False) +@on_command('充值帮助', aliases=('我要充钱', '续费帮助', '我要续费', '👴要充钱'), only_to_me=False) async def reg_help_chat(session): if session.event.detail_type == 'private': msg = config.REG_HELP_PRIVATE else: msg = config.REG_HELP_GROUP - #else: - # 新版QQ已不在有discuss, 所有多人聊天都是群消息 + # else: + # 新版QQ已不在有discuss, 所有多人聊天都是群消息 # return await session.finish(msg) @@ -32,7 +30,7 @@ async def master_help_chat(session): if session.event.detail_type == 'group': return if session.event.user_id not in hoshino.config.SUPERUSERS: - await session.finish('只有主人才能查看此页帮助') + await session.finish('你又不是管理员你查你🐴呢') await session.finish(config.ADMIN_HELP) diff --git a/admin.py b/admin.py index 5ec5b81..c62c148 100644 --- a/admin.py +++ b/admin.py @@ -9,15 +9,14 @@ from .constant import config - @on_command('变更所有授权', aliases=('批量变更', '批量授权'), only_to_me=False) async def add_time_all_chat(session): - ''' + """ 为所有已有授权的群增加授权x天, 可用于维护补偿时间等场景 - ''' + """ if session.event.user_id not in hoshino.config.SUPERUSERS: util.log(f'{session.event.user_id}尝试批量授权, 已拒绝') - await session.finish('只有主人才能批量授权哦') + await session.finish('你又不是老子的骂死塔你批量授权个🔨') return if not session.current_arg: await session.finish('请发送需要为所有群增加或减少的长, 例如“变更所有授权 7”') @@ -33,17 +32,17 @@ async def add_time_all_chat(session): @on_command('授权列表', aliases=('查看授权列表', '查看全部授权', '查询全部授权'), only_to_me=True) async def group_list_chat(session): - ''' + """ 此指令获得的是, 所有已经获得授权的群, 其中一些群可能Bot并没有加入 \n 分页显示, 请在authMS.py中配置 - ''' + """ if session.event.user_id not in hoshino.config.SUPERUSERS: util.log(f'{session.event.user_id}尝试查看授权列表, 已拒绝') - await session.finish('只有主人才能查看授权列表哦') + await session.finish('你又不是老子的骂死塔你看你大爷') return if session.event.detail_type == 'group': # 群聊查看授权列表你也是个小天才 - await session.finish('请超级管理员私聊机器人查看授权列表') + await session.finish('群聊查看授权列表?你也是真个天才') if not session.current_arg.strip(): # 无其他参数默认第一页 @@ -92,7 +91,7 @@ async def add_time_chat(session): if session.event.user_id not in hoshino.config.SUPERUSERS: util.log(f'{session.event.user_id}尝试为群{gid}增加{days}天授权, 已拒绝') - await session.finish('只有主人才能变更授权哦') + await session.finish('你又不是老子的骂死塔你改个p') return result = await util.change_authed_time(gid, days) @@ -101,7 +100,6 @@ async def add_time_chat(session): await session.finish(msg) - @on_command('转移授权', only_to_me=False) async def group_change_chat(session): if not session.current_arg: @@ -116,27 +114,29 @@ async def group_change_chat(session): if session.event.user_id not in hoshino.config.SUPERUSERS: util.log(f'{session.event.user_id}尝试转移授权{old_gid}到{new_gid}, 已拒绝') - session.finish('只有主人才能转移授权哦') + session.finish('又不是老子的骂死塔,还想转移?想p吃呢') return - + gtime_old = util.check_group(old_gid) if gtime_old == 0: await session.finish('旧群无授权, 不可进行转移') if old_gid == new_gid: await session.finish('宁搁这儿原地TP呢?') - + await util.transfer_group(old_gid, new_gid) gtime_new = util.check_group(new_gid) - msg = await util.process_group_msg(new_gid,expiration=gtime_new, title=f'旧群{old_gid}授权已清空, 新群授权状态:\n') + msg = await util.process_group_msg(new_gid, expiration=gtime_new, title=f'旧群{old_gid}授权已清空, 新群授权状态:\n') await notify_group(group_id=old_gid, txt=f'机器人管理员已转移本群授权时长至其他群。') await session.finish(msg) + +# noinspection PyUnboundLocalVariable @on_command('授权状态', only_to_me=False) async def auth_status_chat(session): if session.event.user_id not in hoshino.config.SUPERUSERS: util.log(f'{session.event.user_id}尝试查看授权状态, 已拒绝') - await session.finish('只有主人才能查看授权状态哦') + await session.finish('你又不是老子的骂死塔你查个🥚🥚') return for sid in hoshino.get_self_ids(): sgl = set(g['group_id'] @@ -154,10 +154,10 @@ async def auth_status_chat(session): @on_command('清除授权', aliases=('删除授权', '移除授权', '移除群授权', '删除群授权'), only_to_me=True) async def remove_auth_chat(session): - ''' + """ 完全移除一个群的授权 \n 不需要二次确认, 我寻思着你rm /* -rf的时候也没人让你二次确认啊 \n - ''' + """ if not session.current_arg.strip(): await session.finish('请输入正确的群号, 例如“清除授权 123456789”') gid = int(session.current_arg.strip()) @@ -165,7 +165,7 @@ async def remove_auth_chat(session): if session.event.user_id not in hoshino.config.SUPERUSERS: util.log(f'{session.event.user_id}尝试为群{gid}清除授权, 已拒绝') - await session.finish('只有主人才能清除授权哦') + await session.finish('你不是骂死塔还想删授权,是不是要老子把你🐴删了') if not time_left: await session.finish('此群未获得授权') @@ -178,11 +178,12 @@ async def remove_auth_chat(session): await session.send(msg) -@on_command('不检查人数', aliases=('设置人数白名单'), only_to_me=False) +# noinspection PyUnboundLocalVariable +@on_command('不检查人数', aliases='设置人数白名单', only_to_me=False) async def no_number_check_chat(session): - ''' + """ 不检查一个群的人数是否超过人数限制, 在群聊中发送则为不检查本群 - ''' + """ if session.event.detail_type == 'group': gid = session.event.group_id elif session.event.detail_type == 'private': @@ -193,7 +194,7 @@ async def no_number_check_chat(session): uid = session.event.user_id if uid not in hoshino.config.SUPERUSERS: util.log(f'{uid}尝试为群{gid}清除设置不检查人数, 已拒绝') - await session.finish('只有主人才能设置白名单') + await session.finish('你不是主人你设你个大头鬼的人数白名单') return util.allowlist(group_id=gid, operator='add', nocheck='no_number_check') @@ -202,7 +203,8 @@ async def no_number_check_chat(session): await session.finish(f'已将群{gid}添加至白名单, 类型为不检查人数') -@on_command('不检查授权', aliases=('设置授权白名单'), only_to_me=False) +# noinspection PyUnboundLocalVariable +@on_command('不检查授权', aliases='设置授权白名单', only_to_me=False) async def no_auth_check_chat(session): if session.event.detail_type == 'group': gid = session.event.group_id @@ -214,7 +216,7 @@ async def no_auth_check_chat(session): uid = session.event.user_id if uid not in hoshino.config.SUPERUSERS: util.log(f'{uid}尝试为群{gid}清除设置不检查授权, 已拒绝') - await session.finish('只有主人才能设置白名单') + await session.finish('你不是主人你设你个大头鬼的授权白名单') return util.allowlist(group_id=gid, operator='add', nocheck='no_auth_check') util.log(f'已将群{gid}添加至白名单, 类型为不检查授权') @@ -222,11 +224,12 @@ async def no_auth_check_chat(session): await session.finish(f'已将群{gid}添加至白名单, 类型为不检查授权') +# noinspection PyUnboundLocalVariable @on_command('添加白名单', only_to_me=False) async def no_check_chat(session): - ''' + """ 最高级别白名单, 授权与人数都检查 - ''' + """ if session.event.detail_type == 'group': gid = session.event.group_id elif session.event.detail_type == 'private': @@ -237,7 +240,7 @@ async def no_check_chat(session): uid = session.event.user_id if uid not in hoshino.config.SUPERUSERS: util.log(f'{uid}尝试为群{gid}清除设置添加白名单, 已拒绝') - await session.finish('只有主人才能设置白名单') + await session.finish('不是主人还想设白名单?你是不是憨批') return util.allowlist(group_id=gid, operator='add', nocheck='no_check') @@ -246,7 +249,7 @@ async def no_check_chat(session): await session.finish(f'已将群{gid}添加至白名单, 类型为全部不检查') -@on_command('移除白名单', aliases=('删除白名单')) +@on_command('移除白名单', aliases='删除白名单') async def remove_allowlist_chat(session): if not session.current_arg.strip(): await session.finish('请输入正确的群号, 例如“移除白名单 123456789”') @@ -255,7 +258,7 @@ async def remove_allowlist_chat(session): if uid not in hoshino.config.SUPERUSERS: util.log(f'{uid}尝试移除白名单{gid}, 已拒绝') - await session.finish('只有主人才能移除白名单') + await session.finish('不是主人还想设白名单?你是不是憨批') return re_code = util.allowlist(group_id=gid, operator='remove') @@ -270,7 +273,7 @@ async def remove_allowlist_chat(session): async def get_allowlist_chat(session): if session.event.user_id not in hoshino.config.SUPERUSERS: util.log(f'{session.event.user_id}尝试查看白名单, 已拒绝') - await session.finish('只有主人才能查看白名单') + await session.finish('不是主人还想看白名单?你是不是憨批') return allow_list = util.get_list(list_type='allowlist') @@ -285,7 +288,7 @@ async def get_allowlist_chat(session): gname = gname_dir[gid] gnocheck = allow_list[gid] msg += f'群名:{gname}\n类型:{gnocheck}\n\n' - i = i+1 + i = i + 1 session.finish(msg) @@ -293,7 +296,7 @@ async def get_allowlist_chat(session): async def reload_ef(session): if session.event.user_id not in hoshino.config.SUPERUSERS: util.log(f'{session.event.user_id}刷新事件过滤器, 已拒绝') - await session.finish('只有主人才能刷新事件过滤器') + await session.finish('刷你🐴,给👴爪巴') return await util.flush_group() await session.send("刷新成功!") diff --git a/authMS.py.example b/authMS.py.example index 109652e..c6c3902 100644 --- a/authMS.py.example +++ b/authMS.py.example @@ -59,7 +59,10 @@ class auth_config(object): # 提醒/检查的时间间隔, 单位小时, # 值为1, 意为每小时检查一次, 注意实际每天的检查次数会向下取整 - FREQUENCY = 6 + # 修改:以下为时间间隔,从上往下依次是小时,分钟,秒 + FREQUENCY_H = 8 + FREQUENCY_M = 0 + FREQUENCY_S = 0 # ----------------------授权列表与卡密列表---------------------------- diff --git a/card.py b/card.py index 64cbded..debccd1 100644 --- a/card.py +++ b/card.py @@ -1,13 +1,20 @@ -from hoshino.config.__bot__ import SUPERUSERS -from nonebot import on_command +import base64 +import re from math import ceil -import hoshino -import re +from nonebot import on_command +import hoshino +from hoshino import aiorequests +from hoshino.config.__bot__ import SUPERUSERS +from hoshino.typing import CommandSession from . import util from .constant import config +headers = {"User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.6) ", + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + "Accept-Language": "zh-cn" + } @on_command('生成卡密', only_to_me=True) @@ -15,11 +22,11 @@ async def creat_key_chat(session): if session.event.user_id not in hoshino.config.SUPERUSERS: # 非超管, 忽略 util.log(f'{session.event.user_id}尝试生成卡密,已拒绝') - await session.finish('只有主人才能生成卡密哦') + await session.finish('你不是管理员你是在生🥚🐴') return if session.event.detail_type == 'group': # 群聊生成卡密你可真是个小天才 - await session.finish('请私聊机器人生成') + await session.finish('群聊生成卡密你可真是个小天才') return origin = session.current_arg.strip() pattern = re.compile(r'^(\d{1,5})\*(\d{1,3})$') @@ -42,20 +49,20 @@ async def creat_key_chat(session): async def key_list_chat(session): if session.event.user_id not in hoshino.config.SUPERUSERS: util.log(f'{session.event.user_id}尝试查看卡密列表,已拒绝') - await session.finish('只有主人才能查看卡密列表哦') + await session.finish('你不是管理员你看你个√8️⃣') return if session.event.detail_type == 'group': # 群聊查看卡密你可真是个小天才 await session.finish('憨批!私聊我查看剩余卡密啦!') if not session.current_arg.strip(): # 无其他参数默认第一页 - page = 1 + page = 1 else: page = int(session.current_arg.strip()) cards_in_page = config.CARDS_IN_PAGE key_list = util.get_key_list() length = len(key_list) - pages_all = ceil(length/cards_in_page) + pages_all = ceil(length / cards_in_page) if page > pages_all: await session.finish(f'没有那么多页, 当前共有卡密共{length}条, 共{pages_all}页') @@ -64,12 +71,12 @@ async def key_list_chat(session): if not length: await session.finish('无可用卡密信息') - + msg = '======卡密列表======\n' i = 0 for items in key_list: i = i + 1 - if i < (page-1)*cards_in_page+1 or i > page*cards_in_page: + if i < (page - 1) * cards_in_page + 1 or i > page * cards_in_page: continue msg += '卡密:' + items['key'] + '\n时长:' + str(items['duration']) + '天\n' msg += f'第{page}页, 共{pages_all}页\n发送卡密列表+页码以查询其他页' @@ -78,9 +85,8 @@ async def key_list_chat(session): @on_command('充值', only_to_me=False) async def reg_group_chat(session: CommandSession): - key = session.get('key', prompt="请输入卡密(直接发送)") - if len(key) != 16: + if len(key) != 32: session.finish('卡密错误,请检查后重新开始。') days = util.query_key(key) if days == 0: @@ -98,14 +104,22 @@ async def reg_group_chat(session: CommandSession): if gid is None: return if session.event.detail_type == 'private': - sid = session.event.self_id - group_name = await util.get_group_name(sid, gid) - msg = f"""[CQ:image,file={get_group_acatar_url(int(gid))}]\n -群号:{gid} -群名:{group_name} -※请确认以上信息后,回复“确认”来完成本次操作。 -※回复其他内容会终止。 -""" + group_info = await util.get_group_info(gid) + group_head = f"https://p.qlogo.cn/gh/{gid}/{gid}/0" + msg = "这群都没加呢你充个🐔8️⃣" + try: + response = await aiorequests.get(group_head, headers=headers) + base64_str = f'base64://{base64.b64encode(await response.content).decode()}' + msg = f"[CQ:image,file={base64_str}]\n" \ + f"群号:{gid}\n" \ + f"群名:{group_info[int(gid)]}\n" \ + f"※请确认以上信息后,回复“确认”来完成本次操作。\n" \ + f"※回复其他内容会终止。" + except KeyError: + await session.bot.finish(session.event, msg) + except Exception as e: + print(repr(e)) + await session.bot.finish(session.event, "未知错误,请联系管理员") ensure = session.get("ensure", prompt=msg) if ensure != "确认": session.finish("已取消本次充值") @@ -124,13 +138,13 @@ async def reg_group_chat(session: CommandSession): session.finish(msg) -@on_command('检验卡密',aliases=('检查卡密'), only_to_me=False) +@on_command('检验卡密', aliases='检查卡密', only_to_me=False) async def check_card_chat(session): if not session.current_arg: await session.finish('检验卡密请发送“检验卡密 卡密”哦~') else: origin = session.current_arg.strip() - pattern = re.compile(r'^(\w{16})$') + pattern = re.compile(r'^(\w{32})$') m = pattern.match(origin) if m is None: await session.finish('格式输错了啦憨批!请按照“检验卡密 卡密”进行输入!') @@ -162,7 +176,7 @@ async def auth_query_chat(session): return else: # 权限为超级管理员 - gid = session.current_arg.strip() + gid = session.current_arg.strip() if not gid.isdigit(): await session.finish('请输入正确的群号') return diff --git a/constant.py b/constant.py index fab3b90..4572396 100644 --- a/constant.py +++ b/constant.py @@ -2,25 +2,22 @@ import os import hoshino +from hoshino.config import authMS - -__version__ = '0.2.1.6' +__version__ = '0.2.2' try: - config = hoshino.config.authMS.auth_config -except: + config = authMS.auth_config +except Exception as e: # 保不准哪个憨憨又不读README呢 - hoshino.logger.error('authMS无配置文件!请仔细阅读README') - + hoshino.logger.error('authMS无配置文件!请仔细阅读README!详细报错:\n' + str(e)) -if hoshino.config.authMS.auth_config.ENABLE_COM: - path_first = hoshino.config.authMS.auth_config.DB_PATH +if authMS.auth_config.ENABLE_COM: + path_first = authMS.auth_config.DB_PATH else: - path_first = '' - + path_first = os.path.dirname(__file__) + path_first = os.path.join(path_first, "sqlite") key_dict = SqliteDict(os.path.join(path_first, 'key.sqlite'), autocommit=True) group_dict = SqliteDict(os.path.join(path_first, 'group.sqlite'), autocommit=True) trial_list = SqliteDict(os.path.join(path_first, 'trial.sqlite'), autocommit=True) # 试用列表 - - diff --git a/friend.py b/friend.py index ba60587..dbb9494 100644 --- a/friend.py +++ b/friend.py @@ -6,13 +6,12 @@ from . import util - @on_request('friend') async def friend_approve(session): if config.FRIEND_APPROVE: - util.log(f'已自动接受来自{session.event.user_id}的好友请求','friend_add') + util.log(f'已自动接受来自{session.event.user_id}的好友请求', 'friend_add') hoshino.logger.info(f'已自动接受来自{session.event.user_id}的好友请求') await session.approve() else: - util.log(f'收到来自{session.event.user_id}的好友请求','friend_add') + util.log(f'收到来自{session.event.user_id}的好友请求', 'friend_add') hoshino.logger.info(f'收到来自{session.event.user_id}的好友请求') diff --git a/group.py b/group.py index e3cddcd..cf278b3 100644 --- a/group.py +++ b/group.py @@ -1,19 +1,20 @@ -from nonebot import on_request, on_notice, on_command, NoticeSession +import asyncio from datetime import datetime import pytz -import asyncio -import hoshino, nonebot +from nonebot import on_request, on_notice, on_command, NoticeSession -from .constant import config, key_dict, group_dict, trial_list, config +import hoshino +import nonebot from . import util +from .constant import group_dict, trial_list, config tz = pytz.timezone('Asia/Shanghai') @on_request('group') async def approve_group_invite(session): - ''' + """ 自动处理入群邀请 \n 由于腾讯憨批, 现在被邀请加入50人以下的群不需要验证, 因此此条目只适用于50人以上的邀请的情况, 50人以下请参见下一条函数\n 请注意, 应当移除其他@on_request('group.add')或者其他入群管理,以防止冲突, 例如移除botmanager下的join_approve \n @@ -23,7 +24,7 @@ async def approve_group_invite(session): 2. 群授权已过期(新群试用也视为有授权, 期间内可自由加入) v0.1.1后新增, 配置ENABLE_AUTH为假的时候, 不检查授权 - ''' + """ if not config.ENABLE_AUTH: # 配置ENABLE_AUTH为0, 则授权系统不起作用, 不会自动通过加群邀请 @@ -52,19 +53,21 @@ async def approve_group_invite(session): @on_notice('group_increase') async def approve_group_invite_auto(session): - ''' + """ 被邀请加入50人以下群时会自动接受, 此时获得的事件类型为通知而非邀请 \n 无法处理拒绝入群的邀请, 应当使用退群(如果开启了自动退群的话) - ''' + """ + # noinspection PyProtectedMember self_ids = session.bot._wsr_api_clients.keys() for item in self_ids: sid = item gid = session.event.group_id + # noinspection PyUnboundLocalVariable if int(session.event.user_id) != int(sid): # 入群的人不是自己 return rt = await check_number(gid) - + if rt == 'overflow': # 人数超标不自动试用, 考虑到风控, 也不会立刻退群, 而是在下一次自动检查时退群 new_group_auth = 'no trial' @@ -84,9 +87,9 @@ async def approve_group_invite_auto(session): @on_notice('group_decrease.kick_me') async def kick_me_alert(session: NoticeSession): - ''' + """ 被踢出同样记录 - ''' + """ group_id = session.event.group_id operator_id = session.event.operator_id util.log(f'被{operator_id}踢出群{group_id}', 'group_kick') @@ -94,9 +97,9 @@ async def kick_me_alert(session: NoticeSession): @on_command('退群', only_to_me=False) async def group_leave_chat(session): - ''' + """ 退群, 并不影响授权, 清除授权请试用清除授权命令 - ''' + """ if session.event.user_id not in hoshino.config.SUPERUSERS: await session.finish('只有主人才能让我退群哦') return @@ -104,7 +107,7 @@ async def group_leave_chat(session): await session.send('正在褪裙...') rt_code = await util.gun_group(group_id=gid, reason='管理员操作') - if rt_code == True: + if rt_code: await session.send(f'已成功退出群{gid}') util.log(f'已成功退出群{gid}', 'group_leave') else: @@ -114,9 +117,9 @@ async def group_leave_chat(session): @on_command('快速检查', only_to_me=True) async def quick_check_chat(session): - ''' + """ 立即执行一次检查, 内容与定时任务一样 - ''' + """ if session.event.user_id not in hoshino.config.SUPERUSERS: return await check_auth() @@ -124,9 +127,9 @@ async def quick_check_chat(session): async def check_auth(): - ''' + """ 检查所有已加入群的授权状态, 和人数 - ''' + """ bot = nonebot.get_bot() # 该函数会独立地检查一次所有群的人数是否超标 @@ -145,7 +148,7 @@ async def check_auth(): if rt_code == 'no_check' or rt_code == 'no_auth_check': # 在白名单, 并不会影响过期事件 continue - + if time_left.total_seconds() <= 0: # 已过期, 检查是否在白名单中 @@ -166,7 +169,7 @@ async def check_auth(): util.log(f'向群{gid}发送过期提醒时发生错误{type(e)}') group_dict.pop(gid) await util.flush_group() - if days_left < config.REMIND_BRFORE_EXPIRED and days_left >= 0: + if config.REMIND_BRFORE_EXPIRED > days_left >= 0: # 将要过期 msg_remind = await util.process_group_msg( gid=gid, @@ -195,9 +198,9 @@ async def check_auth(): async def check_number(group_id=0): - ''' + """ 检查所有群的成员数量是否符合要求, 当传入group_id时则检查传入的群 - ''' + """ if group_id == 0: gnums = await util.get_group_info(info_type='member_count') else: diff --git a/schedule.py b/schedule.py index 57ae4f7..218d652 100644 --- a/schedule.py +++ b/schedule.py @@ -1,27 +1,26 @@ from nonebot import scheduler import pytz -import datetime +from hoshino.config.authMS import auth_config as config -from .constant import config from .group import check_auth tz = pytz.timezone('Asia/Shanghai') +hour = config.FREQUENCY_H +minute = config.FREQUENCY_M +second = config.FREQUENCY_S -@scheduler.scheduled_job('cron', hour='*', minute='02') + +@scheduler.scheduled_job('interval', hours=hour, minutes=minute, seconds=second) async def check_auth_sdj(): - ''' + """ 自动检查Bot已加入的群的授权是否过期 \n 注意只会检查已加入的群, 未加入而有授权的群, 不会被检查, 但是授权时间照样流逝(-1s), 在加入该群后才会在日志显示 \n 例如1月5日给A群3天授权, 那么当A群7日邀请时剩余授权时间会是1天, 9日邀请时会拒绝加群 \n v0.1.1后新增特性, 在配置ENABLE_AUTH为0, 则不会自动检查, 并且整个授权系统不生效, 但是可以充值, 生成卡密等, 以度过刚装上授权系统后的过渡期 - ''' - now = datetime.datetime.now(tz) - hour_now = now.hour - if hour_now % config.FREQUENCY != 0: - return + """ if not config.ENABLE_AUTH: return await check_auth() diff --git a/util.py b/util.py index 7f8099b..360bd1c 100644 --- a/util.py +++ b/util.py @@ -1,43 +1,43 @@ - -from hoshino.config.__bot__ import SUPERUSERS +import asyncio +import json +import os +import random +import string +import time from datetime import timedelta, datetime -from math import ceil -import random, string -import os -import time, json -import asyncio -import nonebot, hoshino +import hoshino +import nonebot +from hoshino.config.__bot__ import SUPERUSERS from .constant import key_dict, group_dict, trial_list, config - def generate_key(): - ''' - 生成16位卡密 - ''' - begin=config.BEGIN - new_key = ''.join(random.sample(string.ascii_letters + string.digits, 16-len(begin))) + """ + 生成32位卡密 + """ + begin = config.BEGIN + new_key = ''.join(random.sample(string.ascii_letters + string.digits, 32 - len(begin))) while new_key in key_dict: # 防止生成重复的卡密, 不过概率太低了。。。 - new_key = ''.join(random.sample(string.ascii_letters + string.digits, 16-len(begin))) + new_key = ''.join(random.sample(string.ascii_letters + string.digits, 32 - len(begin))) new_key = begin + new_key return new_key def add_key(duration): - ''' + """ 卡密添加到数据库中 - ''' + """ new_key = generate_key() key_dict[new_key] = duration return new_key def get_key_list(): - ''' + """ 获取全部的卡密列表 - ''' + """ key_list = [] for key, value in key_dict.iteritems(): key_list.append({'key': key, 'duration': value}) @@ -45,9 +45,9 @@ def get_key_list(): def del_key(key): - ''' + """ 删除一张卡密, 成功返回True - ''' + """ if key in key_dict: key_dict.pop(key) return True @@ -55,9 +55,9 @@ def del_key(key): def update_key(key, duration): - ''' + """ 更新一张卡密,成功返回True - ''' + """ if duration <= 0: # 禁止将有效期更新为0, 因为检验卡密时以0为无效标志 return False @@ -68,9 +68,9 @@ def update_key(key, duration): def query_key(key): - ''' + """ 检查一张卡密, 有效则返回可以增加的授权时间, 无效则返回0 - ''' + """ if key in key_dict: return key_dict[key] else: @@ -78,10 +78,10 @@ def query_key(key): def check_group(gid): - ''' - 检查一个群是否有授权, 如果有返回过期时间(datetime格式), 否则返回False. + """ + 检查一个群是否有授权, 如果有返回过期时间(datetime格式), 否则返回False. 注意无论Bot是否加入此群都会返回 - ''' + """ if gid in group_dict: return group_dict[gid] else: @@ -89,9 +89,9 @@ def check_group(gid): async def reg_group(gid, key): - ''' + """ 为一个群充值, 卡密无效则返回False, 否则返回剩余有效期(datatime格式) - ''' + """ days = query_key(key) if days == 0: return False @@ -101,14 +101,15 @@ async def reg_group(gid, key): async def change_authed_time(gid, time_change=0, operate=''): - ''' + """ 不使用卡密, 而直接对一个群的授权时间进行操作 - ''' + """ if operate == 'clear': try: # 用try是因为可能会尝试给本来就无授权的群清空授权, 此种情况并不需要另外通知, 因为最终目的一致 group_dict.pop(gid) - except: + except Exception as e: + print(e) pass await flush_group() return 0 @@ -121,23 +122,24 @@ async def change_authed_time(gid, time_change=0, operate=''): await flush_group() return group_dict[gid] + async def get_nickname(user_id): - ''' + """ 获取用户昵称 - ''' + """ uid = user_id user_info = await nonebot.get_bot().get_stranger_info(user_id=uid) return user_info['nickname'] async def get_group_info(group_ids=0, info_type='group_name'): - ''' + """ 1. 传入一个整型数字, 返回单个群指定信息, 格式为字典 2. 传入一个list, 内含多个群号(int), 返回一个字典, 键为群号, 值为指定信息 3. 不填入参数, 返回一个包含所有群号与指定信息的字典 无论获取多少群信息, 均只有一次API的开销, 传入未加入的群时, 将自动忽略 info_type支持group_id, group_name, max_member_count, member_count - ''' + """ group_info_all = await get_group_list_all() _gids = [] _gnames = [] @@ -149,10 +151,14 @@ async def get_group_info(group_ids=0, info_type='group_name'): if group_ids == 0: return group_info_dir - if type(group_ids) == int: + if isinstance(group_ids, int): # 转为列表 group_ids = [group_ids] print(group_ids) + if isinstance(group_ids, str): + # 转为列表 + group_ids = [int(group_ids)] + print(group_ids) for key in list(group_info_dir.keys()): if key not in group_ids: @@ -164,9 +170,9 @@ async def get_group_info(group_ids=0, info_type='group_name'): async def get_authed_group_list(): - ''' + """ 获取已授权的群 - ''' + """ authed_group_list = [] group_name_dir = await get_group_info() @@ -177,10 +183,11 @@ async def get_authed_group_list(): return authed_group_list +# noinspection ALL async def get_group_list_all(): - ''' + """ 获取所有群, 无论授权与否, 返回为原始类型(列表) - ''' + """ bot = nonebot.get_bot() self_ids = bot._wsr_api_clients.keys() for sid in self_ids: @@ -188,15 +195,16 @@ async def get_group_list_all(): return group_list +# noinspection ALL async def process_group_msg(gid, expiration, title: str = '', end='', group_name_sp=''): - ''' + """ 把查询消息处理为固定的格式 \n 第一行为额外提醒信息(例如充值成功)\n 群号:<群号> \n 群名:<群名> \n 授权到期:<到期时间> \n 部分情况下, 可以通过指定群组名的方式来减少对API的调用次数(我并不知道这个对性能是否有大影响) - ''' + """ if group_name_sp == '': bot = nonebot.get_bot() self_ids = bot._wsr_api_clients.keys() @@ -204,7 +212,8 @@ async def process_group_msg(gid, expiration, title: str = '', end='', group_name try: group_info = await bot.get_group_info(self_id=sid, group_id=gid) group_name = group_info['group_name'] - except: + except Exception as e: + print(e) group_name = '未知(Bot未加入此群)' else: group_name = group_name_sp @@ -216,9 +225,9 @@ async def process_group_msg(gid, expiration, title: str = '', end='', group_name async def new_group_check(gid): - ''' + """ 加入新群时检查此群是否符合条件,如果有试用期则会自动添加试用期授权时间, 同时添加试用标志 - ''' + """ if gid in group_dict: time_left = group_dict[gid] - datetime.now() @@ -240,19 +249,20 @@ async def new_group_check(gid): async def transfer_group(old_gid, new_gid): - ''' + """ 转移授权,新群如果已经有时长了则在现有时长上增加 - ''' + """ today = datetime.now() left_time = group_dict[old_gid] - today if old_gid in group_dict else timedelta(days=0) group_dict[new_gid] = left_time + (group_dict[new_gid] if new_gid in group_dict else today) group_dict.pop(old_gid) await flush_group() + async def gun_group(group_id, reason='管理员操作'): - ''' + """ 退出群聊, 同时会发送消息, 说明退群原因 - ''' + """ gid = group_id msg = config.GROUP_LEAVE_MSG msg += reason @@ -269,9 +279,9 @@ async def gun_group(group_id, reason='管理员操作'): async def notify_group(group_id, txt): - ''' + """ 发送自定义提醒广播,顺带解决了HoshinoBot和Yobot的广播短板 - ''' + """ gid = group_id try: await nonebot.get_bot().send_group_msg(group_id=gid, message=txt) @@ -279,16 +289,17 @@ async def notify_group(group_id, txt): return False return True + async def notify_master(txt): - ''' + """ 通知主人 - ''' + """ try: await nonebot.get_bot().send_private_msg(user_id=SUPERUSERS[0], message=txt) except nonebot.CQHttpError: return False return True - + def time_now(): return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) @@ -305,9 +316,9 @@ def time_now(): def log(info, log_type='debug'): - ''' + """ 记录日志, 保存位置为HoshinoBot/logs/authMS.log - ''' + """ if not config.LOG: return if not config.DEBUG and log_type not in LOG_LIST: @@ -315,14 +326,15 @@ def log(info, log_type='debug'): return file_name = 'log/authMS.log' - with open(file_name, 'a', encoding='utf-8') as l: - l.writelines(f"[{time_now()}]") - l.writelines(info) - l.writelines('\n') + with open(file_name, 'a', encoding='utf-8') as f: + f.writelines(f"[{time_now()}]") + f.writelines(info) + f.writelines('\n') +# noinspection ALL def allowlist(group_id, operator='none', nocheck='no_number_check'): - ''' + """ operator------ none: 检查一个群或人是否在白名单中, 不在时返回值为not in add: 增加白名单 @@ -332,7 +344,7 @@ def allowlist(group_id, operator='none', nocheck='no_number_check'): no_number_check: 不检查人数 no_auth_check: 不检查授权(永久有效) no_check: 全部不检查 - ''' + """ ALLOWLIST_PATH = os.path.expanduser('~/.hoshino/authMS/allowlist.json') if os.path.exists(ALLOWLIST_PATH): @@ -374,8 +386,9 @@ def allowlist(group_id, operator='none', nocheck='no_number_check'): # 这个没写完别看了------------------------------------------- +# noinspection ALL async def set_block_list(group_id, operator_id, reason='no reason'): - ''' + """ 将一个群添加到黑名单, 目前仅本地拉黑, 未来可能支持......算了不画饼了 可以重复拉黑, 以更新reason @@ -387,7 +400,7 @@ async def set_block_list(group_id, operator_id, reason='no reason'): group_info: 直接传入bot.get_group_info()返回的原始信息 group_member_list: 直接传入bot.get_group_member_list()返回的群所有成员信息 operator_name: 操作者昵称 - ''' + """ BLOCKLIST_PATH = os.path.expanduser('~/.hoshino/authMS/blocklist.json') @@ -410,12 +423,13 @@ async def set_block_list(group_id, operator_id, reason='no reason'): pass +# noinspection ALL def get_list(list_type='allowlist'): - ''' + """ list_type可选blocklist和allowlist 保存位置: ~./.hoshino/authMS/blocklist.json和allowlist.json 为保持兼容性, 会将所有键值转化为int - ''' + """ LIST_PATH = os.path.expanduser(f'~/.hoshino/authMS/{list_type}.json') if os.path.exists(LIST_PATH): with open(LIST_PATH, 'r', encoding='utf-8') as rf: diff --git a/web_activate.py b/web_activate.py index 0538296..8a137fc 100644 --- a/web_activate.py +++ b/web_activate.py @@ -1,13 +1,18 @@ -from quart import request, Blueprint, jsonify, render_template - import nonebot - +from quart import request, Blueprint, render_template +import os from . import util +runtime_path = os.path.dirname(__file__) +web_path = os.path.join(runtime_path, "activate") - -activate = Blueprint('activate', __name__, url_prefix='/activate', template_folder="./activate" - , static_folder='./activate', static_url_path='') +activate = Blueprint( + 'activate', __name__, + url_prefix='/activate', + template_folder=web_path, + static_folder=web_path, + static_url_path='' +) bot = nonebot.get_bot() app = bot.server_app @@ -22,6 +27,6 @@ async def activate_group(): result = await util.reg_group(group_id, key) if result: log_info = f'卡密{key}通过网页被激活\n为群聊{group_id}增加了{days}天授权时长' - util.log(log_info,'card_use') + util.log(log_info, 'card_use') await util.notify_master(log_info) return await render_template("activate.html") diff --git a/web_server.py b/web_server.py index 9787003..a8c5726 100644 --- a/web_server.py +++ b/web_server.py @@ -1,18 +1,19 @@ -from hoshino import Service, priv -from quart import request, Blueprint, jsonify, render_template - -import string -import random import nonebot -import hoshino - -from datetime import * +from quart import request, Blueprint, jsonify, render_template +import os from . import util from .constant import config +runtime_path = os.path.dirname(__file__) +web_path = os.path.join(runtime_path, "vue") -auth = Blueprint('auth', __name__, url_prefix='/auth', template_folder="./vue", static_folder='./vue', - static_url_path='') +auth = Blueprint( + 'auth', __name__, + url_prefix='/auth', + template_folder=web_path, + static_folder=web_path, + static_url_path='' +) bot = nonebot.get_bot() app = bot.server_app manage_password = config.PASSWORD # 管理密码请在authMS.py中修改