async def reload_ef(bot: Bot, event: CQEvent): if event.user_id not in salmon.configs.SUPERUSERS: util.log(f'{event.user_id}尝试刷新事件过滤器, 已拒绝') await reload_filter.finish('只有主人才能刷新事件过滤器') return await util.flush_group() await reload_filter.finish('刷新成功!')
async def group_change_chat(bot: Bot, event: CQEvent): if not event.get_plaintext(): await trans_auth.finish('请发送“转移授权 旧群群号*新群群号”来进行转移') origin = event.get_plaintext().strip() pattern = re.compile(r'^(\d{5,15})\*(\d{5,15})$') m = pattern.match(origin) if m is None: await trans_auth.finish( '格式或群号错误\n请发送“转移授权 旧群群号*新群群号”来转移群授权时长\n如果新群已经授权,则会增加对应时长') old_gid = int(m.group(1)) new_gid = int(m.group(2)) if event.user_id not in salmon.configs.SUPERUSERS: util.log(f'{event.user_id}尝试转移授权{old_gid}到{new_gid}, 已拒绝') trans_auth.finish('权限不足') gtime_old = util.check_group(old_gid) if gtime_old == 0: await trans_auth.finish('旧群无授权, 不可进行转移') if old_gid == new_gid: await trans_auth.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') await notify_group(group_id=old_gid, txt=f'已转移本群授权时长至其他群。') await trans_auth.finish(msg)
async def check_number(group_id=0): ''' 检查所有群的成员数量是否符合要求, 当传入group_id时则检查传入的群 ''' if group_id == 0: gnums = await util.get_group_info(info_type='member_count') else: __gid = group_id gnums = await util.get_group_info(group_ids=__gid, info_type='member_count') for gid in gnums: if gnums[gid] > config.MAX_GROUP_NUM: # 人数超过, 检测是否在白名单 rt_code = util.allowlist(gid) if rt_code == 'not in' or rt_code == 'no_check_auth': util.log(f'群{gid}人数超过设定值, 当前人数{gnums[gid]}, 白名单状态{rt_code}', 'number_check') if group_id == 0: # 检查全部群的情况, 可以自动退出 if config.AUTO_LEAVE: await util.gun_group(group_id=gid, reason='群人数超过管理员设定的最大值') else: await util.notify_group(group_id=gid, txt='群人数超过管理员设定的最大值, 请联系管理员') else: # 检查单个群的情况, 只通知而不自动退出, 等到下次计划任务时再退出 await util.notify_group(group_id=gid, txt='群人数超过管理员设定的最大值, 请联系管理员') return 'overflow' return None
async def add_time_all_rec(bot: Bot, event: CQEvent, state: T_State): if event.user_id not in salmon.configs.SUPERUSERS: util.log(f'{event.user_id}尝试批量授权, 已拒绝') await all_add.finish('权限不足') days = event.get_plaintext().strip() if days: state['days'] = days
async def friend_approve(bot: Bot, event: FriendRequestEvent): if config.FRIEND_APPROVE: util.log(f'已自动接受来自{event.user_id}的好友请求', 'friend_add') salmon.logger.info(f'已自动接受来自{event.user_id}的好友请求') await bot.set_friend_add_request(flag=event.flag, approve=True) else: util.log(f'收到来自{event.user_id}的好友请求', 'friend_add') salmon.logger.info(f'收到来自{event.user_id}的好友请求')
async def no_auth_check_chat(bot: Bot, event: CQEvent, state: T_State): gid = int(state['gid']) if event.user_id not in salmon.configs.SUPERUSERS: util.log(f'{event.user_id}尝试为群{gid}设置不检查授权, 已拒绝') await no_auth_check.finish('权限不足') util.allowlist(group_id=gid, operator='add', nocheck='no_auth_check') util.log(f'管理员{event.user_id}已将群{gid}添加至白名单, 类型为不检查授权') await notify_group(group_id=gid, txt='已添加本群为白名单,将不会检查本群授权是否过期') await no_auth_check.finish(f'已将群{gid}添加至白名单, 类型为不检查授权')
async def add_time_all_chat(bot: Bot, event: CQEvent, state: T_State): try: days = int(state['days']) except: await all_add.finish('Invalid input.') authed_group_list = await util.get_authed_group_list() for ginfo in authed_group_list: await util.change_authed_time(ginfo['gid'], days) util.log(f'已为所有群授权增加{days}天') await all_add.finish(f'已为所有群授权增加{days}天')
async def no_check_chat(bot: Bot, event: CQEvent, state: T_State): try: gid = int(state['gid']) except: await no_check.finish('Invalid input.') if event.user_id not in salmon.configs.SUPERUSERS: util.log(f'{event.user_id}尝试为群{gid}添加白名单, 已拒绝') await no_check.finish('权限不足') util.allowlist(group_id=gid, operator='add', nocheck='no_check') util.log(f'管理员{event.user_id}已将群{gid}添加至白名单, 类型为全部不检查') await notify_group(group_id=gid, txt='已添加本群为白名单,将不会检查本群授权以及人数上限') await no_check.finish(f'已将群{gid}添加至白名单, 类型为全部不检查')
async def remove_allowlist_chat(bot: Bot, event: CQEvent, state: T_State): try: gid = int(state['gid']) except: await remove_allowlist.finish('Invalid input.') if event.user_id not in salmon.configs.SUPERUSERS: util.log(f'{event.user_id}尝试移除白名单{gid}, 已拒绝') await remove_allowlist.finish('权限不足') re_code = util.allowlist(group_id=gid, operator='remove') if re_code == 'not in': await remove_allowlist.finish(f'群{gid}不在白名单中') await notify_group(group_id=gid, txt='已移除本群的白名单') util.log(f'已将群{gid}移出白名单') await remove_allowlist.finish(f'已将群{gid}移出白名单')
async def add_time_chat(bot: Bot, event: CQEvent): origin = event.get_plaintext().strip() pattern = re.compile(r'^(\d{5,15})([+-]\d{1,5})$') m = pattern.match(origin) if m is None: await change_auth.finish('请发送“授权 群号±时长”来进行指定群的授权') gid = int(m.group(1)) days = int(m.group(2)) if event.user_id not in salmon.configs.SUPERUSERS: util.log(f'{event.user_id}尝试为群{gid}增加{days}天授权, 已拒绝') await change_auth.finish('权限不足') result = await util.change_authed_time(gid, days) msg = await util.process_group_msg(gid, result, title='变更成功, 变更后的群授权信息:\n') await notify_group(group_id=gid, txt=f'已为本群增加{days}天授权时长。\n可在群内发送【查询授权】来查看授权时间。') await change_auth.finish(msg)
async def auth_status_chat(bot: Bot, event: CQEvent): if event.user_id not in salmon.configs.SUPERUSERS: util.log(f'{event.user_id}尝试查看授权状态, 已拒绝') await auth_status.finish('权限不足') if isinstance(event, GroupMessageEvent): await auth_list.finish('不支持群聊查看') elif isinstance(event, PrivateMessageEvent): sid = event.self_id sgl = set(g['group_id'] for g in await bot.get_group_list(self_id=sid)) frl = set(f['user_id'] for f in await bot.get_friend_list(self_id=sid)) # 直接从service里抄了, 面向cv编程才是真 gp_num = len(sgl) fr_num = len(frl) agp_num = len(await util.get_authed_group_list()) msg = f'Bot账号:{sid}\n所在群数:{gp_num}\n好友数:{fr_num}\n授权群数:{agp_num}' await auth_status.finish(msg)
async def group_list_chat(bot: Bot, event: CQEvent): ''' 此指令获得的是, 所有已经获得授权的群, 其中一些群可能Bot并没有加入 分页显示, 请在authMS.py中配置 ''' if event.user_id not in salmon.configs.SUPERUSERS: util.log(f'{event.user_id}尝试查看授权列表, 已拒绝') await auth_list.finish('只有主人才能查看授权列表哦') if isinstance(event, GroupMessageEvent): # 群聊查看授权列表你也是个小天才 await auth_list.finish('不支持群聊查看') elif isinstance(event, PrivateMessageEvent): if not event.get_plaintext().split(): # 无其他参数默认第一页 page = 1 else: page = int(event.get_plaintext().strip()) msg = '======授权列表======\n' authed_group_list = await util.get_authed_group_list() length = len(authed_group_list) groups_in_page = config.GROUPS_IN_PAGE pages_all = ceil(length / groups_in_page) # 向上取整 if page > pages_all: await auth_list.finish(f'页码错误, 当前共有授权信息{length}条, 共{pages_all}页') if page <= 0: await auth_list.finish('请输入正确的页码') i = 0 for item in authed_group_list: i = i + 1 if i < (page - 1) * groups_in_page + 1 or i > page * groups_in_page: continue gid = int(item['gid']) g_time = util.check_group(gid) msg_new = await util.process_group_msg( gid, g_time, title=f'第{i}条信息\n', end='\n\n', group_name_sp=item['groupName']) msg += msg_new msg += f'第{page}页, 共{pages_all}页\n发送授权列表+页码以查询其他页' await auth_list.finish(msg)
async def remove_auth_chat(bot: Bot, event: CQEvent, state: T_State): try: gid = int(state['gid']) except: await remove_auth.finish('Invalid input.') if event.user_id not in salmon.configs.SUPERUSERS: util.log(f'{event.user_id}尝试为群{gid}清除授权, 已拒绝') await remove_auth.finish('权限不足') time_left = util.check_group(gid) if not time_left: await remove_auth.finish('此群未获得授权') msg = await util.process_group_msg(gid=gid, expiration=time_left, title='已移除授权,原授权信息如下\n') await util.change_authed_time(gid=gid, operate='clear') if config.AUTO_LEAVE: await util.gun_group(group_id=gid, reason='本群已被移除授权,具体事项请联系维护') msg += '\n已尝试退出该群聊' await remove_auth.finish(msg)
async def get_allowlist_chat(bot: Bot, event: CQEvent): if event.user_id not in salmon.configs.SUPERUSERS: util.log(f'{event.user_id}尝试查看白名单, 已拒绝') await get_allowlist.finish('权限不足') if isinstance(event, GroupMessageEvent): await get_allowlist.finish('不支持群聊查看') elif isinstance(event, PrivateMessageEvent): allow_list = util.get_list(list_type='allowlist') msg = '白名单信息\n' gids = list(allow_list.keys()) gname_dir = await util.get_group_info(group_ids=gids, info_type='group_name') # 考虑到一般没有那么多白名单, 因此此处不做分页 i = 1 for gid in gname_dir: msg += f'第{i}条: 群号{gid}\n' gname = gname_dir[gid] gnocheck = allow_list[gid] msg += f'群名:{gname}\n类型:{gnocheck}\n\n' i = i + 1 await get_allowlist.finish(msg)
async def approve_group_invite_auto(bot: Bot, event: GroupIncreaseNoticeEvent): ''' 被邀请加入50人以下群时会自动接受, 此时获得的事件类型为通知而非邀请. 无法处理拒绝入群的邀请, 应当使用退群(如果开启了自动退群的话) ''' if not event.is_tome(): return gid = event.group_id rt = await check_number(gid) if rt == 'overflow': # 人数超标不自动试用, 考虑到风控, 也不会立刻退群, 而是在下一次自动检查时退群 new_group_auth = 'no trial' else: new_group_auth = await util.new_group_check(gid) if new_group_auth == 'expired' or new_group_auth == 'no trial': await util.notify_group(group_id=gid, txt='本群无授权或授权或已过期, 请联系维护') util.log(f'成功加入群{gid}中,该群授权状态{new_group_auth}, 将在下次计划任务时自动退出', 'group_leave') salmon.logger.info(f'成功加入群{gid}中,该群授权状态{new_group_auth}, 将在下次计划任务时自动退出') elif new_group_auth == 'authed' or new_group_auth == 'trial': await asyncio.sleep(5) # 别发太快了 # 避免重复try await util.notify_group(group_id=gid, txt=config.NEW_GROUP_MSG) util.log(f'成功加入群{gid}中, 该群授权状态{new_group_auth}', 'group_add') salmon.logger.info(f'成功加入群{gid}中, 该群授权状态{new_group_auth}')
async def handle_group_invite(bot: Bot, event: GroupRequestEvent): ''' 自动处理入群邀请 适用于50人以上的邀请的情况, 50人以下请参见下一条函数 ''' if not config.ENABLE_AUTH: # 配置ENABLE_AUTH为0, 则授权系统不起作用, 不会自动通过加群邀请 return if event.sub_type == 'invite': gid = event.group_id new_group_auth = await util.new_group_check(gid) if event.user_id not in configs.SUPERUSERS: if new_group_auth == 'expired' or new_group_auth == 'no trial': await bot.set_group_add_request(flag=event.flag, sub_type=event.sub_type, approve=False, reason='邀请进入无授权群请联系维护组') util.log(f'接受到加群邀请, 群号{gid}授权状态{new_group_auth}, 拒绝加入', 'group_add') elif new_group_auth == 'authed' or new_group_auth == 'trial': await bot.set_group_add_request(flag=event.flag, sub_type=event.sub_type, approve=True) util.log(f'接受到加群邀请, 群号{gid}授权状态{new_group_auth}, 同意加入', 'group_add') else: await bot.set_group_add_request(flag=event.flag, sub_type=event.sub_type, approve=True) util.log(f'维护邀请入群, 群号{gid}授权状态{new_group_auth}, 同意加入', 'group_add') elif event.sub_type == 'add': cfg = configs.groupmaster.join_approve gid = event.group_id if gid not in cfg: return for k in cfg[gid].get('keywords', []): if k in event.comment: await bot.set_group_add_request(flag=event.flag, sub_type=event.sub_type, approve=True) return if cfg[gid].get('reject_when_not_match', False): await bot.set_group_add_request(flag=event.flag, sub_type=event.sub_type, approve=False) return
async def check_auth(): ''' 检查所有已加入群的授权状态和人数 ''' await check_number() # 独立地检查一次所有群的人数是否超标 group_info_all = await util.get_group_list_all() for group in group_info_all: gid = group['group_id'] if gid in group_dict: util.log(f'正在检查群{gid}的授权......') # 此群已有授权或曾有授权, 检查是否过期 time_left = group_dict[gid] - datetime.now() days_left = time_left.days rt_code = util.allowlist(gid) if rt_code == 'no_check' or rt_code == 'no_auth_check': # 在白名单, 并不会影响过期事件 continue if time_left.total_seconds() <= 0: # 已过期, 检查是否在白名单中 if config.AUTO_LEAVE and time_left.total_seconds() < -config.LEAVE_AFTER_DAYS * 86400: # 自动退群且已过期超过LEAVE_AFTER_DAYS天, 如果设置LEAVE_AFTER_DAYS为0则立刻退群 await util.gun_group(group_id=gid, reason='授权过期') util.log(f'群{gid}授权过期,已自动退群', 'group_leave') else: # 不自动退群, 只发消息提醒 t_sp = '【提醒】本群授权已过期\n' e_sp = '若需要继续使用请联系bot维护' gname_sp = group['group_name'] msg_expired = await util.process_group_msg(gid=gid, expiration=group_dict[gid], title=t_sp, end=e_sp, group_name_sp=gname_sp) try: for bot in salmon.get_bot_list(): await bot.send_group_msg(group_id=gid, message=msg_expired) except Exception as e: 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: # 将要过期 msg_remind = await util.process_group_msg( gid=gid, expiration=group_dict[gid], title=f'【提醒】本群的授权已不足{days_left + 1}天\n', end='\n若需要继续使用请联系bot维护', group_name_sp=group['group_name']) try: await bot.send_group_msg(group_id=gid, message=msg_remind) except Exception as e: salmon.logger.error(f'向群{gid}发生到期提醒消息时发生错误{type(e)}') util.log(f'群{gid}的授权不足{days_left + 1}天') elif gid not in trial_list: # 正常情况下, 无论是50人以上群还是50人以下群, 都需要经过机器人同意或检查 # 但是!如果机器人掉线期间被拉进群试用, 将无法处理试用, 因此有了这部分憨批代码 if not config.NEW_GROUP_DAYS and config.AUTO_LEAVE: # 无新群试用机制,直接退群 await util.gun_group(group_id=gid, reason='无授权') util.log(f'发现无记录而被拉入的新群{gid}, 已退出此群', 'group_leave') else: await util.new_group_check(gid) util.log(f'发现无记录而被拉入的新群{gid}, 已开始试用', 'group_add')