From 2ee0d9084a67582a4e99aff84990baf45e084c97 Mon Sep 17 00:00:00 2001 From: musnow Date: Sat, 25 Feb 2023 21:20:04 +0800 Subject: [PATCH 01/24] feat(apiToken): modify save_token_files in token_ck fix(api): modify /shop-url to /shop --- code/api.py | 8 ++++---- code/main.py | 7 ++++--- code/utils/api/ApiHandler.py | 2 +- code/utils/api/ApiToken.py | 5 +++-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/code/api.py b/code/api.py index 29e1148..027dccb 100644 --- a/code/api.py +++ b/code/api.py @@ -15,9 +15,9 @@ def hello_world(request): # put application's code here return web.Response(body=json.dumps( { 'code': 0, - 'message': 'Hello! Use path /shop-url or /shop-img to get valorant daily shop', + 'message': 'Hello! Use path /shop or /shop-img to get valorant daily shop', 'info': - '在path后添加/shop-img或者/shop-url来获取每日商店,前者会直接跳转,后者返回一个带图片url的json。示例: /shop-url?account=Riot账户&passwd=Riot密码&img_src=可选参数,自定义背景图', + '在path后添加/shop-img或者/shop来获取每日商店,前者会直接跳转,后者返回一个带图片url的json。示例: /shop?account=Riot账户&passwd=Riot密码&img_src=可选参数,自定义背景图', 'docs': 'https://github.com/Aewait/Kook-Valorant-Bot/blob/main/docs/valorant-shop-img-api.md' }, indent=2, @@ -37,7 +37,7 @@ async def get_dailshop_img(request): content_type='application/json',status=200) except: err_cur = traceback.format_exc() - print(f"[{GetTime()}] [Api] ERR in /shop-url\n{err_cur}") + print(f"[{GetTime()}] [Api] ERR in /shop\n{err_cur}") return web.Response(body=json.dumps( { 'code': 200, @@ -90,7 +90,7 @@ async def get_dailshop_img(request): content_type='application/json',status=200) except: err_cur = traceback.format_exc() - print(f"[{GetTime()}] [Api] ERR in /shop-url\n{err_cur}") + print(f"[{GetTime()}] [Api] ERR in /shop\n{err_cur}") return web.Response(body=json.dumps( { 'code': 200, diff --git a/code/main.py b/code/main.py index 6b4a319..1f17e45 100644 --- a/code/main.py +++ b/code/main.py @@ -77,7 +77,7 @@ async def Save_File_Task(): @bot.command(name='kill') -async def KillBot(msg: Message,num:str, *arg): +async def KillBot(msg: Message,num:str='124124', *arg): logging(msg) if msg.author_id == master_id and int(num)==config['no']: # 保存所有文件 @@ -1278,11 +1278,12 @@ async def get_daily_shop(msg: Message, *arg): # 每天8点bot遍历完之后会把vip的商店结果图存起来 shop_path = f"./log/img_temp_vip/shop/{msg.author_id}.png" # 如果是vip而且path存在,背景图/登录用户没有更改过,图片缓存时间正确 - if is_vip and (os.path.exists(shop_path)) and is_CacheLatest(msg.author_id): + if is_vip and is_CacheLatest(msg.author_id): upload_flag = False #有缓存图,直接使用本地已有链接 dailyshop_img_src = VipShopBgDict['cache'][msg.author_id]['cache_img'] - elif is_vip and (msg.author_id in VipShopBgDict['bg']): #本地缓存路径不存在,或者缓存过期 + elif is_vip: # 本地缓存路径不存在,或者缓存过期 play_currency = await fetch_vp_rp_dict(userdict) #获取用户的vp和rp + # 如果没有设置背景图,那就设置为err background_img = ('err' if msg.author_id not in VipShopBgDict['bg'] else VipShopBgDict['bg'][msg.author_id]["background"][0]) img_ret = await get_shop_img_169(list_shop, diff --git a/code/utils/api/ApiHandler.py b/code/utils/api/ApiHandler.py index bb196c3..8676ba8 100644 --- a/code/utils/api/ApiHandler.py +++ b/code/utils/api/ApiHandler.py @@ -199,7 +199,7 @@ async def tfa_code_requeset(request): return { 'code': 200, 'message': 'Riot account not in Api2faDict', - 'info': '拳头账户不在dict中,请先请求/shop-img或/shop-url接口' + 'info': '拳头账户不在dict中,请先请求/shop-img或/shop接口' } key = Api2faDict['data'][account] diff --git a/code/utils/api/ApiToken.py b/code/utils/api/ApiToken.py index 8e07758..82566c6 100644 --- a/code/utils/api/ApiToken.py +++ b/code/utils/api/ApiToken.py @@ -80,6 +80,7 @@ async def token_ck(token: str): if ApiTokenDict['data'][token]['od_time'] == 0: od_time = time.time() + ApiTokenDict['data'][token]['days'] * 86400 ApiTokenDict['data'][token]['od_time'] = od_time + save_token_files("token init use") # 用户的token是否过期? if time.time() > ApiTokenDict['data'][token]['od_time']: # 过期了,删除该token @@ -110,7 +111,7 @@ async def check_token_rate(token: str): if ApiTokenDict['data'][token]['rate_nums'] == 0: ApiTokenDict['data'][token]['rate_time'] = cur_time ApiTokenDict['data'][token]['rate_nums'] = 1 - save_token_files("token init use") + # save_token_files("token init use") return {'status': True, 'message': 'first use', 'info': '一切正常'} # rate_nums不为0,代表检测周期内有调用 elif time_diff <= TOKEN_RATE_TIME: # 和上次调用的时间差在60s以内 @@ -121,7 +122,7 @@ async def check_token_rate(token: str): ApiTokenDict['data'][token]['rate_nums'] += 1 return {'status': True, 'message': 'time_diff <= 60, in rate', 'info': '一切正常'} else: # 时间超过60s - save_token_files("rate check") + # save_token_files("rate check") # 重置rate_time为当前时间,重置计数器(开始新一轮速率检测) ApiTokenDict['data'][token]['rate_time'] = cur_time ApiTokenDict['data'][token]['rate_nums'] = 0 From 423dc2d9653358a706fdc613cdd8878727067725 Mon Sep 17 00:00:00 2001 From: musnows Date: Sat, 25 Feb 2023 16:15:31 +0000 Subject: [PATCH 02/24] feat(ShopRate): add ShopCache with md5 for 1-1 img --- code/main.py | 32 ++++++++----- code/utils/ShopRate.py | 91 +++++++++++++++++++++++++++++++++++- code/utils/api/ApiHandler.py | 40 +++++++++++----- 3 files changed, 139 insertions(+), 24 deletions(-) diff --git a/code/main.py b/code/main.py index 1f17e45..0170396 100644 --- a/code/main.py +++ b/code/main.py @@ -1275,8 +1275,8 @@ async def get_daily_shop(msg: Message, *arg): is_vip = await vip_ck(msg.author_id) #判断用户是否为VIP img_ret = {'status': True, 'value': None} upload_flag = True - # 每天8点bot遍历完之后会把vip的商店结果图存起来 - shop_path = f"./log/img_temp_vip/shop/{msg.author_id}.png" + # 初始化为一个展示错误的图片 + dailyshop_img_src = "https://img.kookapp.cn/assets/2023-02/5UxA8W06B70e803m.png" # 如果是vip而且path存在,背景图/登录用户没有更改过,图片缓存时间正确 if is_vip and is_CacheLatest(msg.author_id): upload_flag = False #有缓存图,直接使用本地已有链接 @@ -1290,19 +1290,26 @@ async def get_daily_shop(msg: Message, *arg): vp=play_currency['vp'], rp=play_currency['rp'], bg_img_src=background_img) - else: # 普通用户/没有自定义图片的vip用户 - img_ret = await get_shop_img_11(list_shop) - - if img_ret['status']: #true + else: # 普通用户 + # 判断是否有缓存命中 + cache_ret = await ShopRate.query_ShopCache(skinlist=list_shop) + if not cache_ret['status']: # 缓存没有命中 + img_ret = await get_shop_img_11(list_shop) + else: # 命中 + upload_flag = False + dailyshop_img_src = cache_ret['img_url'] + + # img_ret 代表是否画图成功,如果是缓存命中,也当成功处理 + if img_ret['status']: bg = img_ret['value'] #获取图片 - else: #出现背景图片违规或其他问题 + else: # 出现背景图片违规或其他问题 await msg.reply(img_ret['value']) print(f"[GetShopImg] Au:{msg.author_id} {img_ret['value']}") return # 获取图片成功,打印画图耗时 - log_time += f"- [Drawing] {format(time.time() - draw_time,'.4f')} - [Au] {msg.author_id}" - print(log_time) + print(log_time+f"- [Drawing] {format(time.time() - draw_time,'.4f')} - [Au] {msg.author_id}") + # 判断是否需要上传,false不需要 if upload_flag: imgByteArr = io.BytesIO() bg.save(imgByteArr, format='PNG') @@ -1313,10 +1320,13 @@ async def get_daily_shop(msg: Message, *arg): VipShopBgDict['bg'][msg.author_id]['status'] = True # 设置商店图片缓存+图片缓存的时间 VipShopBgDict['cache'][msg.author_id] = {'cache_img': dailyshop_img_src, 'cache_time': time.time()} + else: # 非vip,更新缓存 + await ShopRate.update_ShopCache(skinlist=list_shop,img_url=dailyshop_img_src) + # 结束shop的总计时,结果为浮点数,保留两位小数 shop_using_time = format(time.perf_counter() - start, '.2f') - # 商店的图片 + # 商店的图片 卡片 cm = CardMessage() c = Card(color='#fb4b57') c.append(Module.Header(f"玩家 {player_gamename} 的每日商店!")) @@ -1324,7 +1334,7 @@ async def get_daily_shop(msg: Message, *arg): c.append(Module.Container(Element.Image(src=dailyshop_img_src))) cm.append(c) - #皮肤评分和评价,用户不在rate_err_user里面才显示(在评论中发表违规言论的用户) + # 皮肤评分和评价卡片,用户不在rate_err_user里面才显示(在评论中发表违规言论的用户) if not check_rate_err_user(msg.author_id): cm = await ShopRate.get_shop_rate_cm(list_shop, msg.author_id, cm=cm) end = time.perf_counter() #计算获取评分的时间 diff --git a/code/utils/ShopRate.py b/code/utils/ShopRate.py index 18f01a8..9755032 100644 --- a/code/utils/ShopRate.py +++ b/code/utils/ShopRate.py @@ -6,7 +6,7 @@ # 皮肤的评价 from utils.valorant import Val -from utils.FileManage import config,SkinRateDict +from utils.FileManage import config,SkinRateDict,GetTime leancloud.init(config["leancloud"]["appid"], master_key=config["leancloud"]["master_key"]) PLATFORM = "kook" @@ -379,4 +379,91 @@ async def remove_UserRate(skin_uuid:str,user_id:str): objlist[0].destroy() return True - return False \ No newline at end of file + return False + +#########################################hash skin list############################################### + +import hashlib + +# 生成字符串的MD5值 +def md5(content:str=None): + """generate md5 for string + """ + if content is None: + return '' + md5gen = hashlib.md5() + md5gen.update(content.encode()) + md5code = md5gen.hexdigest() + md5gen = None + return md5code + + +# 生成字符串的SHA256值 +def sha256(content:str=None): + if content is None: + return '' + sha256gen = hashlib.sha256() + sha256gen.update(content.encode()) + sha256code = sha256gen.hexdigest() + sha256gen = None + return sha256code + +# 生成skinlist的md5 +def get_skinlist_md5(skinlist:list): + """Args: skinlist with 4 skin_uuid\n + Return: md5(md5+sha) str + """ + skinlist = sorted(skinlist) # 排序 + # 将uuid拼接 + strlist = "=".join(i for i in skinlist) + md5Ret = md5(strlist) # 计算md5 + shaRet = sha256(strlist) # 计算sha256 + return md5(md5Ret+shaRet) # 两个一起还撞车,买彩票去吧 + +# 判断皮肤的值是否有缓存 +async def query_ShopCache(skinlist:list): + """Args: skinlist with 4 skin_uuid\n + Info: this def only used by none vip shop img + + Return:{ + "status": True/False, + "img_url": shop img url (will be empty when status False) + } + """ + md5Ret = get_skinlist_md5(skinlist) + ret = { "status": False,"img_url":""} + query = leancloud.Query('ShopCache') + query.equal_to('md5',md5Ret) # 查找md5值相同的元素 + objlist = query.find() + if len(objlist) > 0: #找到了 + ret['img_url'] = objlist[0].get('imgUrl') + ret['status'] = True + print(f"[{GetTime()}] ShopCache hit! [{md5Ret}]") + + return ret + +# 缓存皮肤(先判断出来没有再操作) +async def update_ShopCache(skinlist:list,img_url:str): + """md5(skinlist), cache imgurl to leancloud + """ + md5Ret = get_skinlist_md5(skinlist) + ShopCache = leancloud.Object.extend('ShopCache') + query = ShopCache.query + query.equal_to('md5',md5Ret) # 查找md5值相同的元素 + objlist = query.find() + obj = ShopCache() + retBool = True + if len(objlist) > 0: #找到了 + dbSkinlist = objlist[0].get('skinList') + if skinlist == dbSkinlist: + return True # 已经有了还缓存什么啊 + else: # md5撞车 + obj = objlist[0] # 赋值 + retBool = False + # 没找到或者list不相同(md5撞车了),新建并保存 + obj.set('md5',md5Ret) + obj.set('skinList',skinlist) + obj.set('imgUrl',img_url) + obj.save() + print(f"[{GetTime()}] update_ShopCache [{md5Ret}]") + return retBool \ No newline at end of file diff --git a/code/utils/api/ApiHandler.py b/code/utils/api/ApiHandler.py index 8676ba8..3cfd6ac 100644 --- a/code/utils/api/ApiHandler.py +++ b/code/utils/api/ApiHandler.py @@ -2,14 +2,13 @@ import time import threading import traceback -# import requests -# import asyncio + from utils.valorant.EzAuth import EzAuthExp, auth2fa, auth2faWait, Get2faWait_Key, User2faCode from utils.api.ApiToken import check_token_rate from utils.Gtime import GetTime from utils.KookApi import kook_create_asset from utils.valorant.Val import fetch_daily_shop, fetch_vp_rp_dict -from utils.ShopImg import get_shop_img_11, get_shop_img_169 +from utils import ShopRate,ShopImg # bot的配置文件 from utils.FileManage import config @@ -19,9 +18,10 @@ # 默认的背景图 img_bak_169 = 'https://img.kookapp.cn/assets/2022-10/KcN5YoR5hC0zk0k0.jpg' img_bak_11 = 'https://img.kookapp.cn/assets/2023-01/lzRKEApuEP0rs0rs.jpg' -# gLock = asyncio.Lock() # 创建一把锁,用于保存文件 + # # 上传到lsky (这个上传很麻烦,lsky只认open打开的图片) +# gLock = asyncio.Lock() # 创建一把锁,用于保存文件 # async def lsky_upload(bg): # await gLock.acquire()# 上锁 # path = "./log/api_img_temp.png" @@ -56,28 +56,46 @@ async def base_img_request(params, list_shop, vp1=0, rp1=0): img_src = img_bak_11 # 默认背景1-1 # 开始画图 + ret = { "status": False,"value":"no need to img draw"} # 初始化ret为不需要画图 + cacheRet = {"status":False,"img_url":"err" } # 是否需要上传图片(false代表需要) start = time.perf_counter() if 'img_ratio' in params and params['img_ratio'] == '1': - ret = await get_shop_img_11(list_shop, bg_img_src=img_src) + # 是1-1的图片,检测有没有使用自定义背景图 + if img_src == img_bak_11: # 没有自定义背景图 + # 检测是否有缓存命中 + cacheRet = await ShopRate.query_ShopCache(list_shop) + # 缓存命中失败(需要画图) + if not cacheRet['status']: + ret = await ShopImg.get_shop_img_11(list_shop, bg_img_src=img_src) else: # 只有16-9的图片需获取vp和r点 - ret = await get_shop_img_169(list_shop, vp=vp1, rp=rp1, bg_img_src=img_src) + ret = await ShopImg.get_shop_img_169(list_shop, vp=vp1, rp=rp1, bg_img_src=img_src) # 打印计时 print(f"[{GetTime()}] [Api imgDraw]", format(time.perf_counter() - start, '.2f')) # 结果为浮点数,保留两位小数 - start = time.perf_counter() + # 开始上传图片 + start = time.perf_counter() # 更新start计时器 + # 判断缓存是否命中 + if cacheRet['status']: # 命中了 + dailyshop_img_src = cacheRet['img_url'] + print(f'[{GetTime()}] [Api imgUrl(cache)] {dailyshop_img_src}') + return {'code': 0, 'message': dailyshop_img_src, 'info': '商店图片获取成功,缓存命中'} + # 缓存没有命中,但是获取画图结果成功 if ret['status']: bg = ret['value'] # 这个值是pil的结果 img_src_ret = await kook_create_asset(api_bot_token, bg) # 上传图片到kook # img_src_ret = await lsky_upload(bg) # 上传图片到lsky - if img_src_ret['code'] == 0: + if img_src_ret['code'] == 0: # 上传图片成功 print(f"[{GetTime()}] [Api] kook_create_asset success {format(time.perf_counter() - start, '.2f')}") dailyshop_img_src = img_src_ret['data']['url'] + # 初始值是err,调用了query_ShopCache失败,返回值更新为空 + if cacheRet['img_url'] != 'err': + await ShopRate.update_ShopCache(skinlist=list_shop,img_url=dailyshop_img_src) print(f'[{GetTime()}] [Api imgUrl] {dailyshop_img_src}') return {'code': 0, 'message': dailyshop_img_src, 'info': '商店图片获取成功'} - else: + else: # 上传图片失败 print(f'[{GetTime()}] [Api] kook_create_asset failed') return {'code': 200, 'message': 'img upload err', 'info': '图片上传错误'} - else: #出现图片违规或者url无法获取 + else: # 出现图片违规或者背景图url无法获取 err_str = ret['value'] print(f'[{GetTime()}] [ERR]', err_str) return {'code': 200, 'message': 'img src err', 'info': '自定义图片获取失败'} @@ -105,7 +123,7 @@ async def img_draw_request(request): return {'code':200,'message':'list_shop len err! should be 4','info':'list_shop长度错误,皮肤数量不为4'} token = params['token'] - print(list_shop) + print(f"[{GetTime()}] [list_shop] {list_shop}") ck_ret = await check_token_rate(token) if not ck_ret['status']: return {'code': 200, 'message': ck_ret['message'], 'info': ck_ret['info']} From f714d0b700644233196d3cc7c7cd13ef03c1b0ee Mon Sep 17 00:00:00 2001 From: musnows Date: Sat, 25 Feb 2023 16:15:31 +0000 Subject: [PATCH 03/24] feat(ShopRate): add ShopCache with md5 for 1-1 img, set acl for user and admin_role --- code/config/config.exp.json | 8 ++- code/main.py | 32 ++++++---- code/utils/ShopRate.py | 112 +++++++++++++++++++++++++++++++++-- code/utils/api/ApiHandler.py | 40 +++++++++---- 4 files changed, 163 insertions(+), 29 deletions(-) diff --git a/code/config/config.exp.json b/code/config/config.exp.json index 423caac..4b0eae7 100644 --- a/code/config/config.exp.json +++ b/code/config/config.exp.json @@ -16,7 +16,11 @@ }, "leancloud":{ "appid":"leancloud数据库的appid(可联系作者,共用皮肤评价数据库)", - "master_key":"leancloud数据库的masterkey" + "appkey":"leancloud数据库的appkey", + "master_key":"leancloud数据库的masterkey", + "user_name":"数据库内置用户id", + "user_pwd":"数据库内置用户密码" }, - "no":1000 + "no":1000, + "platform":"kook" } \ No newline at end of file diff --git a/code/main.py b/code/main.py index 1f17e45..0170396 100644 --- a/code/main.py +++ b/code/main.py @@ -1275,8 +1275,8 @@ async def get_daily_shop(msg: Message, *arg): is_vip = await vip_ck(msg.author_id) #判断用户是否为VIP img_ret = {'status': True, 'value': None} upload_flag = True - # 每天8点bot遍历完之后会把vip的商店结果图存起来 - shop_path = f"./log/img_temp_vip/shop/{msg.author_id}.png" + # 初始化为一个展示错误的图片 + dailyshop_img_src = "https://img.kookapp.cn/assets/2023-02/5UxA8W06B70e803m.png" # 如果是vip而且path存在,背景图/登录用户没有更改过,图片缓存时间正确 if is_vip and is_CacheLatest(msg.author_id): upload_flag = False #有缓存图,直接使用本地已有链接 @@ -1290,19 +1290,26 @@ async def get_daily_shop(msg: Message, *arg): vp=play_currency['vp'], rp=play_currency['rp'], bg_img_src=background_img) - else: # 普通用户/没有自定义图片的vip用户 - img_ret = await get_shop_img_11(list_shop) - - if img_ret['status']: #true + else: # 普通用户 + # 判断是否有缓存命中 + cache_ret = await ShopRate.query_ShopCache(skinlist=list_shop) + if not cache_ret['status']: # 缓存没有命中 + img_ret = await get_shop_img_11(list_shop) + else: # 命中 + upload_flag = False + dailyshop_img_src = cache_ret['img_url'] + + # img_ret 代表是否画图成功,如果是缓存命中,也当成功处理 + if img_ret['status']: bg = img_ret['value'] #获取图片 - else: #出现背景图片违规或其他问题 + else: # 出现背景图片违规或其他问题 await msg.reply(img_ret['value']) print(f"[GetShopImg] Au:{msg.author_id} {img_ret['value']}") return # 获取图片成功,打印画图耗时 - log_time += f"- [Drawing] {format(time.time() - draw_time,'.4f')} - [Au] {msg.author_id}" - print(log_time) + print(log_time+f"- [Drawing] {format(time.time() - draw_time,'.4f')} - [Au] {msg.author_id}") + # 判断是否需要上传,false不需要 if upload_flag: imgByteArr = io.BytesIO() bg.save(imgByteArr, format='PNG') @@ -1313,10 +1320,13 @@ async def get_daily_shop(msg: Message, *arg): VipShopBgDict['bg'][msg.author_id]['status'] = True # 设置商店图片缓存+图片缓存的时间 VipShopBgDict['cache'][msg.author_id] = {'cache_img': dailyshop_img_src, 'cache_time': time.time()} + else: # 非vip,更新缓存 + await ShopRate.update_ShopCache(skinlist=list_shop,img_url=dailyshop_img_src) + # 结束shop的总计时,结果为浮点数,保留两位小数 shop_using_time = format(time.perf_counter() - start, '.2f') - # 商店的图片 + # 商店的图片 卡片 cm = CardMessage() c = Card(color='#fb4b57') c.append(Module.Header(f"玩家 {player_gamename} 的每日商店!")) @@ -1324,7 +1334,7 @@ async def get_daily_shop(msg: Message, *arg): c.append(Module.Container(Element.Image(src=dailyshop_img_src))) cm.append(c) - #皮肤评分和评价,用户不在rate_err_user里面才显示(在评论中发表违规言论的用户) + # 皮肤评分和评价卡片,用户不在rate_err_user里面才显示(在评论中发表违规言论的用户) if not check_rate_err_user(msg.author_id): cm = await ShopRate.get_shop_rate_cm(list_shop, msg.author_id, cm=cm) end = time.perf_counter() #计算获取评分的时间 diff --git a/code/utils/ShopRate.py b/code/utils/ShopRate.py index 18f01a8..4361de3 100644 --- a/code/utils/ShopRate.py +++ b/code/utils/ShopRate.py @@ -4,11 +4,21 @@ import traceback from khl.card import Card, CardMessage, Module, Element, Types -# 皮肤的评价 from utils.valorant import Val -from utils.FileManage import config,SkinRateDict -leancloud.init(config["leancloud"]["appid"], master_key=config["leancloud"]["master_key"]) -PLATFORM = "kook" +from utils.FileManage import config,SkinRateDict,GetTime +PLATFORM = config['platform'] # 平台 + +# 初始化leancloud +leancloud.init(config["leancloud"]["appid"], config["leancloud"]["appkey"]) +leanUser = leancloud.User() # 登录用户 +leanUser.login(config["leancloud"]["user_name"],config["leancloud"]["user_pwd"]) +# 设置一个leancloud的acl +leanAcl = leancloud.ACL() +leanAcl.set_public_read_access(True) # 所有用户可读 +# 设置当前登录用户的的可写权限 +leanAcl.set_write_access(leancloud.User.get_current().id, True) +# 设置管理员角色写权限 +leanAcl.set_role_write_access(leancloud.Role('admin'), True) # 获取皮肤评价的信息 async def get_shop_rate(list_shop: dict, kook_user_id: str): @@ -174,6 +184,7 @@ async def update_ShopCmp(): i.set('skinList',list_shop) i.set('rating',rate_avg) i.set('platform',PLATFORM) + i.set_acl(leanAcl) i.save() print(f"[update_shop_cmp] saving best:{i.get('best')}") except: @@ -251,6 +262,7 @@ async def update_UserCmt(user_id:str,skin_uuid:str): obj.set('userId',user_id) obj.set('skinList',skinList) + obj.set_acl(leanAcl) obj.save() # 保存 @@ -343,6 +355,7 @@ async def update_UserRate(skin_uuid:str,rate_info:dict,user_id:str): obj.set('rating',rate_info['pit']) obj.set('rateAt',rate_info['time']) obj.set('msgId',rate_info['msg_id']) + obj.set_acl(leanAcl) obj.save() # 保存 @@ -361,6 +374,7 @@ async def update_SkinRate(skin_uuid:str,skin_name:str,rating:float): # 更新评分 obj.set('rating',rating) + obj.set_acl(leanAcl) obj.save() # 保存 @@ -379,4 +393,92 @@ async def remove_UserRate(skin_uuid:str,user_id:str): objlist[0].destroy() return True - return False \ No newline at end of file + return False + +#########################################hash skin list############################################### + +import hashlib + +# 生成字符串的MD5值 +def md5(content:str=None): + """generate md5 for string + """ + if content is None: + return '' + md5gen = hashlib.md5() + md5gen.update(content.encode()) + md5code = md5gen.hexdigest() + md5gen = None + return md5code + + +# 生成字符串的SHA256值 +def sha256(content:str=None): + if content is None: + return '' + sha256gen = hashlib.sha256() + sha256gen.update(content.encode()) + sha256code = sha256gen.hexdigest() + sha256gen = None + return sha256code + +# 生成skinlist的md5 +def get_skinlist_md5(skinlist:list): + """Args: skinlist with 4 skin_uuid\n + Return: md5(md5+sha) str + """ + skinlist = sorted(skinlist) # 排序 + # 将uuid拼接 + strlist = "=".join(i for i in skinlist) + md5Ret = md5(strlist) # 计算md5 + shaRet = sha256(strlist) # 计算sha256 + return md5(md5Ret+shaRet) # 两个一起还撞车,买彩票去吧 + +# 判断皮肤的值是否有缓存 +async def query_ShopCache(skinlist:list): + """Args: skinlist with 4 skin_uuid\n + Info: this def only used by none vip shop img + + Return:{ + "status": True/False, + "img_url": shop img url (will be empty when status False) + } + """ + md5Ret = get_skinlist_md5(skinlist) + ret = { "status": False,"img_url":""} + query = leancloud.Query('ShopCache') + query.equal_to('md5',md5Ret) # 查找md5值相同的元素 + objlist = query.find() + if len(objlist) > 0: #找到了 + ret['img_url'] = objlist[0].get('imgUrl') + ret['status'] = True + print(f"[{GetTime()}] ShopCache hit! [{md5Ret}]") + + return ret + +# 缓存皮肤(先判断出来没有再操作) +async def update_ShopCache(skinlist:list,img_url:str): + """md5(skinlist), cache imgurl to leancloud + """ + md5Ret = get_skinlist_md5(skinlist) + ShopCache = leancloud.Object.extend('ShopCache') + query = ShopCache.query + query.equal_to('md5',md5Ret) # 查找md5值相同的元素 + objlist = query.find() + obj = ShopCache() + retBool = True + if len(objlist) > 0: #找到了 + dbSkinlist = objlist[0].get('skinList') + if skinlist == dbSkinlist: + return True # 已经有了还缓存什么啊 + else: # md5撞车 + obj = objlist[0] # 赋值 + retBool = False + # 没找到或者list不相同(md5撞车了),新建并保存 + obj.set('md5',md5Ret) + obj.set('skinList',skinlist) + obj.set('imgUrl',img_url) + obj.set_acl(leanAcl) + obj.save() + print(f"[{GetTime()}] update_ShopCache [{md5Ret}]") + return retBool \ No newline at end of file diff --git a/code/utils/api/ApiHandler.py b/code/utils/api/ApiHandler.py index 8676ba8..3cfd6ac 100644 --- a/code/utils/api/ApiHandler.py +++ b/code/utils/api/ApiHandler.py @@ -2,14 +2,13 @@ import time import threading import traceback -# import requests -# import asyncio + from utils.valorant.EzAuth import EzAuthExp, auth2fa, auth2faWait, Get2faWait_Key, User2faCode from utils.api.ApiToken import check_token_rate from utils.Gtime import GetTime from utils.KookApi import kook_create_asset from utils.valorant.Val import fetch_daily_shop, fetch_vp_rp_dict -from utils.ShopImg import get_shop_img_11, get_shop_img_169 +from utils import ShopRate,ShopImg # bot的配置文件 from utils.FileManage import config @@ -19,9 +18,10 @@ # 默认的背景图 img_bak_169 = 'https://img.kookapp.cn/assets/2022-10/KcN5YoR5hC0zk0k0.jpg' img_bak_11 = 'https://img.kookapp.cn/assets/2023-01/lzRKEApuEP0rs0rs.jpg' -# gLock = asyncio.Lock() # 创建一把锁,用于保存文件 + # # 上传到lsky (这个上传很麻烦,lsky只认open打开的图片) +# gLock = asyncio.Lock() # 创建一把锁,用于保存文件 # async def lsky_upload(bg): # await gLock.acquire()# 上锁 # path = "./log/api_img_temp.png" @@ -56,28 +56,46 @@ async def base_img_request(params, list_shop, vp1=0, rp1=0): img_src = img_bak_11 # 默认背景1-1 # 开始画图 + ret = { "status": False,"value":"no need to img draw"} # 初始化ret为不需要画图 + cacheRet = {"status":False,"img_url":"err" } # 是否需要上传图片(false代表需要) start = time.perf_counter() if 'img_ratio' in params and params['img_ratio'] == '1': - ret = await get_shop_img_11(list_shop, bg_img_src=img_src) + # 是1-1的图片,检测有没有使用自定义背景图 + if img_src == img_bak_11: # 没有自定义背景图 + # 检测是否有缓存命中 + cacheRet = await ShopRate.query_ShopCache(list_shop) + # 缓存命中失败(需要画图) + if not cacheRet['status']: + ret = await ShopImg.get_shop_img_11(list_shop, bg_img_src=img_src) else: # 只有16-9的图片需获取vp和r点 - ret = await get_shop_img_169(list_shop, vp=vp1, rp=rp1, bg_img_src=img_src) + ret = await ShopImg.get_shop_img_169(list_shop, vp=vp1, rp=rp1, bg_img_src=img_src) # 打印计时 print(f"[{GetTime()}] [Api imgDraw]", format(time.perf_counter() - start, '.2f')) # 结果为浮点数,保留两位小数 - start = time.perf_counter() + # 开始上传图片 + start = time.perf_counter() # 更新start计时器 + # 判断缓存是否命中 + if cacheRet['status']: # 命中了 + dailyshop_img_src = cacheRet['img_url'] + print(f'[{GetTime()}] [Api imgUrl(cache)] {dailyshop_img_src}') + return {'code': 0, 'message': dailyshop_img_src, 'info': '商店图片获取成功,缓存命中'} + # 缓存没有命中,但是获取画图结果成功 if ret['status']: bg = ret['value'] # 这个值是pil的结果 img_src_ret = await kook_create_asset(api_bot_token, bg) # 上传图片到kook # img_src_ret = await lsky_upload(bg) # 上传图片到lsky - if img_src_ret['code'] == 0: + if img_src_ret['code'] == 0: # 上传图片成功 print(f"[{GetTime()}] [Api] kook_create_asset success {format(time.perf_counter() - start, '.2f')}") dailyshop_img_src = img_src_ret['data']['url'] + # 初始值是err,调用了query_ShopCache失败,返回值更新为空 + if cacheRet['img_url'] != 'err': + await ShopRate.update_ShopCache(skinlist=list_shop,img_url=dailyshop_img_src) print(f'[{GetTime()}] [Api imgUrl] {dailyshop_img_src}') return {'code': 0, 'message': dailyshop_img_src, 'info': '商店图片获取成功'} - else: + else: # 上传图片失败 print(f'[{GetTime()}] [Api] kook_create_asset failed') return {'code': 200, 'message': 'img upload err', 'info': '图片上传错误'} - else: #出现图片违规或者url无法获取 + else: # 出现图片违规或者背景图url无法获取 err_str = ret['value'] print(f'[{GetTime()}] [ERR]', err_str) return {'code': 200, 'message': 'img src err', 'info': '自定义图片获取失败'} @@ -105,7 +123,7 @@ async def img_draw_request(request): return {'code':200,'message':'list_shop len err! should be 4','info':'list_shop长度错误,皮肤数量不为4'} token = params['token'] - print(list_shop) + print(f"[{GetTime()}] [list_shop] {list_shop}") ck_ret = await check_token_rate(token) if not ck_ret['status']: return {'code': 200, 'message': ck_ret['message'], 'info': ck_ret['info']} From e8d5e0dc31dc4e4476743d2603c7276910ba8449 Mon Sep 17 00:00:00 2001 From: musnow Date: Sun, 26 Feb 2023 09:10:30 +0800 Subject: [PATCH 04/24] fix(ShopRate): don't set acl for ShopCmp & SkinRat, make ShopCmp update without comparing --- code/utils/ShopRate.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/code/utils/ShopRate.py b/code/utils/ShopRate.py index 4361de3..5015df2 100644 --- a/code/utils/ShopRate.py +++ b/code/utils/ShopRate.py @@ -170,21 +170,17 @@ async def update_ShopCmp(): kook_user_id = SkinRateDict["kkn"]["worse"]["kook_id"] for i in objlist: if(i.get('best')): # 是最佳 - if SkinRateDict["kkn"]["best"]["pit"] <= i.get('rating'): - continue # 当前用户分数小于数据库中的,不更新 # 设置值 rate_avg = SkinRateDict["kkn"]["best"]["pit"] list_shop = SkinRateDict["kkn"]["best"]["skin"] kook_user_id = SkinRateDict["kkn"]["best"]["kook_id"] - elif(SkinRateDict["kkn"]["worse"]["pit"] >= i.get('rating')): # 是最差,判断分数 - continue # 如果本地用户好于数据库记录,不更新 - # 更新对象并保存 + # 更新对象并保存(不需要比较,而是强制跟新) i.set('userId',kook_user_id) i.set('skinList',list_shop) i.set('rating',rate_avg) i.set('platform',PLATFORM) - i.set_acl(leanAcl) + # i.set_acl(leanAcl) # ShopCmp 设为所有人可写,不需要更新acl i.save() print(f"[update_shop_cmp] saving best:{i.get('best')}") except: @@ -374,8 +370,8 @@ async def update_SkinRate(skin_uuid:str,skin_name:str,rating:float): # 更新评分 obj.set('rating',rating) - obj.set_acl(leanAcl) - obj.save() # 保存 + # obj.set_acl(leanAcl) # 所有人可写,不需要设置acl + obj.save() # 保存 # 删除皮肤评价(违规言论) From c4b931022f6e165f3f0c5031731ebe40ecd2e232 Mon Sep 17 00:00:00 2001 From: musnow Date: Sun, 26 Feb 2023 10:29:10 +0800 Subject: [PATCH 05/24] feat(api): add /shop-cmt update using api for thread safety --- code/api.py | 27 +++++++- code/main.py | 15 +++-- code/utils/ShopRate.py | 121 +++++++++++++++++++++-------------- code/utils/api/ApiHandler.py | 28 ++++++++ 4 files changed, 135 insertions(+), 56 deletions(-) diff --git a/code/api.py b/code/api.py index 027dccb..4e5a56c 100644 --- a/code/api.py +++ b/code/api.py @@ -2,7 +2,7 @@ import traceback from aiohttp import web from utils.Gtime import GetTime -from utils.api.ApiHandler import tfa_code_requeset, afd_request, login_img_request, img_draw_request +from utils.api.ApiHandler import tfa_code_requeset, afd_request, login_img_request, img_draw_request,shop_cmp_request # 初始化节点 routes = web.RouteTableDef() @@ -128,11 +128,34 @@ async def post_tfa_code(request): status=200, content_type='application/json') +# 用于控制db中ShopCmp的更新 +@routes.post('/shop-cmp') +async def post_shop_cmp(request): + print(f"[{GetTime()}] [request] /shop-cmp") + try: + ret = await shop_cmp_request(request) + return web.Response(body=json.dumps(ret, indent=2, sort_keys=True, ensure_ascii=False), + content_type='application/json',status=200) + except: + err_cur = traceback.format_exc() + print(f"[{GetTime()}] [Api] ERR in /shop-cmp\n{err_cur}") + return web.Response(body=json.dumps( + { + 'code': 200, + 'message': 'unkown err', + 'info': f'未知错误', + 'except': f'{err_cur}' + }, + indent=2, + sort_keys=True, + ensure_ascii=False), + status=200, + content_type='application/json') -from main import bot # 爱发电的wh +from main import bot @routes.post('/afd') async def aifadian_webhook(request): print(f"[{GetTime()}] [request] /afd") diff --git a/code/main.py b/code/main.py index 0170396..355affb 100644 --- a/code/main.py +++ b/code/main.py @@ -2005,15 +2005,16 @@ async def auto_skin_notify(): UserShopDict = {} #清空用户的商店 #清空昨日最好/最差用户的皮肤表 SkinRateDict["kkn"] = copy.deepcopy(SkinRateDict["cmp"]) - SkinRateDict["cmp"]["best"]["skin"] = list() - SkinRateDict["cmp"]["best"]["pit"] = 0 - SkinRateDict["cmp"]["worse"]["skin"] = list() - SkinRateDict["cmp"]["worse"]["pit"] = 100 - await ShopRate.update_ShopCmp() # 更新数据库中的记录 - print("[BOT.TASK.NOTIFY] SkinRateDict/UserShopDict clear, sleep(10)") + SkinRateDict["cmp"]["best"]["list_shop"] = list() + SkinRateDict["cmp"]["best"]["rating"] = 0 + SkinRateDict["cmp"]["worse"]["list_shop"] = list() + SkinRateDict["cmp"]["worse"]["rating"] = 100 + # 更新数据库中的记录,并重置计数器 + await ShopRate.update_ShopCmp(SkinRateDict["kkn"]["best"],SkinRateDict["kkn"]["worse"],'kook',True) + print(f"[BOT.TASK.NOTIFY] SkinRateDict/UserShopDict clear, sleep(10) [{GetTime()}]") #睡10s再开始遍历(避免时间不准) await asyncio.sleep(10) - print("[BOT.TASK.NOTIFY] auto_skin_notify Start") + print(f"[BOT.TASK.NOTIFY] skin_notify Start [{GetTime()}]") #加载vip用户列表 VipUserD = copy.deepcopy(VipUserDict) err_count = 0 # 设置一个count来计算出错的用户数量 diff --git a/code/utils/ShopRate.py b/code/utils/ShopRate.py index 5015df2..8648192 100644 --- a/code/utils/ShopRate.py +++ b/code/utils/ShopRate.py @@ -52,15 +52,15 @@ async def get_shop_rate(list_shop: dict, kook_user_id: str): if rate_count > 0: rate_avg = rate_total // rate_count #记录当日冠军和屌丝 - if rate_avg > SkinRateDict["cmp"]["best"]["pit"]: - SkinRateDict["cmp"]["best"]["pit"] = rate_avg - SkinRateDict["cmp"]["best"]["skin"] = list_shop - SkinRateDict["cmp"]["best"]["kook_id"] = kook_user_id + if rate_avg > SkinRateDict["cmp"]["best"]["rating"]: + SkinRateDict["cmp"]["best"]["rating"] = rate_avg + SkinRateDict["cmp"]["best"]["list_shop"] = list_shop + SkinRateDict["cmp"]["best"]["user_id"] = kook_user_id print(f"[shop] update rate-best Au:{kook_user_id} = {rate_avg}") - elif rate_avg < SkinRateDict["cmp"]["worse"]["pit"]: - SkinRateDict["cmp"]["worse"]["pit"] = rate_avg - SkinRateDict["cmp"]["worse"]["skin"] = list_shop - SkinRateDict["cmp"]["worse"]["kook_id"] = kook_user_id + elif rate_avg < SkinRateDict["cmp"]["worse"]["rating"]: + SkinRateDict["cmp"]["worse"]["rating"] = rate_avg + SkinRateDict["cmp"]["worse"]["list_shop"] = list_shop + SkinRateDict["cmp"]["worse"]["user_id"] = kook_user_id print(f"[shop] update rate-worse Au:{kook_user_id} = {rate_avg}") if rate_avg >= 0 and rate_avg <= 20: @@ -117,14 +117,14 @@ async def check_shop_rate(kook_user_id: str, list_shop: list): if rate_count != 0: rate_avg = rate_total // rate_count #平均分 #记录冠军和屌丝 - if rate_avg > SkinRateDict["cmp"]["best"]["pit"]: - SkinRateDict["cmp"]["best"]["pit"] = rate_avg - SkinRateDict["cmp"]["best"]["skin"] = list_shop - SkinRateDict["cmp"]["best"]["kook_id"] = kook_user_id - elif rate_avg < SkinRateDict["cmp"]["worse"]["pit"]: - SkinRateDict["cmp"]["worse"]["pit"] = rate_avg - SkinRateDict["cmp"]["worse"]["skin"] = list_shop - SkinRateDict["cmp"]["worse"]["kook_id"] = kook_user_id + if rate_avg > SkinRateDict["cmp"]["best"]["rating"]: + SkinRateDict["cmp"]["best"]["rating"] = rate_avg + SkinRateDict["cmp"]["best"]["list_shop"] = list_shop + SkinRateDict["cmp"]["best"]["user_id"] = kook_user_id + elif rate_avg < SkinRateDict["cmp"]["worse"]["rating"]: + SkinRateDict["cmp"]["worse"]["rating"] = rate_avg + SkinRateDict["cmp"]["worse"]["list_shop"] = list_shop + SkinRateDict["cmp"]["worse"]["user_id"] = kook_user_id return True else: return False @@ -152,39 +152,66 @@ async def get_available_skinlist(name:str): return retlist # 每日早八,更新leancloud中的ShopCmp -async def update_ShopCmp(): +from asyncio import Lock +Slock = Lock() # 需要加锁 +Slock_no = 0 # 计数器 +async def update_ShopCmp(best:dict,worse:dict,platform:str,resetNo = False): """update shop rate in leancloud + Args: best/worse should be: { + "user_id": "938324311", + "rating": 97.0, + "list_shop": [] + } + + Return: + - { "status":True,"info":"all good"} + - { "status":False,"info":err} """ try: - # 获取对象 - ShopCmp = leancloud.Object.extend('ShopCmp') - query = ShopCmp.query - # 获取到两个已有值 - query.exists('rating') # 通过键值是否存在,进行查找 - objlist = query.find() - if len(objlist) == 0: - raise Exception("leancloud find today err!") - # 开始更新,先设置为最差 - rate_avg = SkinRateDict["kkn"]["worse"]["pit"] - list_shop = SkinRateDict["kkn"]["worse"]["skin"] - kook_user_id = SkinRateDict["kkn"]["worse"]["kook_id"] - for i in objlist: - if(i.get('best')): # 是最佳 - # 设置值 - rate_avg = SkinRateDict["kkn"]["best"]["pit"] - list_shop = SkinRateDict["kkn"]["best"]["skin"] - kook_user_id = SkinRateDict["kkn"]["best"]["kook_id"] - - # 更新对象并保存(不需要比较,而是强制跟新) - i.set('userId',kook_user_id) - i.set('skinList',list_shop) - i.set('rating',rate_avg) - i.set('platform',PLATFORM) - # i.set_acl(leanAcl) # ShopCmp 设为所有人可写,不需要更新acl - i.save() - print(f"[update_shop_cmp] saving best:{i.get('best')}") + # 同一时间只允许一个执行流过来操作ShopCmp + global Slock_no + if resetNo: Slock_no = 0 # 重置 + async with Slock: + # 获取对象 + ShopCmp = leancloud.Object.extend('ShopCmp') + query = ShopCmp.query + # 获取到两个已有值 + query.exists('rating') # 通过键值是否存在,进行查找 + objlist = query.find() + if len(objlist) <= 1: # 应该有两个才对 + raise Exception("leancloud find rating err!") + # 开始更新,先设置为最差 + for i in objlist: + cur_info = f"best:{i.get('best')} no:{Slock_no}" + if(i.get('best')): # 是最佳 + # 如果不是第一个更新,那就需要判断分数 + if best["rating"] < i.get('rating') and Slock_no!=0: + print(f"[update_ShopCmp] skipping {cur_info}") + continue # 当前用户分数小于数据库中的,不更新 + # 设置值 + i.set('userId',best["user_id"]) + i.set('skinList',best["list_shop"]) + i.set('rating',best["rating"]) + i.set('platform',platform) + i.save()# ShopCmp 设为所有人可写,不需要更新acl + elif(worse["rating"] > i.get('rating')) and Slock_no!=0: # 是最差,判断分数 + print(f"[update_ShopCmp] skipping {cur_info}") + continue # 如果本地用户好于数据库记录,不更新 + else: + # 更新对象并保存(不需要比较,而是强制跟新) + i.set('userId',worse["user_id"]) + i.set('skinList',worse["list_shop"]) + i.set('rating',worse["rating"]) + i.set('platform',platform) + i.save()# ShopCmp 设为所有人可写,不需要更新acl + print(f"[update_ShopCmp] saving {cur_info}") + # 处理完,no+1 + Slock_no+=1 + return { "status":True,"info":"update all good"} except: - print(f"ERR! [update_shop_cmp]\n{traceback.format_exc()}") + err = f"ERR! [update_ShopCmp]\n{traceback.format_exc()}" + print(err) + return { "status":False,"info":err} # 获取昨日最好/最差用户 async def get_ShopCmp(): @@ -327,7 +354,7 @@ async def update_UserRate(skin_uuid:str,rate_info:dict,user_id:str): - rate_info:{ "name": skin_name, "cmt": user comment, - "pit": user rating, + "rating": user rating, "time": time stamp, "msg_id: message id } @@ -348,7 +375,7 @@ async def update_UserRate(skin_uuid:str,rate_info:dict,user_id:str): obj.set('userId',user_id) obj.set('comment',rate_info['cmt']) - obj.set('rating',rate_info['pit']) + obj.set('rating',rate_info['rating']) obj.set('rateAt',rate_info['time']) obj.set('msgId',rate_info['msg_id']) obj.set_acl(leanAcl) diff --git a/code/utils/api/ApiHandler.py b/code/utils/api/ApiHandler.py index 3cfd6ac..f2f6256 100644 --- a/code/utils/api/ApiHandler.py +++ b/code/utils/api/ApiHandler.py @@ -231,6 +231,34 @@ async def tfa_code_requeset(request): } +# 更新leancloud +from utils.ShopRate import update_ShopCmp +async def shop_cmp_request(request): + body = await request.content.read() + params = json.loads(body.decode('UTF8')) + if 'best' not in params or 'worse' not in params or 'token' not in params or 'platform' not in params: + print(f"ERR! [{GetTime()}] params needed: token/best/worse/platform") + return { + 'code': 400, + 'message': 'params needed: token/best/worse/platform', + 'info': '缺少参数!请参考api文档,正确设置您的参数', + 'docs': 'https://github.com/Aewait/Kook-Valorant-Bot/blob/main/docs/valorant-shop-img-api.md' + } + + best = params['best'] + worse = params['worse'] + platform = params['platform'] + # 调用已有函数更新,保证线程安全 + upd_ret = await update_ShopCmp(best=best,worse=worse,platform=platform) + ret = {'code':0,'message':upd_ret['status'],'info':'ShopCmp更新成功'} + # 如果正常,那就是0,否则是200 + if not upd_ret['status']: + ret['code'] = 200 + ret['info'] = 'ShopCmp更新错误' + + return ret + + from utils.FileManage import AfdWebhook from khl.card import CardMessage, Card, Module, Types, Element From 4eeec82a6c8369c6db760232c96817d0ac9db405 Mon Sep 17 00:00:00 2001 From: musnow Date: Sun, 26 Feb 2023 10:39:14 +0800 Subject: [PATCH 06/24] docs(api): update api docs for /shop-cmp --- docs/leancloud.md | 2 +- docs/valorant-shop-img-api.md | 74 +++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/docs/leancloud.md b/docs/leancloud.md index 7f1c633..f0bc25d 100644 --- a/docs/leancloud.md +++ b/docs/leancloud.md @@ -59,7 +59,7 @@ 建议在本地维护一个当天(8am之后)的用户最好/最差商店信息,并在次日8am更新到数据库。数据库中维护的是**昨日商店**的最高分/最低分。 -由于leancloud的结构化数据存储并不是[线程安全](https://docs.leancloud.cn/sdk/storage/guide/python/#%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8)的,为了避免多个项目同时在8am访问并更新ShopCmp,请加入开发者频道和我确认,约定一个时间(不同项目错开)来更新数据! +由于leancloud的结构化数据存储并不是[线程安全](https://docs.leancloud.cn/sdk/storage/guide/python/#%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8)的,为了避免多个项目同时在8am访问并更新ShopCmp,请调用 [api/shop-cmp](valorant-shop-img-api.md) 接口进行更新 ## 4.UserCmt diff --git a/docs/valorant-shop-img-api.md b/docs/valorant-shop-img-api.md index d33e894..46bd2df 100644 --- a/docs/valorant-shop-img-api.md +++ b/docs/valorant-shop-img-api.md @@ -239,6 +239,35 @@ vp/rp只有16-9的图片需要,如果设置了`img_ratio`为`'1'`,则无需 } ~~~ +### 3.4 shop-cmt + +该接口用于更新leancloud数据库中的ShopCmt,该数据需要在 8am 并发进行修改。leancloud本身并不提供线程安全处理,就此将所有需要修改ShopCmt的操作统一到本端进行 + +请求方法:`POST` + +| params参数 | 说明 | 参数类型 |是否必填 | +| ---------- | --------------------- | -------- | -------- | +| token | API token | string |是 | +| best | 当日最好用户的商店信息 | json |是 | +| worse | 当日最差用户的商店信息 | json | 是 | +| platform | 来源平台 | string | 是 | + +best/worse应该包含如下字段,其中`user_id`如果么有可以留空(但是不要少这个字段),rating为当前商店4个皮肤的平均分(如一个皮肤么有评分,则不计入平均分计算) + +```json +{ + "user_id": "用户id", + "rating": 97.0, + "list_shop": [] +} +``` +返回示例 + +```json +{"code": 0, "info": "ShopCmp更新成功", "message": true} +``` + + ## 4.Python示例代码 ### 示例代码1:shop @@ -316,4 +345,49 @@ time: 3.9116134020000572 {'code': 0, 'info': '商店图片获取成功', 'message': 'https://img.kookapp.cn/attachments/2023-02/06/xgbRjMQeLQ0rs0rs.png'} time: 3.822338727999977 {'code': 0, 'info': '商店图片获取成功', 'message': 'https://img.kookapp.cn/attachments/2023-02/06/xgbRjMQeLQ0rs0rs.png'} +``` + +### 示例代码3:shop-cmp + +```python +def ApiRq3(best,worse,platform): + url = "https://val.musnow.top/api/shop-cmp" + params = { + "token":"api-token", + "best":best, + "worse":worse, + "platform":platform + } + res = requests.post(url,json=params) # 请求api + print(res) + return res.json() + +# 调用 +ret = ApiRq3({ + "user_id": "这是一个测试用例", + "rating": 100.0, + "list_shop": [ + "c9678d8c-4327-f397-b0ec-dca3c3d6fb15", + "901425cd-405a-d189-3516-ba954965e559", + "9f6e4612-433b-aea9-1683-3db7aee90848", + "4845a7ab-4120-ae1c-aec1-9e915a7424b1" + ] + },{ + "user_id": "这是一个测试用例", + "rating": 20.0, + "list_shop": [ + "155ba654-4afa-1029-9e71-e0b6962d5410", + "68ee5c6c-4424-e95a-f46f-c08ec2dfeb97", + "353c1e5f-4258-c49a-c0d6-319ad33bffea", + "e57317ac-4a93-50a9-30e9-93a098513fa9" + ] + },'qqchannel') +print(ret) +``` + +结果 + +``` + +{'code': 0, 'info': 'ShopCmp更新成功', 'message': True} ``` \ No newline at end of file From 7038fc719c8189b7641918e4da6a9a9249fca4fe Mon Sep 17 00:00:00 2001 From: musnow Date: Sun, 26 Feb 2023 14:36:54 +0800 Subject: [PATCH 07/24] feat(EzAuth): add reauthorize for EzAuth, refactor authorize --- code/utils/valorant/EzAuth.py | 348 +++++++++++++++------------------- 1 file changed, 155 insertions(+), 193 deletions(-) diff --git a/code/utils/valorant/EzAuth.py b/code/utils/valorant/EzAuth.py index 081e52c..c8c3116 100644 --- a/code/utils/valorant/EzAuth.py +++ b/code/utils/valorant/EzAuth.py @@ -1,22 +1,16 @@ # code from https://github.com/Prodzify/Riot-auth/blob/main/main.py import ssl import time -import asyncio -import copy -import random import pandas import requests from requests.adapters import HTTPAdapter -from http.cookies import SimpleCookie from typing import Any from collections import OrderedDict from re import compile -from riot_auth import RiotAuth from utils.valorant import EzAuthExp RiotClient = "RiotClient/62.0.1.4852117.4789131" -User2faCode = {} TFA_TIME_LIMIT = 600 # 600s时间限制 CIPHERS = [ @@ -51,12 +45,68 @@ def __init__(self): "Accept": "application/json, text/plain, */*" }) self.session.mount('https://', SSLAdapter()) - self.is2fa = False # 默认不是2fa用户 + self._cookies_ = self.session.cookies + self.is2fa = False # 2fa set to false + self.__mfa_start__ = 0 # 2fa start time - def authorize(self, username, password, key): - global User2faCode + def __set_userinfo(self): + """set_user_info to value""" + userinfo = self.get_userinfo() + self.user_id = userinfo['sub'] + self.Name = userinfo['name'] + self.Tag = userinfo['tag'] + self.creationdata = userinfo['create_data'] + self.typeban = userinfo['typeban'] + + def __set_region(self): + self.Region_headers = {'Content-Type': 'application/json', 'Authorization': f'{self.token_type} {self.access_token}'} + self.Region = self.get_region(self.Region_headers) + + def __set_access_token(self,data:dict): + """get access_token from response""" + pattern = compile( + 'access_token=((?:[a-zA-Z]|\d|\.|-|_)*).*id_token=((?:[a-zA-Z]|\d|\.|-|_)*).*token_type=((?:[a-zA-Z]|\d|)*).*expires_in=(\d*)') + p_data = pattern.findall(data['response']['parameters']['uri'])[0] + tokens = { + "access_token":p_data[0], + "id_token":p_data[1], + "token_type":p_data[2], + "expires_in":p_data[3] + } + return tokens + + def __set_info(self,tokens:dict): + """auth/reauth success, set entitlements_token, userinfo & region\n + Args: return value of __set_access_token() + """ + self.access_token = tokens['access_token'] + self.id_token = tokens['id_token'] + self.token_type = tokens['token_type'] + + self.base_headers = { + "User-Agent": f"{RiotClient} %s (Windows;10;;Professional, x64)", + "Authorization": f"{self.token_type} {self.access_token}", + } + self.session.headers.update(self.base_headers) + self._cookies_ = self.session.cookies - data = { + self.entitlements_token = self.get_entitlement_token() + self.__set_userinfo() + self.__set_region() + + async def authorize(self, username, password): + """Authenticate using username and password.\n + if username & password empty, using cookie reauth\n + Return: + - {"status":True,"auth":self,"2fa":self.is2fa} + - {"status":False,"auth":self,"2fa_status":self.is2fa} + if False, using email_verify() to send verify code + """ + if username and password: + self._cookies_.clear() # not reauth, clear cookie + + token = {"access_token":"","id_token":"","token_type":"Bearer","expires_in":'0'} + body = { "acr_values": "urn:riot:bronze", "claims": "", "client_id": "riot-client", @@ -65,106 +115,88 @@ def authorize(self, username, password, key): "response_type": "token id_token", "scope": "openid link ban lol_region", } - data2 = {"language": "en_US", "password": password, "remember": "true", "type": "auth", "username": username} - r = self.session.post(url=URLS.AUTH_URL, json=data) - r = self.session.put(url=URLS.AUTH_URL, json=data2) + r = self.session.post(url=URLS.AUTH_URL, json=body) data = r.json() - tokens = ["", ""] # 提前定义,避免下方出错(理论上来说应该走不到下面) + resp_type = data["type"] + + if resp_type != "response": # not reauth + body = { + "language": "en_US", + "password": password, + "remember": "true", + "type": "auth", + "username": username + } + r = self.session.put(url=URLS.AUTH_URL, json=body) + data = r.json() - if "access_token" in r.text: - pattern = compile( - 'access_token=((?:[a-zA-Z]|\d|\.|-|_)*).*id_token=((?:[a-zA-Z]|\d|\.|-|_)*).*expires_in=(\d*)') - data = pattern.findall(data['response']['parameters']['uri'])[0] - token = data[0] - token_id = data[1] - tokens = [token, token_id] + if data["type"] == "response": + pass - elif "auth_failure" in r.text: - User2faCode[key] = {'status': False, 'err': f"[{key}] auth_failure, USER NOT EXIST", - 'start_time': time.time(),'2fa_status':True} - raise EzAuthExp.AuthenticationError(User2faCode[key]['err']) + elif "auth_failure" in r.text: + raise EzAuthExp.AuthenticationError("auth_failure, user not exist") - elif 'rate_limited' in r.text: - User2faCode[key] = {'status': False, 'err': f"[{key}] auth rate_limited", 'start_time': time.time(),'2fa_status':True} - raise EzAuthExp.RatelimitError(User2faCode[key]['err']) + elif 'rate_limited' in r.text: + raise EzAuthExp.RatelimitError("auth_failure, rate_limited") - else: # 到此处是需要邮箱验证的用户 - print(f"[EzAuth] k:{key} 2fa user") - self.is2fa = True # 是2fa用户 - User2faCode[key] = { - 'vcode': '', - 'status': False, - 'start_time': time.time(), - '2fa_status': False, - 'err': None - } - # 开始等待用户提供邮箱验证码 - while (not User2faCode[key]['2fa_status']): - if (time.time() - User2faCode[key]['start_time']) > TFA_TIME_LIMIT: - break # 超过10分钟,以无效处理 - time.sleep(0.2) # 因为是线程执行操作,不能线程+异步 - - # 再次判断,避免是超时break的 - if User2faCode[key]['2fa_status']: - #需要用户通过命令键入邮箱验证码 - authdata = { - 'type': 'multifactor', - 'code': User2faCode[key]['vcode'], - } - r = self.session.put(url=URLS.AUTH_URL, json=authdata) - data = r.json() - if "access_token" in r.text: - pattern = compile( - 'access_token=((?:[a-zA-Z]|\d|\.|-|_)*).*id_token=((?:[a-zA-Z]|\d|\.|-|_)*).*expires_in=(\d*)') - data = pattern.findall(data['response']['parameters']['uri'])[0] - token = data[0] - token_id = data[1] - tokens = [token, token_id] + # 2fa auth + elif 'multifactor' in r.text: + print(f"[EzAuth] 2fa user") + self.is2fa = True # is 2fa user + self.__mfa_start__ = time.time() + return {"status":False,"auth":self,"2fa_status":self.is2fa} + else: + raise EzAuthExp.UnkownError(r.text) - elif "auth_failure" in r.text: - User2faCode[key]['err'] = f"[{key}] 2fa auth_failue" - raise EzAuthExp.MultifactorError(User2faCode[key]['err']) - elif "multifactor_attempt_failed" in r.text: # 大概率是验证码错了 - User2faCode[key]['err'] = f"[{key}] 2fa auth_failue, multifactor_attempt_failed" - raise EzAuthExp.MultifactorError(User2faCode[key]['err']) - else: - User2faCode[key]['err'] = f"[{key}] 2fa auth_failue, unkown err" - raise EzAuthExp.MultifactorError(User2faCode[key]['err']) - else: # 2fa等待超出600s - User2faCode[key]['err']=f"[{key}] 2fa wait overtime, wait failed" - raise EzAuthExp.WaitOvertimeError(User2faCode[key]['err']) + # get access_token from response + if "access_token" in r.text: + token = self.__set_access_token(data) + # auth/reauth success + self.__set_info(tokens=token) + else: + raise EzAuthExp.UnkownError(r.text) - # auth success - self.access_token = tokens[0] - self.id_token = tokens[1] + return {"status":True,"auth":self,"2fa_status":self.is2fa} - self.base_headers = { - 'User-Agent': f"{RiotClient} %s (Windows;10;;Professional, x64)", - 'Authorization': f'Bearer {self.access_token}', - } - self.session.headers.update(self.base_headers) - self.cookie = self.session.cookies + async def email_verfiy(self,vcode:str): + """email_verfiy after trying authorize + Return {"status":True,"auth":self,"2fa":self.is2fa} + """ + # no need to 2fa + if self.__mfa_start__ == 0: + return {"status":True,"auth":self,"2fa":self.is2fa} + # check time + if (time.time() - self.__mfa_start__) <= TFA_TIME_LIMIT: + authdata = { + 'type': 'multifactor', + 'code': vcode, + } + r = self.session.put(url=URLS.AUTH_URL, json=authdata) + data = r.json() + print(r.text) + + if data["type"] == "response": + pass + elif "auth_failure" in r.text: + raise EzAuthExp.MultifactorError("2fa auth_failue") + elif "multifactor_attempt_failed" in r.text: # verify code err + raise EzAuthExp.MultifactorError("2fa auth_failue, multifactor_attempt_failed") + else: + raise EzAuthExp.MultifactorError("2fa auth_failue, unkown err") + else: # 2fa wait overtime + print((time.time() - self.__mfa_start__)) + raise EzAuthExp.WaitOvertimeError("2fa wait overtime, wait failed") + + # get access_token from response + if "access_token" in r.text: + token = self.__set_access_token(data) + # auth/reauth success + self.__set_info(tokens=token) + else: + raise EzAuthExp.UnkownError(r.text) - self.entitlements_token = self.get_entitlement_token() - self.emailverifed = self.get_emailverifed() - - userinfo = self.get_userinfo() - self.user_id = userinfo['sub'] - self.Name = userinfo['name'] - self.Tag = userinfo['tag'] - self.creationdata = userinfo['create_data'] - self.typeban = userinfo['typeban'] - self.Region_headers = {'Content-Type': 'application/json', 'Authorization': f'Bearer {self.access_token}'} - self.session.headers.update(self.Region_headers) - self.Region = self.get_Region() - # return self - User2faCode[key] = { - 'status': True, - 'auth': self, - 'err': None, - '2fa_status':True - } - print(f"[EzAuth] k:{key} auth success") + self.__mfa_start__ = 0 + return {"status":True,"auth":self,"2fa":self.is2fa} def get_entitlement_token(self): r = self.session.post(URLS.ENTITLEMENT_URL, json={}) @@ -210,15 +242,18 @@ def get_userinfo(self): typeban = "None" return {'sub':Sub, 'name':Name, 'tag':Tag, 'create_data':Createdat, 'typeban':typeban} - def get_Region(self): + def get_region(self,headers): + """headers {'Content-Type': 'application/json', 'Authorization': f'{self.token_type} {self.access_token}'} + """ json = {"id_token": self.id_token} + r = self.session.headers.update(headers) r = self.session.put('https://riot-geo.pas.si.riotgames.com/pas/v1/product/valorant', json=json) data = r.json() Region = data['affinities']['live'] return Region def print(self): - print() + print("=" * 50) print(f"Accestoken: {self.access_token}") print("-" * 50) print(f"Entitlements: {self.entitlements_token}") @@ -232,98 +267,25 @@ def print(self): print(f"Createdat: {self.creationdata}") print("-" * 50) print(f"Bantype: {self.typeban}") + print("=" * 50) - def get_Token(self): - userdict = { + def get_userdict(self): + """Return = { 'auth_user_id': self.user_id, 'access_token': self.access_token, - 'entitlements_token': self.entitlements_token + 'entitlements_token': self.entitlements_token, + 'region':self.region + } + """ + return { + 'auth_user_id': self.user_id, + 'access_token': self.access_token, + 'entitlements_token': self.entitlements_token, + 'region': self.Region } - return userdict - - def get_CookieDict(self): - # cookie转换成dict - ck_dict = requests.utils.dict_from_cookiejar(self.cookie) - return ck_dict - - async def get_RiotAuth(self): - # cookie dict导入到SimpleCookie - Scookie = SimpleCookie(self.get_CookieDict()) - rauth = RiotAuth() - # 更新cookie - rauth._cookie_jar.update_cookies(Scookie) - ret = await rauth.reauthorize() # 测试登录 - if ret: - return rauth - else: #失败返回None - raise Exception('EzAuth change to RiotAuth failed') - - -###################################### Riot Auth ###################################################### - - -# 获取拳头的token -# 此部分代码来自 https://github.com/floxay/python-riot-auth -async def authflow(user: str, passwd: str): - CREDS = user, passwd - auth = RiotAuth() - await auth.authorize(*CREDS) - # await auth.reauthorize() - # print(f"Access Token Type: {auth.token_type}\n",f"Access Token: {auth.access_token}\n") - # print(f"Entitlements Token: {auth.entitlements_token}\n",f"User ID: {auth.user_id}") - return auth - - -# 两步验证的用户 -def auth2fa(user: str, passwd: str, key: str): - auth = EzAuth() - auth.authorize(user, passwd, key=key) - - -# 轮询检测的等待 -async def auth2faWait(key, msg=None): - while True: - if key in User2faCode: - # 如果2fa_status为假,代表是2fa且账户密码没有问题,需要用户提供vcode - if not User2faCode[key]['2fa_status']: - print(f"[auth2faWait] k:{key} 2fa Wait") - if msg != None: - await msg.reply(f"您开启了邮箱双重验证,请使用「/tfa {key} 邮箱码」的方式验证\n栗子:若邮箱验证码为114514,那么您应该键入 `/tfa {key} 114514`" - ) - - # 开始循环检测status状态 - while (not User2faCode[key]['status']): - # 不为none,出现错误 - if User2faCode[key]['err'] != None: - if 'rate_limited' in User2faCode[key]['err']: - raise EzAuthExp.RatelimitError(User2faCode[key]['err']) - elif 'auth_failure' in User2faCode[key]['err']: - raise EzAuthExp.AuthenticationError(User2faCode[key]['err']) - elif 'overtime' in User2faCode[key]['err']: - del User2faCode[key] - raise EzAuthExp.WaitOvertimeError(User2faCode[key]['err']) - else: - raise EzAuthExp.UnkownError(User2faCode[key]['err']) - - # 睡一会再检测 - await asyncio.sleep(0.3) - - # 如果退出且为真,代表登录成功了 - if User2faCode[key]['status']: - ret = copy.deepcopy(User2faCode[key]) - del User2faCode[key] - print(f"[auth2faWait] k:{key} Wait success,del key") - return ret - else: # 走到这里没有被raise,出现了未知错误 - print(f"[auth2faWait] k:{key} Wait failed, unkown err") - raise EzAuthExp.UnkownError("auth2faWait Failed") - # key值不在,睡一会后再看看 - await asyncio.sleep(0.2) - -async def Get2faWait_Key(): - ran = random.randint(1, 9999) - while (ran in User2faCode): - ran = random.randint(1, 9999) # 创建一个1-9999的随机值 - # 直到创建出了一个不在其中的键值 - return ran \ No newline at end of file + async def reauthorize(self): + """reauthorize using cookie + """ + await self.authorize("","") + return self \ No newline at end of file From 09487302661e3ec00a4c375f65b3d7df899b0211 Mon Sep 17 00:00:00 2001 From: musnow Date: Sun, 26 Feb 2023 20:16:18 +0800 Subject: [PATCH 08/24] refactor(main): using new version of EzAuth in main --- code/main.py | 95 ++++++++++++++++++++++------------- code/utils/valorant/EzAuth.py | 40 ++++++++++----- 2 files changed, 87 insertions(+), 48 deletions(-) diff --git a/code/main.py b/code/main.py index 355affb..9c58e69 100644 --- a/code/main.py +++ b/code/main.py @@ -17,7 +17,6 @@ from khl.command import Rule from aiohttp import client_exceptions from PIL import Image, UnidentifiedImageError # 用于合成图片 -from riot_auth import RiotAuth, auth_exceptions from utils import ShopRate from utils.Help import help_main, help_val, help_develop @@ -27,7 +26,7 @@ get_card) from utils.GrantRoles import (Color_GrantRole, Color_SetGm, Color_SetMsg, THX_Sponser) from utils.valorant.Val import * -from utils.valorant.EzAuth import auth2fa, authflow, auth2faWait, Get2faWait_Key, User2faCode,EzAuthExp +from utils.valorant.EzAuth import EzAuth,EzAuthExp from utils.Gtime import GetTime, GetTimeStampOf8AM from utils.BotVip import (VipUserDict, create_vip_uuid, fetch_vip_user, roll_vip_start, using_vip_uuid, vip_ck, vip_time_remain, vip_time_remain_cm, vip_time_stamp,get_vip_shop_bg_cm,replace_illegal_img,illegal_img_169) @@ -938,20 +937,21 @@ async def login(msg: Message, user: str = 'err', passwd: str = 'err', apSave='', send_msg = await msg.reply(cm0) #记录消息id用于后续更新 # 3.登录,获取用户的token - key = await Get2faWait_Key() # 先获取一个key - # 如果使用异步运行该函数,执行流会被阻塞住等待,应该使用线程来操作 - th = threading.Thread(target=auth2fa, args=(user, passwd, key)) - th.start() - resw = await auth2faWait(key=key, msg=msg) # 随后主执行流来这里等待 - res_auth = await resw['auth'].get_RiotAuth() # 直接获取RiotAuth对象 - is2fa = resw['auth'].is2fa # 是否是2fa用户 + auth = EzAuth() + resw = await auth.authorize(user,passwd) + UserAuthDict[msg.author_id] = {"auth": auth, "2fa": auth.is2fa } # 将对象插入 + # 3.1 没有成功,是2fa用户,需要执行/tfa命令 + if not resw['status']: + cm1 = await get_card("登录中断,需要提供邮箱验证码", "请使用「/tfa 验证码」提供邮箱验证码", icon_cm.val_logo_gif) + await upd_card(send_msg['msg_id'], cm1, channel_type=msg.channel_type) + return + # 4.如果没有抛出异常,那就是完成登录了,设置用户的玩家uuid+昵称 UserTokenDict[msg.author_id] = { - 'auth_user_id': res_auth.user_id, - 'GameName': resw['auth'].Name, - 'TagLine': resw['auth'].Tag + 'auth_user_id': auth.user_id, + 'GameName': auth.Name, + 'TagLine': auth.Tag } - UserAuthDict[msg.author_id] = {"auth": res_auth, "2fa": is2fa } # 将对象插入 # 设置基础打印信息 text = f"登陆成功!欢迎回来,{UserTokenDict[msg.author_id]['GameName']}#{UserTokenDict[msg.author_id]['TagLine']}" info_text = "当前cookie有效期为2~3天,有任何问题请[点我](https://kook.top/gpbTwZ)" @@ -962,11 +962,10 @@ async def login(msg: Message, user: str = 'err', passwd: str = 'err', apSave='', if msg.author_id in VipShopBgDict['bg']: VipShopBgDict['bg'][msg.author_id]['status'] = False # 用于保存cookie的路径,保存vip用户登录信息 - cookie_path = f"./log/cookie/{msg.author_id}.cke" - res_auth._cookie_jar.save(cookie_path) #保存 + auth.save_cookies(f"./log/cookie/{msg.author_id}.cke") # 6.用户自己选择是否保存账户密码,默认是不保存的;2fa用户也不会保存 - if apSave == 'save' and (not is2fa): + if apSave == 'save' and (not auth.is2fa): # 不在这里再新建(用于保存阿狸使用账户密码重登的时间,告知用户) if msg.author_id not in UserApLog: UserApLog[msg.author_id] = {} @@ -1031,22 +1030,41 @@ async def login(msg: Message, user: str = 'err', passwd: str = 'err', apSave='', @bot.command(name='tfa') -async def tfa_verify(msg: Message, key: str, tfa: str, *arg): - print(f"[{GetTime()}] Au:{msg.author_id}_{msg.author.username}#{msg.author.identify_num} = /2fa") +async def tfa_verify(msg: Message, tfa: str, *arg): + print(f"[{GetTime()}] Au:{msg.author_id}_{msg.author.username}#{msg.author.identify_num} = /tfa") if len(tfa) != 6: await msg.reply(f"邮箱验证码长度错误,请确认您输入了正确的6位验证码\n当前参数:{tfa}") return + send_msg = {'msg_id':''} try: - global User2faCode - key = int(key) - if key in User2faCode: - User2faCode[key]['vcode'] = tfa - User2faCode[key]['2fa_status'] = True - await msg.reply(f"两步验证码 `{tfa}` 获取成功,请等待……") - else: - await msg.reply(f"第二个参数key值错误,请确认您的输入,或重新login") + # 1. 先判断用户是否在dict里面 + if msg.author_id not in UserAuthDict: + await msg.reply("您不在UserAuthDict中,请先执行login!") + return + # 1.1 在,且auth对象是ezauth + auth = UserAuthDict[msg.author_id]['auth'] + assert isinstance(auth,EzAuth) + + # 2.发送提示信息 + cm0 = await get_card(f"两步验证码「{tfa}」获取成功", "小憩一下,很快就好啦!", icon_cm.val_logo_gif) + send_msg = await msg.reply(cm0) #记录消息id用于后续更新 + # 3.进行邮箱验证 + res = await auth.email_verfiy(tfa) + # 4.成功 + text = f"登陆成功!欢迎回来,{UserTokenDict[msg.author_id]['GameName']}#{UserTokenDict[msg.author_id]['TagLine']}" + info_text = "当前cookie有效期为2~3天,有任何问题请[点我](https://kook.top/gpbTwZ)" + cm = await get_card(text, info_text, icon_cm.correct) + await upd_card(send_msg['msg_id'], cm, channel_type=msg.channel_type) + + except EzAuthExp.MultifactorError as result: + if "multifactor_attempt_failed" in str(result): + cm = await get_card("两步验证码错误,请重试",str(result),icon_cm.lagging) + else: + cm = await get_card("邮箱验证错误,请重新login",str(result),icon_cm.lagging) + # 更新消息 + await upd_card(send_msg['msg_id'], cm, channel_type=msg.channel_type) except Exception as result: # 其他错误 await BaseException_Handler("tfa", traceback.format_exc(), msg, bot) @@ -1107,6 +1125,7 @@ async def login_reauth(kook_user_id: str): print(base_print + "auth_token failure,trying reauthorize()") global UserAuthDict,UserTokenDict auth = UserAuthDict[kook_user_id]['auth'] + assert isinstance(auth,EzAuth) #用cookie重新登录,会返回一个bool是否成功 ret = await auth.reauthorize() if ret: #会返回一个bool是否成功,成功了重新赋值 @@ -1116,9 +1135,14 @@ async def login_reauth(kook_user_id: str): print(base_print + "reauthorize() Failed! T-T") # 失败打印 # 有保存账户密码+不是邮箱验证用户 if kook_user_id in UserAuthDict['AP'] and (not UserAuthDict[kook_user_id]['2fa']): - res_auth = await authflow(UserAuthDict['AP'][kook_user_id]['a'], UserAuthDict['AP'][kook_user_id]['p']) - UserAuthDict[kook_user_id]['auth'] = res_auth # 用账户密码重新登录 - res_auth._cookie_jar.save(f"./log/cookie/{kook_user_id}.cke") #保存cookie + auth = EzAuth()# 用账户密码重新登录 + resw = await auth.authorize(UserAuthDict['AP'][kook_user_id]['a'], UserAuthDict['AP'][kook_user_id]['p']) + if not resw['status']: # 需要邮箱验证,那就直接跳出 + print(base_print + "authorize() need 2fa, return False") + return False + # 更新auth对象 + UserAuthDict[kook_user_id]['auth'] = auth + auth.save_cookies(f"./log/cookie/{kook_user_id}.cke") # 保存cookie # 记录使用账户密码重新登录的时间 UserApLog[kook_user_id][GetTime()] = UserTokenDict[kook_user_id]['GameName'] print(base_print + "authflow() by AP") @@ -1139,11 +1163,9 @@ async def check_reauth(def_name: str = "", msg: Union[Message, str] = ''): try: user_id = msg if isinstance(msg, str) else msg.author_id #如果是str就直接用 auth = UserAuthDict[user_id]['auth'] - userdict = { - 'auth_user_id': auth.user_id, - 'access_token': auth.access_token, - 'entitlements_token': auth.entitlements_token - } + assert isinstance(auth,EzAuth) + # 直接从对象中获取userdict + userdict = auth.get_userdict() resp = await fetch_valorant_point(userdict) # resp={'httpStatus': 400, 'errorCode': 'BAD_CLAIMS', 'message': 'Failure validating/decoding RSO Access Token'} # 如果没有这个键,会直接报错进except; 如果有这个键,就可以继续执行下面的内容 @@ -1298,6 +1320,7 @@ async def get_daily_shop(msg: Message, *arg): else: # 命中 upload_flag = False dailyshop_img_src = cache_ret['img_url'] + log_time+="[cache] " # img_ret 代表是否画图成功,如果是缓存命中,也当成功处理 if img_ret['status']: @@ -2297,8 +2320,8 @@ async def loading_channel_cookie(): cookie_path = f"./log/cookie/{user}.cke" #如果路径存在,那么说明已经保存了这个vip用户的cookie if os.path.exists(cookie_path): - auth = RiotAuth() #新建一个对象 - auth._cookie_jar.load(cookie_path) #加载cookie + auth = EzAuth() + auth.load_cookies(cookie_path) #加载cookie ret_bool = await auth.reauthorize() #尝试登录 if ret_bool: # True登陆成功 UserAuthDict[user] = {"auth": auth, "2fa": False} #将对象插入 diff --git a/code/utils/valorant/EzAuth.py b/code/utils/valorant/EzAuth.py index c8c3116..5f67f92 100644 --- a/code/utils/valorant/EzAuth.py +++ b/code/utils/valorant/EzAuth.py @@ -1,5 +1,6 @@ -# code from https://github.com/Prodzify/Riot-auth/blob/main/main.py +# repo: https://github.com/musnows/Riot-auth import ssl +import json import time import pandas import requests @@ -9,8 +10,8 @@ from re import compile from utils.valorant import EzAuthExp - -RiotClient = "RiotClient/62.0.1.4852117.4789131" +# get latest version: https://valorant-api.com/v1/version +RiotClient = "RiotClient/63.0.9.4909983.4789131" TFA_TIME_LIMIT = 600 # 600s时间限制 CIPHERS = [ @@ -45,7 +46,6 @@ def __init__(self): "Accept": "application/json, text/plain, */*" }) self.session.mount('https://', SSLAdapter()) - self._cookies_ = self.session.cookies self.is2fa = False # 2fa set to false self.__mfa_start__ = 0 # 2fa start time @@ -88,7 +88,6 @@ def __set_info(self,tokens:dict): "Authorization": f"{self.token_type} {self.access_token}", } self.session.headers.update(self.base_headers) - self._cookies_ = self.session.cookies self.entitlements_token = self.get_entitlement_token() self.__set_userinfo() @@ -103,7 +102,7 @@ async def authorize(self, username, password): if False, using email_verify() to send verify code """ if username and password: - self._cookies_.clear() # not reauth, clear cookie + self.session.cookies.clear() # not reauth, clear cookie token = {"access_token":"","id_token":"","token_type":"Bearer","expires_in":'0'} body = { @@ -173,7 +172,6 @@ async def email_verfiy(self,vcode:str): } r = self.session.put(url=URLS.AUTH_URL, json=authdata) data = r.json() - print(r.text) if data["type"] == "response": pass @@ -184,7 +182,6 @@ async def email_verfiy(self,vcode:str): else: raise EzAuthExp.MultifactorError("2fa auth_failue, unkown err") else: # 2fa wait overtime - print((time.time() - self.__mfa_start__)) raise EzAuthExp.WaitOvertimeError("2fa wait overtime, wait failed") # get access_token from response @@ -197,6 +194,16 @@ async def email_verfiy(self,vcode:str): self.__mfa_start__ = 0 return {"status":True,"auth":self,"2fa":self.is2fa} + + async def reauthorize(self) -> bool: + """reauthorize using cookie + """ + try: + await self.authorize("","") + return True + except Exception as result: + print(f"[EzAuth] reauthoreize err!\n{result}") + return False def get_entitlement_token(self): r = self.session.post(URLS.ENTITLEMENT_URL, json={}) @@ -284,8 +291,17 @@ def get_userdict(self): 'region': self.Region } - async def reauthorize(self): - """reauthorize using cookie + def save_cookies(self,path:str): + """dump cookies_dict to path (w+) + """ + cookies = requests.utils.dict_from_cookiejar(self.session.cookies) + with open(path,"w+") as f: + f.write(json.dumps(cookies)) + + def load_cookies(self,path:str): + """load cookies_dic from path (rb) """ - await self.authorize("","") - return self \ No newline at end of file + with open(path,"r") as f: + load_cookies = json.loads(f.read()) + + self.session.cookies = requests.utils.cookiejar_from_dict(load_cookies) \ No newline at end of file From 0a49604d9666878e0ea67d1df0e27b3f74328a82 Mon Sep 17 00:00:00 2001 From: musnow Date: Sun, 26 Feb 2023 20:54:04 +0800 Subject: [PATCH 09/24] refactor(api): add /login, using EzAuth docs(api): update api docs --- code/api.py | 57 ++++++++++++++---- code/utils/api/ApiHandler.py | 110 +++++++++++++++++++--------------- docs/valorant-shop-img-api.md | 45 ++++++++++---- 3 files changed, 142 insertions(+), 70 deletions(-) diff --git a/code/api.py b/code/api.py index 4e5a56c..d7b0b87 100644 --- a/code/api.py +++ b/code/api.py @@ -2,7 +2,7 @@ import traceback from aiohttp import web from utils.Gtime import GetTime -from utils.api.ApiHandler import tfa_code_requeset, afd_request, login_img_request, img_draw_request,shop_cmp_request +from utils.api import ApiHandler # 初始化节点 routes = web.RouteTableDef() @@ -32,7 +32,7 @@ def hello_world(request): # put application's code here async def get_dailshop_img(request): print(f"[{GetTime()}] [request] /shop-draw") try: - ret = await img_draw_request(request) + ret = await ApiHandler.img_draw_request(request) return web.Response(body=json.dumps(ret, indent=2, sort_keys=True, ensure_ascii=False), content_type='application/json',status=200) except: @@ -57,7 +57,7 @@ async def get_dailshop_img(request): async def get_dailshop_img(request): print(f"[{GetTime()}] [request] /shop-img") try: - ret = await login_img_request(request) + ret = await ApiHandler.login_request(request,"GET") if ret['code'] == 0: return web.Response(headers={'Location': ret['message']}, status=303) # 303是直接跳转到图片 else: @@ -80,12 +80,12 @@ async def get_dailshop_img(request): content_type='application/json') -# 获取图片url -@routes.post('/shop') +# 登录接口 +@routes.post('/login') async def get_dailshop_img(request): - print(f"[{GetTime()}] [request] /shop") + print(f"[{GetTime()}] [request] /login") try: - ret = await login_img_request(request,"POST") + ret = await ApiHandler.login_request(request,"POST") return web.Response(body=json.dumps(ret, indent=2, sort_keys=True, ensure_ascii=False), content_type='application/json',status=200) except: @@ -104,12 +104,12 @@ async def get_dailshop_img(request): status=200, content_type='application/json') - +# 邮箱验证登录 @routes.post('/tfa') async def post_tfa_code(request): print(f"[{GetTime()}] [request] /tfa") try: - ret = await tfa_code_requeset(request) + ret = await ApiHandler.tfa_code_requeset(request) return web.Response(body=json.dumps(ret, indent=2, sort_keys=True, ensure_ascii=False), content_type='application/json',status=200) except: @@ -127,13 +127,48 @@ async def post_tfa_code(request): ensure_ascii=False), status=200, content_type='application/json') + +@routes.post('/shop') +async def get_dailshop_img(request): + print(f"[{GetTime()}] [request] /shop") + try: + body = await request.content.read() + params = json.loads(body.decode('UTF8')) + # 判断必须要的参数是否齐全 + if 'account' not in params or 'token' not in params: + print(f"ERR! [{GetTime()}] params needed: token/account/passwd") + return { + 'code': 400, + 'message': 'params needed: token/account/passwd', + 'info': '缺少参数!示例: /shop-img?token=api凭证&account=Riot账户&passwd=Riot密码&img_src=自定义背景图(可选)', + 'docs': 'https://github.com/Aewait/Kook-Valorant-Bot/blob/main/docs/valorant-shop-img-api.md' + } + # 画图请求,不需要检测token速率 + ret = await ApiHandler.shop_get_request(params,params['account']) + return web.Response(body=json.dumps(ret, indent=2, sort_keys=True, ensure_ascii=False), + content_type='application/json',status=200) + except: + err_cur = traceback.format_exc() + print(f"[{GetTime()}] [Api] ERR in /shop\n{err_cur}") + return web.Response(body=json.dumps( + { + 'code': 200, + 'message': 'unkown err', + 'info': f'未知错误', + 'except': f'{err_cur}' + }, + indent=2, + sort_keys=True, + ensure_ascii=False), + status=200, + content_type='application/json') # 用于控制db中ShopCmp的更新 @routes.post('/shop-cmp') async def post_shop_cmp(request): print(f"[{GetTime()}] [request] /shop-cmp") try: - ret = await shop_cmp_request(request) + ret = await ApiHandler.shop_cmp_request(request) return web.Response(body=json.dumps(ret, indent=2, sort_keys=True, ensure_ascii=False), content_type='application/json',status=200) except: @@ -160,7 +195,7 @@ async def post_shop_cmp(request): async def aifadian_webhook(request): print(f"[{GetTime()}] [request] /afd") try: - ret = await afd_request(request, bot) + ret = await ApiHandler.afd_request(request, bot) return web.Response(body=json.dumps(ret, indent=2, sort_keys=True, ensure_ascii=False), content_type='application/json') except: diff --git a/code/utils/api/ApiHandler.py b/code/utils/api/ApiHandler.py index f2f6256..a204bd8 100644 --- a/code/utils/api/ApiHandler.py +++ b/code/utils/api/ApiHandler.py @@ -3,7 +3,7 @@ import threading import traceback -from utils.valorant.EzAuth import EzAuthExp, auth2fa, auth2faWait, Get2faWait_Key, User2faCode +from utils.valorant.EzAuth import EzAuthExp,EzAuth from utils.api.ApiToken import check_token_rate from utils.Gtime import GetTime from utils.KookApi import kook_create_asset @@ -14,7 +14,7 @@ from utils.FileManage import config # 用来给kook上传文件的bot token api_bot_token = config['token']['api_bot_token'] -Api2faDict = {'data': {}} # 保存2fa用户登录的过程信息 +ApiAuthDict = {'data':{}} # 默认的背景图 img_bak_169 = 'https://img.kookapp.cn/assets/2022-10/KcN5YoR5hC0zk0k0.jpg' img_bak_11 = 'https://img.kookapp.cn/assets/2023-01/lzRKEApuEP0rs0rs.jpg' @@ -133,9 +133,34 @@ async def img_draw_request(request): else: return await base_img_request(params, list_shop, int(params['vp']), int(params['rp'])) +# 获取商店的请求 +async def shop_get_request(params,account:str): + # 1.参数检测 + isRaw = ('raw' in params and str(params['raw']) != '0') # 用户需要原始uuid + isimgRatio = ( 'img_ratio' not in params or str(params['img_ratio']) != '1') # 判断是否有指定图片比例 + # 2.获取缓存中的auth对象 + if account not in ApiAuthDict['data']: + return { "code":200,"message":"account不在ApiAuthDict缓存中,请先调用/login接口", + "info":"account not in ApiAuthDict['data']" } + # 2.1 判断通过,获取auth + auth = ApiAuthDict['data'][account]['auth'] + assert isinstance(auth,EzAuth) + # 3 获取每日商店 + userdict = auth.get_userdict() + resp = await fetch_daily_shop(userdict) + print(f'[{GetTime()}] [Api] fetch_daily_shop success') + list_shop = resp["SkinsPanelLayout"]["SingleItemOffers"] # 商店刷出来的4把枪 + res_vprp = {'vp': 0, 'rp': 0} # 先初始化为0 + if isimgRatio or isRaw: + res_vprp = await fetch_vp_rp_dict(userdict) # 只有16-9的图片需获取vp和r点 + # 如果用户需要raw,则返回皮肤uuid和vp rp的dict + if isRaw: + return { "code":0,"message":"获取原始接口返回值成功","info":"get raw response success","storefront":resp,"wallet":res_vprp} + else: + return await base_img_request(params, list_shop, res_vprp['vp'], res_vprp['rp']) # 登录+画图 -async def login_img_request(request,method = "GET"): +async def login_request(request,method = "GET"): params = request.rel_url.query if method=="POST": body = await request.content.read() @@ -153,22 +178,20 @@ async def login_img_request(request,method = "GET"): account = params['account'] passwd = params['passwd'] token = params['token'] - isRaw = ('raw' in params and str(params['raw']) != '0') # 用户需要原始uuid - isimgRatio = ( 'img_ratio' not in params or str(params['img_ratio']) != '1') # 判断是否有指定图片比例 # 检测token速率,避免撞墙 ck_ret = await check_token_rate(token) if not ck_ret['status']: return {'code': 200, 'message': ck_ret['message'], 'info': ck_ret['info']} try: - key = await Get2faWait_Key() - Api2faDict['data'][account] = key - # 因为如果使用异步,该执行流会被阻塞住等待,应该使用线程来操作 - th = threading.Thread(target=auth2fa, args=(account, passwd, key)) - th.start() - resw = await auth2faWait(key=key) # 随后主执行流来这里等待 - res_auth = resw['auth'] - del Api2faDict['data'][account] # 登录成功,删除账户键值 + # 登录,获取用户的token + auth = EzAuth() + resw = await auth.authorize(account,passwd) + ApiAuthDict['data'][account] = {"auth": auth, "2fa": auth.is2fa } # 将对象插入 + # 没有成功,是2fa用户,需要执行/tfa + if not resw['status']: + return {'code': 0, 'message': "need provide email verify code", 'info': '2fa用户,请使用/tfa接口提供邮箱验证码'} + except EzAuthExp.RatelimitError as result: print(f"ERR! [{GetTime()}] login - EzAuthExp.RatelimitError") return {'code': 200, 'message': "EzAuthExp.RiotRatelimitError", 'info': 'riot登录api超速,请稍后重试'} @@ -176,23 +199,14 @@ async def login_img_request(request,method = "GET"): print(f"ERR! [{GetTime()}] login\n{traceback.format_exc()}") return {'code': 200, 'message': f"{result}", 'info': 'riot登录错误,详见message'} - print(f'[{GetTime()}] [Api] k:{key} - user auth success') - userdict = { - 'auth_user_id': res_auth.user_id, - 'access_token': res_auth.access_token, - 'entitlements_token': res_auth.entitlements_token - } - resp = await fetch_daily_shop(userdict) #获取每日商店 - print(f'[{GetTime()}] [Api] fetch_daily_shop success') - list_shop = resp["SkinsPanelLayout"]["SingleItemOffers"] # 商店刷出来的4把枪 - res_vprp = {'vp': 0, 'rp': 0} # 先初始化为0 - if isimgRatio or isRaw: - res_vprp = await fetch_vp_rp_dict(userdict) # 只有16-9的图片需获取vp和r点 - # 如果用户需要raw,则返回皮肤uuid和vp rp的dict - if isRaw: - return { "code":0,"message":"获取原始接口返回值成功","info":"get raw response success","storefront":resp,"wallet":res_vprp} - else: - return await base_img_request(params, list_shop, res_vprp['vp'], res_vprp['rp']) + # 走到这里,代表不是2fa用户,且登陆成功 + print(f'[{GetTime()}] [Api] user auth success') + # 如果是GET方法,直接调用获取商店的操作 + if method == "GET": # /shop-img 接口是get的 + return await shop_get_request(params,account) + # 保存cookie到本地 + auth.save_cookies(f"./log/cookie/api/{account}.cke") + return {'code': 0, 'message': "auth success", 'info': '登录成功!'} # 邮箱验证的post @@ -212,23 +226,25 @@ async def tfa_code_requeset(request): vcode = params['vcode'] token = params['token'] - global Api2faDict - if account not in Api2faDict['data']: - return { - 'code': 200, - 'message': 'Riot account not in Api2faDict', - 'info': '拳头账户不在dict中,请先请求/shop-img或/shop接口' - } - - key = Api2faDict['data'][account] - User2faCode[key]['vcode'] = vcode - User2faCode[key]['2fa_status'] = True - return { - 'code': 0, - 'message': 'email verify code post success,wait for shop img return', - 'info': '两步验证码获取成功,请等待主接口返回', - 'vcode': vcode - } + global ApiAuthDict + if account not in ApiAuthDict['data']: + return { 'code': 200,'message': 'Riot account not in ApiAuthDict', + 'info': '拳头账户不在dict中,请先请求/shop-img或/login接口' } + try: + auth = ApiAuthDict['data'][account]['auth'] + assert isinstance(auth,EzAuth) + res = await auth.email_verfiy(vcode) + except EzAuthExp.MultifactorError as result: + if "multifactor_attempt_failed" in str(result): + return { 'code': 200,'message': 'multifactor_attempt_failed', + 'info': '两步验证码错误,请在10min内重新调用此接口重传','vcode': vcode } + # 其他情况 + return {'code': 200,'message': '2fa auth_failure','info': '两步验证登陆错误,请重新操作','vcode': vcode} + # 走到这里,代表不是2fa用户,且登陆成功 + print(f'[{GetTime()}] [Api] 2fa user auth success') + # 保存cookie到本地 + auth.save_cookies(f"./log/cookie/api/{account}.cke") + return {'code': 0, 'message': "2fa auth success", 'info': '2fa用户登录成功!'} # 更新leancloud diff --git a/docs/valorant-shop-img-api.md b/docs/valorant-shop-img-api.md index 46bd2df..e4bd0d6 100644 --- a/docs/valorant-shop-img-api.md +++ b/docs/valorant-shop-img-api.md @@ -82,7 +82,9 @@ https://val.musnow.top/api/shop-img?token=API的密钥&account=账户&passwd=密 ### 3.1 shop -如果你是开发者,请使用`/shop`来获取`json`格式的结果 +如果你是开发者,请使用`/shop`来获取`json`格式的结果; + +注意,请求此接口之前,请先请求 `/login` 和 `/tfa` ~~~ https://val.musnow.top/api/shop @@ -90,13 +92,10 @@ https://val.musnow.top/api/shop 请求方法: `POST` -速率限制:`10r/m` - | body参数 | 说明 | 参数类型 |是否必填 | | ---------- | --------------------- | -------- | -------- | | token | API token | string|是 | | account | 拳头账户 | string |是 | -| passwd | 拳头账户密码 | string|是 | | img_src | 自定义背景图的url链接 | string | 否 | | img_ratio | 自定义返回图比例,值为1代表正方形 | int |否 | | raw | 设置为1,获取Riot接口的原始响应(不画图) | int | 否 | @@ -163,8 +162,35 @@ https://valorant-api.com/v1/competitivetiers/{competitivetierUuid} 还有一件事!部分皮肤返回结果中,是不带皮肤的图片的(我真的不理解为什么会这样)这也需要你遍历本地找皮肤图片! +### 3.2 login -### 3.2 tfa +该接口用于登录,后台将会根据account将用户的登录信息缓存到内存中 + +~~~ +https://val.musnow.top/api/login +~~~ + +请求方法:`POST` + +速率限制:`10r/m` + +| body参数 | 说明 | 参数类型 |是否必填 | +| ---------- | --------------------- | -------- | -------- | +| token | API token | string|是 | +| account | 拳头账户 | string |是 | +| passwd | 拳头账户密码 | string |是 | + +返回示例(登陆成功) +```json +{"code": 0,"info": "登录成功!", "message": "auth success"} +``` +返回示例(需要邮箱验证) + +```json +{"code": 0, "info": "2fa用户,请使用/tfa接口提供邮箱验证码", "message": "need provide email verify code"} +``` + +### 3.3 tfa 此接口用于两步验证,适用于开启了邮箱验证的用户; @@ -187,15 +213,10 @@ https://val.musnow.top/api/tfa 返回示例 ~~~json -{ - "code": 0, - "message": "email verify code post success,wait for shop img return", - "info": "两步验证码获取成功,请等待主接口返回", - "vcode": 114514 -} +{ "code": 0, "message": "2fa auth success", "info": "2fa用户登录成功!"} ~~~ -### 3.3 shop-draw +### 3.4 shop-draw 这个接口更加适合在本地管理用户的登录信息,本地调用riot api获取用户`商店皮肤/vp/rp`后,再调用此接口,直接返回图片url From 70d9aa9f5f70d0aa143262b1e1ecb57f687a7a12 Mon Sep 17 00:00:00 2001 From: musnow Date: Sun, 26 Feb 2023 21:15:10 +0800 Subject: [PATCH 10/24] feat(main): add ApiAuthLog load in start task --- code/main.py | 37 +++++++++++++++++++++++++++++++----- code/utils/FileManage.py | 2 ++ code/utils/api/ApiHandler.py | 23 +++++++++++----------- 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/code/main.py b/code/main.py index 9c58e69..6b53cd9 100644 --- a/code/main.py +++ b/code/main.py @@ -35,7 +35,7 @@ from utils.valorant.ValFileUpd import update_bundle_url, update_price, update_skins # bot的token文件 -from utils.FileManage import config, Save_All_File +from utils.FileManage import config, Save_All_File,ApiAuthLog # 用读取来的 config 初始化 bot,字段对应即可 bot = Bot(token=config['token']['bot']) # 只用来上传图片的bot @@ -2315,7 +2315,7 @@ async def loading_channel_cookie(): log_str_success = "[BOT.TASK] load cookie success = Au:" log_str_failed = "[BOT.TASK] load cookie failed! = Au:" log_not_exits = "[BOT.TASK] cookie path not exists = Au:" - #遍历用户列表 + # 遍历用户列表 for user, uinfo in VipUserDict.items(): cookie_path = f"./log/cookie/{user}.cke" #如果路径存在,那么说明已经保存了这个vip用户的cookie @@ -2337,12 +2337,39 @@ async def loading_channel_cookie(): else: log_not_exits += f"({user}) " continue - #结束任务 + # 结束任务 print(log_str_success) #打印正常的用户 print(log_str_failed) #打印失败的用户 print(log_not_exits) #打印路径不存在的用户 - print("[BOT.TASK] loading cookie finished") - + print(f"[BOT.TASK] loading user cookie finished {GetTime()}") + + # api缓存的用户列表 + log_str_success = "[BOT.TASK] api load cookie success = Au:" + log_str_failed = "[BOT.TASK] api load cookie failed! = Au:" + log_not_exits = "[BOT.TASK] api cookie path not exists = Au:" + # 遍历api用户列表 + for user in ApiAuthLog: + cookie_path = f"./log/cookie/api/{user}.cke" + #如果路径存在,那么说明已经保存了这个vip用户的cookie + if os.path.exists(cookie_path): + auth = EzAuth() + auth.load_cookies(cookie_path) #加载cookie + ret_bool = await auth.reauthorize() #尝试登录 + if ret_bool: # True登陆成功 + UserAuthDict[user] = {"auth": auth, "2fa": False} #将对象插入 + log_str_success += f"({user})" + else: + log_str_failed += f"({user}) " + #print(f"[BOT.TASK] Au:{user} - load cookie failed!") + continue + else: + log_not_exits += f"({user}) " + continue + # 结束任务 + print(log_str_success) #打印正常的用户 + print(log_str_failed) #打印失败的用户 + print(log_not_exits) #打印路径不存在的用户 + print(f"[BOT.TASK] loading api user cookie finished {GetTime()}") # 开机 (如果是主文件就开机) if __name__ == '__main__': diff --git a/code/utils/FileManage.py b/code/utils/FileManage.py index 1e9aee2..da0646b 100644 --- a/code/utils/FileManage.py +++ b/code/utils/FileManage.py @@ -143,6 +143,8 @@ async def save_aio(self): UserAuthID = FileManage("./log/UserAuthID.json") # 用户游戏id/uuid,账户密码重登记录 UserTokenDict = UserAuthID['data'] # riot用户游戏id和uuid UserApLog = UserAuthID['ap_log'] # 账户密码重登记录 +ApiAuthLog = UserAuthID['api_log'] # api 缓存用户的account记录 +ApiAuthCache = {'data':{}} # api EzAuth对象缓存 VipUuidDict = FileManage("./log/VipUuid.json") # vip uuid文件 VipShopBgDict = FileManage("./log/VipUserShopBg.json") # vip 背景图设置;商店图缓存 diff --git a/code/utils/api/ApiHandler.py b/code/utils/api/ApiHandler.py index a204bd8..1ccacfa 100644 --- a/code/utils/api/ApiHandler.py +++ b/code/utils/api/ApiHandler.py @@ -11,10 +11,9 @@ from utils import ShopRate,ShopImg # bot的配置文件 -from utils.FileManage import config +from utils.FileManage import config,ApiAuthCache,ApiAuthLog # 用来给kook上传文件的bot token api_bot_token = config['token']['api_bot_token'] -ApiAuthDict = {'data':{}} # 默认的背景图 img_bak_169 = 'https://img.kookapp.cn/assets/2022-10/KcN5YoR5hC0zk0k0.jpg' img_bak_11 = 'https://img.kookapp.cn/assets/2023-01/lzRKEApuEP0rs0rs.jpg' @@ -139,11 +138,11 @@ async def shop_get_request(params,account:str): isRaw = ('raw' in params and str(params['raw']) != '0') # 用户需要原始uuid isimgRatio = ( 'img_ratio' not in params or str(params['img_ratio']) != '1') # 判断是否有指定图片比例 # 2.获取缓存中的auth对象 - if account not in ApiAuthDict['data']: - return { "code":200,"message":"account不在ApiAuthDict缓存中,请先调用/login接口", - "info":"account not in ApiAuthDict['data']" } + if account not in ApiAuthCache['data']: + return { "code":200,"message":"account不在ApiAuthCache缓存中,请先调用/login接口", + "info":"account not in ApiAuthCache['data']" } # 2.1 判断通过,获取auth - auth = ApiAuthDict['data'][account]['auth'] + auth = ApiAuthCache['data'][account]['auth'] assert isinstance(auth,EzAuth) # 3 获取每日商店 userdict = auth.get_userdict() @@ -187,7 +186,7 @@ async def login_request(request,method = "GET"): # 登录,获取用户的token auth = EzAuth() resw = await auth.authorize(account,passwd) - ApiAuthDict['data'][account] = {"auth": auth, "2fa": auth.is2fa } # 将对象插入 + ApiAuthCache['data'][account] = {"auth": auth, "2fa": auth.is2fa } # 将对象插入 # 没有成功,是2fa用户,需要执行/tfa if not resw['status']: return {'code': 0, 'message': "need provide email verify code", 'info': '2fa用户,请使用/tfa接口提供邮箱验证码'} @@ -205,6 +204,7 @@ async def login_request(request,method = "GET"): if method == "GET": # /shop-img 接口是get的 return await shop_get_request(params,account) # 保存cookie到本地 + ApiAuthLog.append(account) # 记录已缓存的用户账户(方便开机加载) auth.save_cookies(f"./log/cookie/api/{account}.cke") return {'code': 0, 'message': "auth success", 'info': '登录成功!'} @@ -226,12 +226,12 @@ async def tfa_code_requeset(request): vcode = params['vcode'] token = params['token'] - global ApiAuthDict - if account not in ApiAuthDict['data']: - return { 'code': 200,'message': 'Riot account not in ApiAuthDict', + global ApiAuthCache + if account not in ApiAuthCache['data']: + return { 'code': 200,'message': 'Riot account not in ApiAuthCache', 'info': '拳头账户不在dict中,请先请求/shop-img或/login接口' } try: - auth = ApiAuthDict['data'][account]['auth'] + auth = ApiAuthCache['data'][account]['auth'] assert isinstance(auth,EzAuth) res = await auth.email_verfiy(vcode) except EzAuthExp.MultifactorError as result: @@ -243,6 +243,7 @@ async def tfa_code_requeset(request): # 走到这里,代表不是2fa用户,且登陆成功 print(f'[{GetTime()}] [Api] 2fa user auth success') # 保存cookie到本地 + ApiAuthLog.append(account) # 记录已缓存的用户账户(方便开机加载) auth.save_cookies(f"./log/cookie/api/{account}.cke") return {'code': 0, 'message': "2fa auth success", 'info': '2fa用户登录成功!'} From 56e301dc2016338e8b94d86b3f648f0bedd45c2d Mon Sep 17 00:00:00 2001 From: musnow Date: Sun, 26 Feb 2023 21:25:04 +0800 Subject: [PATCH 11/24] fix(ApiHandler): add reauthorize check in shop --- code/utils/api/ApiHandler.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/utils/api/ApiHandler.py b/code/utils/api/ApiHandler.py index 1ccacfa..c9c6a14 100644 --- a/code/utils/api/ApiHandler.py +++ b/code/utils/api/ApiHandler.py @@ -144,6 +144,11 @@ async def shop_get_request(params,account:str): # 2.1 判断通过,获取auth auth = ApiAuthCache['data'][account]['auth'] assert isinstance(auth,EzAuth) + # 2.2 重新登录 + ret = await auth.reauthorize() + if not ret: + return { "code":200,"message":"缓存信息失效,需要重新登录", + "info":"cache reauthorize failed,please /login" } # 3 获取每日商店 userdict = auth.get_userdict() resp = await fetch_daily_shop(userdict) From 8f066e358a5dfb19e51d441cf7555dceb76aeb5c Mon Sep 17 00:00:00 2001 From: musnow Date: Mon, 27 Feb 2023 18:19:05 +0800 Subject: [PATCH 12/24] fix(main): fix key err in tfa auth refactor(FileManage): rename UserTokenDict/UserApLog to UserRiotName/UserPwdReauth --- code/main.py | 65 +++++++++++++++++++++------------------- code/utils/FileManage.py | 4 +-- 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/code/main.py b/code/main.py index 6b53cd9..ea6756d 100644 --- a/code/main.py +++ b/code/main.py @@ -426,7 +426,7 @@ async def dx(msg: Message): ###########################################vip###################################################### #用来存放roll的频道/服务器/回应用户的dict -from utils.FileManage import VipShopBgDict,VipRollDcit,UserApLog +from utils.FileManage import VipShopBgDict,VipRollDcit,UserPwdReauth # 新建vip的uuid,第一个参数是天数,第二个参数是数量 @bot.command(name="vip-a") @@ -863,7 +863,7 @@ async def vip_time_add(msg: Message, vday: int = 1, *arg): ##################################################################################### # 预加载用户的riot游戏id和玩家uuid(登录后Api获取) -from utils.FileManage import UserTokenDict,SkinNotifyDict,EmojiDict,SkinRateDict +from utils.FileManage import UserRiotName,SkinNotifyDict,EmojiDict,SkinRateDict # 用来存放auth对象(无法直接保存到文件) UserAuthDict = {'AP': {}} @@ -889,9 +889,9 @@ def check_rate_err_user(user_id: str): # 判断uuid是否相等(用户有没有切换登录账户) def isSame_Authuuid(msg: Message): - """UserShopDict[msg.author_id]["auth_user_id"] == UserTokenDict[msg.author_id]["auth_user_id"] + """UserShopDict[msg.author_id]["auth_user_id"] == UserRiotName[msg.author_id]["auth_user_id"] """ - return UserShopDict[msg.author_id]["auth_user_id"] == UserTokenDict[msg.author_id]["auth_user_id"] + return UserShopDict[msg.author_id]["auth_user_id"] == UserRiotName[msg.author_id]["auth_user_id"] # 检查全局用户登录速率 async def check_GloginRate(): @@ -919,7 +919,7 @@ async def check_UserAuthDict_len(msg: Message): async def login(msg: Message, user: str = 'err', passwd: str = 'err', apSave='', *arg): print(f"[{GetTime()}] Au:{msg.author_id}_{msg.author.username}#{msg.author.identify_num} = /login {apSave}") log_bot_user(msg.author_id) #这个操作只是用来记录用户和cmd总数的 - global Login_Forbidden, login_rate_limit, UserTokenDict, UserAuthDict + global Login_Forbidden, login_rate_limit, UserRiotName, UserAuthDict if not isinstance(msg, PrivateMessage): # 不是私聊的话,禁止调用本命令 await msg.reply(f"为了避免您的账户信息泄漏,请「私聊」使用本命令!\n用法:`/login 账户 密码`") return @@ -947,13 +947,13 @@ async def login(msg: Message, user: str = 'err', passwd: str = 'err', apSave='', return # 4.如果没有抛出异常,那就是完成登录了,设置用户的玩家uuid+昵称 - UserTokenDict[msg.author_id] = { + UserRiotName[msg.author_id] = { 'auth_user_id': auth.user_id, 'GameName': auth.Name, 'TagLine': auth.Tag } # 设置基础打印信息 - text = f"登陆成功!欢迎回来,{UserTokenDict[msg.author_id]['GameName']}#{UserTokenDict[msg.author_id]['TagLine']}" + text = f"登陆成功!欢迎回来,{UserRiotName[msg.author_id]['GameName']}#{UserRiotName[msg.author_id]['TagLine']}" info_text = "当前cookie有效期为2~3天,有任何问题请[点我](https://kook.top/gpbTwZ)" # 5.如果是vip用户,则执行下面的代码 @@ -967,8 +967,8 @@ async def login(msg: Message, user: str = 'err', passwd: str = 'err', apSave='', # 6.用户自己选择是否保存账户密码,默认是不保存的;2fa用户也不会保存 if apSave == 'save' and (not auth.is2fa): # 不在这里再新建(用于保存阿狸使用账户密码重登的时间,告知用户) - if msg.author_id not in UserApLog: - UserApLog[msg.author_id] = {} + if msg.author_id not in UserPwdReauth: + UserPwdReauth[msg.author_id] = {} UserAuthDict['AP'][msg.author_id] = {'a': user, 'p': passwd} info_text += "\n您选择了保存账户密码,cookie失效后将使用账户密码重登" @@ -978,7 +978,7 @@ async def login(msg: Message, user: str = 'err', passwd: str = 'err', apSave='', # 8.全部都搞定了,打印登录信息日志 print( - f"[Login] Au:{msg.author_id} - {UserTokenDict[msg.author_id]['GameName']}#{UserTokenDict[msg.author_id]['TagLine']}" + f"[Login] Au:{msg.author_id} - {UserRiotName[msg.author_id]['GameName']}#{UserRiotName[msg.author_id]['TagLine']}" ) except EzAuthExp.AuthenticationError as result: print(f"ERR! [{GetTime()}] login Au:{msg.author_id} - {result}") @@ -1053,7 +1053,12 @@ async def tfa_verify(msg: Message, tfa: str, *arg): # 3.进行邮箱验证 res = await auth.email_verfiy(tfa) # 4.成功 - text = f"登陆成功!欢迎回来,{UserTokenDict[msg.author_id]['GameName']}#{UserTokenDict[msg.author_id]['TagLine']}" + UserRiotName[msg.author_id] = { + 'auth_user_id': auth.user_id, + 'GameName': auth.Name, + 'TagLine': auth.Tag + } + text = f"登陆成功!欢迎回来,{UserRiotName[msg.author_id]['GameName']}#{UserRiotName[msg.author_id]['TagLine']}" info_text = "当前cookie有效期为2~3天,有任何问题请[点我](https://kook.top/gpbTwZ)" cm = await get_card(text, info_text, icon_cm.correct) await upd_card(send_msg['msg_id'], cm, channel_type=msg.channel_type) @@ -1074,15 +1079,15 @@ async def tfa_verify(msg: Message, tfa: str, *arg): async def logout(msg: Message, *arg): logging(msg) try: - global UserTokenDict, UserAuthDict + global UserRiotName, UserAuthDict if msg.author_id not in UserAuthDict: #使用not in判断是否不存在 cm = await get_card("您尚未登陆!无须logout", "阿巴阿巴?", icon_cm.whats_that) await msg.reply(cm) return - log_text = f"[Logout] Au:{msg.author_id} - {UserTokenDict[msg.author_id]['GameName']}#{UserTokenDict[msg.author_id]['TagLine']}" + log_text = f"[Logout] Au:{msg.author_id} - {UserRiotName[msg.author_id]['GameName']}#{UserRiotName[msg.author_id]['TagLine']}" # 如果id存在,删除auth对象 - # 因为UserTokenDict里面只存放了用户游戏名/uuid,且不作为是否登录的判断,所以不需要删除 + # 因为UserRiotName里面只存放了用户游戏名/uuid,且不作为是否登录的判断,所以不需要删除 del UserAuthDict[msg.author_id] # 如果是vip用户,删除本地保存的cookie cookie_path = f"./log/cookie/{msg.author_id}.cke" @@ -1091,7 +1096,7 @@ async def logout(msg: Message, *arg): os.remove(cookie_path) # 删除文件 log_text+= " - rm cookie file" - text = f"已退出登录!下次再见,{UserTokenDict[msg.author_id]['GameName']}#{UserTokenDict[msg.author_id]['TagLine']}" + text = f"已退出登录!下次再见,{UserRiotName[msg.author_id]['GameName']}#{UserRiotName[msg.author_id]['TagLine']}" cm = await get_card(text, "你会回来的,对吗?", icon_cm.crying_crab) await msg.reply(cm) print(log_text) @@ -1103,16 +1108,16 @@ async def logout(msg: Message, *arg): async def login_acpw(msg:Message,*arg): logging(msg) try: - if msg.author_id not in UserApLog: + if msg.author_id not in UserPwdReauth: await msg.reply(f"您没有保存账户密码或2fa用户,该命令无效") return send_text='none' - if len(UserApLog[msg.author_id]) == 0: + if len(UserPwdReauth[msg.author_id]) == 0: send_text = "阿狸还没有用过您的账户密码来重新登录呢" else: send_text = '以下为账户密码登录日志\n' - for i in UserApLog[msg.author_id]: - send_text+=f"{i} - {UserApLog[msg.author_id][i]}\n" + for i in UserPwdReauth[msg.author_id]: + send_text+=f"{i} - {UserPwdReauth[msg.author_id][i]}\n" # 发送信息 await msg.reply(send_text) except Exception as result: # 其他错误 @@ -1123,7 +1128,7 @@ async def login_acpw(msg:Message,*arg): async def login_reauth(kook_user_id: str): base_print = f"[{GetTime()}] Au:{kook_user_id} = " print(base_print + "auth_token failure,trying reauthorize()") - global UserAuthDict,UserTokenDict + global UserAuthDict,UserRiotName auth = UserAuthDict[kook_user_id]['auth'] assert isinstance(auth,EzAuth) #用cookie重新登录,会返回一个bool是否成功 @@ -1144,7 +1149,7 @@ async def login_reauth(kook_user_id: str): UserAuthDict[kook_user_id]['auth'] = auth auth.save_cookies(f"./log/cookie/{kook_user_id}.cke") # 保存cookie # 记录使用账户密码重新登录的时间 - UserApLog[kook_user_id][GetTime()] = UserTokenDict[kook_user_id]['GameName'] + UserPwdReauth[kook_user_id][GetTime()] = UserRiotName[kook_user_id]['GameName'] print(base_print + "authflow() by AP") ret = True # 正好返回auth.reauthorize()的bool @@ -1255,7 +1260,7 @@ async def get_daily_shop(msg: Message, *arg): reau = await check_reauth("每日商店", msg) if reau == False: return #如果为假说明重新登录失败 # 重新获取token成功,从dict中获取玩家id - player_gamename = f"{UserTokenDict[msg.author_id]['GameName']}#{UserTokenDict[msg.author_id]['TagLine']}" + player_gamename = f"{UserRiotName[msg.author_id]['GameName']}#{UserRiotName[msg.author_id]['TagLine']}" # 获取玩家id成功了,再提示正在获取商店 cm = await get_card("正在尝试获取您的每日商店", "阿狸正在施法,很快就好啦!", icon_cm.duck) if isinstance(reau, dict): #如果传过来的是一个dict,说明重新登录成功且发送了消息 @@ -1288,7 +1293,7 @@ async def get_daily_shop(msg: Message, *arg): timeout = time.strftime("%H:%M:%S", time.gmtime(timeout)) # 将秒数转为标准时间 # 需要设置uuid来保证是同一个用户,方便同日的下次查询 UserShopDict[msg.author_id] = {} - UserShopDict[msg.author_id]["auth_user_id"] = UserTokenDict[msg.author_id]["auth_user_id"] + UserShopDict[msg.author_id]["auth_user_id"] = UserRiotName[msg.author_id]["auth_user_id"] UserShopDict[msg.author_id]["SkinsPanelLayout"] = resp["SkinsPanelLayout"] log_time += f"[Api_shop] {format(time.time()-a_time,'.4f')} " @@ -1437,7 +1442,7 @@ async def get_night_market(msg: Message, *arg): c = Card(color='#fb4b57') c.append( Module.Header( - f"玩家 {UserTokenDict[msg.author_id]['GameName']}#{UserTokenDict[msg.author_id]['TagLine']} 的夜市!")) + f"玩家 {UserRiotName[msg.author_id]['GameName']}#{UserRiotName[msg.author_id]['TagLine']} 的夜市!")) for Bonus in resp["BonusStore"]["BonusStoreOffers"]: skin = fetch_skin_bylist(Bonus["Offer"]["OfferID"]) skin_icon = skin["data"]['levels'][0]["displayIcon"] @@ -1553,7 +1558,7 @@ async def get_user_card(msg: Message, *arg): c = Card(color='#fb4b57') c.append( Module.Header( - f"玩家 {UserTokenDict[msg.author_id]['GameName']}#{UserTokenDict[msg.author_id]['TagLine']} 的个人信息")) + f"玩家 {UserRiotName[msg.author_id]['GameName']}#{UserRiotName[msg.author_id]['TagLine']} 的个人信息")) c.append(Module.Container(Element.Image(src=player_card['data']['wideArt']))) #将图片插入进去 text = f"玩家称号:" + player_title['data']['displayName'] + "\n" text+= f"玩家等级:{player_level} - 经验值:{player_level_xp}\n" @@ -2072,7 +2077,7 @@ async def auto_skin_notify(): await ShopRate.check_shop_rate(vip, list_shop) #计算用户商店得分 #vip用户会提前缓存当日商店,需要设置uuid来保证是同一个游戏用户 UserShopDict[vip] = {} - UserShopDict[vip]["auth_user_id"] = UserTokenDict[vip]["auth_user_id"] + UserShopDict[vip]["auth_user_id"] = UserRiotName[vip]["auth_user_id"] UserShopDict[vip]["SkinsPanelLayout"] = resp["SkinsPanelLayout"] #直接获取商店图片 draw_time = time.time() #开始计算画图需要的时间 @@ -2114,14 +2119,14 @@ async def auto_skin_notify(): if shop_text == "err": c.append( Module.Header( - f"早安!玩家 {UserTokenDict[vip]['GameName']}#{UserTokenDict[vip]['TagLine']} 的每日商店")) + f"早安!玩家 {UserRiotName[vip]['GameName']}#{UserRiotName[vip]['TagLine']} 的每日商店")) c.append(Module.Context(f"失效时间剩余: {timeout} 本次查询用时: {using_time}s")) c.append(Module.Container(Element.Image(src=dailyshop_img_src))) else: c.append( Module.Section( Element.Text( - f"早安!玩家 {UserTokenDict[vip]['GameName']}#{UserTokenDict[vip]['TagLine']}", + f"早安!玩家 {UserRiotName[vip]['GameName']}#{UserRiotName[vip]['TagLine']}", Types.Text.KMD), Element.Image(src=icon_cm.shot_on_fire, size='sm'))) c.append(Module.Section(Element.Text(shop_text, Types.Text.KMD))) c.append(Module.Context(Element.Text(f"这里有没有你想要的枪皮呢?", Types.Text.KMD))) @@ -2327,8 +2332,8 @@ async def loading_channel_cookie(): UserAuthDict[user] = {"auth": auth, "2fa": False} #将对象插入 log_str_success += f"({user})" #print(f"[BOT.TASK] Au:{user} - load cookie success!") - #不用重新修改UserTokenDict里面的游戏名和uuid - #因为UserTokenDict是在login的时候保存的,只要用户没有切换账户 + #不用重新修改UserRiotName里面的游戏名和uuid + #因为UserRiotName是在login的时候保存的,只要用户没有切换账户 #那么玩家id和uuid都是不会变化的,也没必要重新加载 else: log_str_failed += f"({user}) " diff --git a/code/utils/FileManage.py b/code/utils/FileManage.py index da0646b..2fe6d11 100644 --- a/code/utils/FileManage.py +++ b/code/utils/FileManage.py @@ -141,8 +141,8 @@ async def save_aio(self): SkinNotifyDict = FileManage("./log/UserSkinNotify.json") # 皮肤提醒 用户记录 GameIdDict = FileManage("./log/game_idsave.json") # 玩家游戏id保存 UserAuthID = FileManage("./log/UserAuthID.json") # 用户游戏id/uuid,账户密码重登记录 -UserTokenDict = UserAuthID['data'] # riot用户游戏id和uuid -UserApLog = UserAuthID['ap_log'] # 账户密码重登记录 +UserRiotName = UserAuthID['data'] # riot用户游戏id和uuid +UserPwdReauth = UserAuthID['ap_log'] # 账户密码重登记录 ApiAuthLog = UserAuthID['api_log'] # api 缓存用户的account记录 ApiAuthCache = {'data':{}} # api EzAuth对象缓存 From 86604b0dcf4c01b1ca7d58540e86d2ea8d80a6d8 Mon Sep 17 00:00:00 2001 From: musnow Date: Mon, 27 Feb 2023 18:32:37 +0800 Subject: [PATCH 13/24] fix(main): modify rules to on_message, update khl.py==0.3.15 fix(ApiHandler): add account check of ApiAuthLog --- code/main.py | 22 ++++++++++------------ code/utils/api/ApiHandler.py | 6 ++++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/code/main.py b/code/main.py index ea6756d..a048cd6 100644 --- a/code/main.py +++ b/code/main.py @@ -1,5 +1,4 @@ # encoding: utf-8: -import json import os import io import random @@ -11,10 +10,8 @@ import copy import zhconv import asyncio -import threading from khl import (Bot, Event, EventTypes, Message, PrivateMessage, requester) from khl.card import Card, CardMessage, Element, Module, Types, Struct -from khl.command import Rule from aiohttp import client_exceptions from PIL import Image, UnidentifiedImageError # 用于合成图片 @@ -129,16 +126,17 @@ async def Vhelp(msg: Message, *arg): # 当有人@机器人的时候进行回复,可识别出是否为机器人作者 -@bot.command(regex=r'(.+)', rules=[Rule.is_bot_mentioned(bot)]) -async def atAhri(msg: Message, mention_str: str): - logging(msg) +@bot.on_message() +async def atAhri(msg: Message): try: - if msg.author_id == master_id: - text = help_develop() - await msg.reply(text) - else: - await msg.reply(f"呀,听说有人想我了,是吗?\n输入`/ahri`打开帮助面板,和阿狸一起玩吧!") - print(f"[atAhri] Au:{msg.author_id} msg.reply success!") + if f"(met){bot.me.id}(met)" in msg.content: + logging(msg) + if msg.author_id == master_id: + text = help_develop() + await msg.reply(text) + else: + await msg.reply(f"呀,听说有人想我了,是吗?\n输入`/ahri` 或 `/vhelp` 打开帮助面板,和阿狸一起玩吧!") + print(f"[atAhri] Au:{msg.author_id} msg.reply success!") except: err_str = f"ERR! [{GetTime()}] atAhri\n```\n{traceback.format_exc()}\n```" await msg.reply(f"{err_str}") diff --git a/code/utils/api/ApiHandler.py b/code/utils/api/ApiHandler.py index c9c6a14..94e9a89 100644 --- a/code/utils/api/ApiHandler.py +++ b/code/utils/api/ApiHandler.py @@ -209,7 +209,8 @@ async def login_request(request,method = "GET"): if method == "GET": # /shop-img 接口是get的 return await shop_get_request(params,account) # 保存cookie到本地 - ApiAuthLog.append(account) # 记录已缓存的用户账户(方便开机加载) + if account not in ApiAuthLog: + ApiAuthLog.append(account) # 记录已缓存的用户账户(方便开机加载) auth.save_cookies(f"./log/cookie/api/{account}.cke") return {'code': 0, 'message': "auth success", 'info': '登录成功!'} @@ -248,7 +249,8 @@ async def tfa_code_requeset(request): # 走到这里,代表不是2fa用户,且登陆成功 print(f'[{GetTime()}] [Api] 2fa user auth success') # 保存cookie到本地 - ApiAuthLog.append(account) # 记录已缓存的用户账户(方便开机加载) + if account not in ApiAuthLog: + ApiAuthLog.append(account) # 记录已缓存的用户账户(方便开机加载) auth.save_cookies(f"./log/cookie/api/{account}.cke") return {'code': 0, 'message': "2fa auth success", 'info': '2fa用户登录成功!'} From 2345329643454036ee6e1f2f82588002450fcfb3 Mon Sep 17 00:00:00 2001 From: musnow Date: Mon, 27 Feb 2023 18:37:27 +0800 Subject: [PATCH 14/24] docs(requirements): update requirements.txt --- requirements.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 373313c..d3e54c7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,9 @@ aiofiles==23.1.0 aiohttp==3.8.1 -khl.py==0.3.7 +khl.py==0.3.15 leancloud==2.9.12 pandas==1.5.2 Pillow==9.4.0 psutil==5.9.4 requests==2.28.1 -riot-auth @ git+https://github.com/floxay/python-riot-auth.git@e70f76002728b99005baccd6fe3157c03d4d9f02 zhconv==1.4.3 From 870777b6d944d7533bff4920ba43a346f51bb698 Mon Sep 17 00:00:00 2001 From: musnow Date: Mon, 27 Feb 2023 22:37:12 +0800 Subject: [PATCH 15/24] refactor(main): short import and style changed --- code/main.py | 281 +++++++++++++++++++++++++-------------------------- 1 file changed, 135 insertions(+), 146 deletions(-) diff --git a/code/main.py b/code/main.py index a048cd6..740f7ad 100644 --- a/code/main.py +++ b/code/main.py @@ -1,6 +1,5 @@ # encoding: utf-8: -import os -import io +import os, io import random import time import traceback @@ -13,26 +12,19 @@ from khl import (Bot, Event, EventTypes, Message, PrivateMessage, requester) from khl.card import Card, CardMessage, Element, Module, Types, Struct from aiohttp import client_exceptions -from PIL import Image, UnidentifiedImageError # 用于合成图片 +from PIL import Image, UnidentifiedImageError # 用于合成图片 -from utils import ShopRate -from utils.Help import help_main, help_val, help_develop -from utils.BotLog import logging, log_bot_list, log_bot_user, log_bot_list_text, APIRequestFailed_Handler, BaseException_Handler,get_proc_info -from utils.Other import weather +from utils import ShopRate, ShopImg, Help, GrantRoles, Translate, BotVip, Other +from utils.valorant import ValFileUpd +from utils.BotLog import logging, log_bot_list, log_bot_user, log_bot_list_text, APIRequestFailed_Handler, BaseException_Handler, get_proc_info from utils.KookApi import (icon_cm, status_active_game, status_active_music, status_delete, bot_offline, upd_card, - get_card) -from utils.GrantRoles import (Color_GrantRole, Color_SetGm, Color_SetMsg, THX_Sponser) + get_card) from utils.valorant.Val import * -from utils.valorant.EzAuth import EzAuth,EzAuthExp +from utils.valorant.EzAuth import EzAuth, EzAuthExp from utils.Gtime import GetTime, GetTimeStampOf8AM -from utils.BotVip import (VipUserDict, create_vip_uuid, fetch_vip_user, roll_vip_start, using_vip_uuid, vip_ck, - vip_time_remain, vip_time_remain_cm, vip_time_stamp,get_vip_shop_bg_cm,replace_illegal_img,illegal_img_169) -from utils.Translate import ListTL, translate_main, Shutdown_TL, checkTL, Open_TL, Close_TL -from utils.ShopImg import get_shop_img_11, get_shop_img_169, img_requestor -from utils.valorant.ValFileUpd import update_bundle_url, update_price, update_skins # bot的token文件 -from utils.FileManage import config, Save_All_File,ApiAuthLog +from utils.FileManage import config, Save_All_File, ApiAuthLog, VipUserDict # 用读取来的 config 初始化 bot,字段对应即可 bot = Bot(token=config['token']['bot']) # 只用来上传图片的bot @@ -73,9 +65,9 @@ async def Save_File_Task(): @bot.command(name='kill') -async def KillBot(msg: Message,num:str='124124', *arg): +async def KillBot(msg: Message, num: str = '124124', *arg): logging(msg) - if msg.author_id == master_id and int(num)==config['no']: + if msg.author_id == master_id and int(num) == config['no']: # 保存所有文件 await Save_All_File(False) await msg.reply(f"[KILL] 保存全局变量成功,bot下线") @@ -102,7 +94,7 @@ async def world(msg: Message): async def Ahri(msg: Message, *arg): logging(msg) try: - cm = help_main(start_time) + cm = Help.help_main(start_time) await msg.reply(cm) except Exception as result: await BaseException_Handler("ahri", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") @@ -116,7 +108,7 @@ async def Ahri(msg: Message, *arg): async def Vhelp(msg: Message, *arg): logging(msg) try: - cm = help_val() + cm = Help.help_val() await msg.reply(cm) except Exception as result: await BaseException_Handler("vhelp", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") @@ -132,7 +124,7 @@ async def atAhri(msg: Message): if f"(met){bot.me.id}(met)" in msg.content: logging(msg) if msg.author_id == master_id: - text = help_develop() + text = Help.help_develop() await msg.reply(text) else: await msg.reply(f"呀,听说有人想我了,是吗?\n输入`/ahri` 或 `/vhelp` 打开帮助面板,和阿狸一起玩吧!") @@ -204,7 +196,7 @@ async def Weather(msg: Message, city: str = "err"): return try: - await weather(msg, city) + await Other.weather(msg, city) except Exception as result: await BaseException_Handler("Weather", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") err_str = f"ERR! [{GetTime()}] Weather\n```\n{traceback.format_exc()}\n```" @@ -220,13 +212,13 @@ async def Weather(msg: Message, city: str = "err"): async def Color_Set_GM(msg: Message, Card_Msg_id: str): logging(msg) if msg.author_id == master_id: - await Color_SetGm(msg, Card_Msg_id) + await GrantRoles.Color_SetGm(msg, Card_Msg_id) # 判断消息的emoji回应,并给予不同角色 @bot.on_event(EventTypes.ADDED_REACTION) async def Grant_Roles(b: Bot, event: Event): - await Color_GrantRole(b, event) + await GrantRoles.Color_GrantRole(b, event) # 给用户上色(在发出消息后,机器人自动添加回应) @@ -234,13 +226,13 @@ async def Grant_Roles(b: Bot, event: Event): async def Color_Set(msg: Message): logging(msg) if msg.author_id == master_id: - await Color_SetMsg(bot, msg) + await GrantRoles.Color_SetMsg(bot, msg) # 感谢助力者(每天19点进行检查) @bot.task.add_cron(hour=19, minute=0, timezone="Asia/Shanghai") async def thanks_sponser(): - await THX_Sponser(bot) + await GrantRoles.THX_Sponser(bot) ######################################## Translate ################################################ @@ -250,14 +242,14 @@ async def thanks_sponser(): @bot.command(name='TL', aliases=['tl']) async def translation(msg: Message, *arg): logging(msg) - await translate_main(msg, ' '.join(arg)) + await Translate.translate_main(msg, ' '.join(arg)) #查看当前占用的实时翻译栏位 @bot.command() async def CheckTL(msg: Message): logging(msg) - await msg.reply(f"目前已使用栏位:{checkTL()}/{len(ListTL)}") + await msg.reply(f"目前已使用栏位:{Translate.checkTL()}/{len(Translate.ListTL)}") # 关闭所有栏位的实时翻译(避免有些人用完不关) @@ -266,34 +258,34 @@ async def ShutdownTL(msg: Message): logging(msg) if msg.author.id != master_id: return #这条命令只有bot的作者可以调用 - await Shutdown_TL(bot, msg) + await Translate.Shutdown_TL(bot, msg) # 通过频道id判断是否实时翻译本频道内容 @bot.command(regex=r'(.+)') async def TL_Realtime(msg: Message, *arg): - if msg.ctx.channel.id in ListTL: #判断频道是否已开启实时翻译 + if msg.ctx.channel.id in Translate.ListTL: #判断频道是否已开启实时翻译 word = " ".join(arg) # 不翻译关闭实时翻译的指令 if word == "/TLOFF" or word == "/tloff" or word == '/tlon' or word == '/TLON': return # 翻译 logging(msg) - await translate_main(msg, ' '.join(arg)) + await Translate.translate_main(msg, ' '.join(arg)) # 开启实时翻译功能 @bot.command(name='TLON', aliases=['tlon']) async def TLON(msg: Message): logging(msg) - await Open_TL(msg) + await Translate.Open_TL(msg) # 关闭实时翻译功能 @bot.command(name='TLOFF', aliases=['tloff']) async def TLOFF(msg: Message): logging(msg) - await Close_TL(msg) + await Translate.Close_TL(msg) ########################################################################################### @@ -424,7 +416,8 @@ async def dx(msg: Message): ###########################################vip###################################################### #用来存放roll的频道/服务器/回应用户的dict -from utils.FileManage import VipShopBgDict,VipRollDcit,UserPwdReauth +from utils.FileManage import VipShopBgDict, VipRollDcit, UserPwdReauth + # 新建vip的uuid,第一个参数是天数,第二个参数是数量 @bot.command(name="vip-a") @@ -432,7 +425,7 @@ async def get_vip_uuid(msg: Message, day: int = 30, num: int = 10): logging(msg) try: if msg.author_id == master_id: - text = await create_vip_uuid(num, day) + text = await BotVip.create_vip_uuid(num, day) cm = CardMessage() c = Card(Module.Header(f"已生成新的uuid 数量:{num} 天数:{day}"), Module.Divider(), @@ -458,7 +451,7 @@ async def buy_vip_uuid(msg: Message, uuid: str = 'err', *arg): return try: #把bot传过去是为了让阿狸在有人成兑换激活码之后发送消息到log频道 - ret = await using_vip_uuid(msg, uuid, bot, debug_ch) + ret = await BotVip.using_vip_uuid(msg, uuid, bot, debug_ch) global VipShopBgDict #在用户兑换vip的时候就创建此键值 VipShopBgDict['cache'][msg.author_id] = {'cache_time': 0, 'cache_img': None} except Exception as result: @@ -473,11 +466,11 @@ async def buy_vip_uuid(msg: Message, uuid: str = 'err', *arg): async def check_vip_timeremain(msg: Message, *arg): logging(msg) try: - if not await vip_ck(msg): + if not await BotVip.vip_ck(msg): return # 获取时间 - ret_t = vip_time_remain(msg.author_id) - ret_cm = await vip_time_remain_cm(ret_t) + ret_t = BotVip.vip_time_remain(msg.author_id) + ret_cm = await BotVip.vip_time_remain_cm(ret_t) await msg.reply(ret_cm) except Exception as result: await BaseException_Handler("vip-c", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") @@ -492,7 +485,7 @@ async def list_vip_user(msg: Message, *arg): logging(msg) try: if msg.author_id == master_id: - text = await fetch_vip_user() + text = await BotVip.fetch_vip_user() cm2 = CardMessage() c = Card(Module.Header(f"当前vip用户列表如下"), color='#e17f89') c.append(Module.Section(Element.Text(f"```\n{text}```", Types.Text.KMD))) @@ -523,7 +516,7 @@ async def check_vip_img(): i = 0 while i < sz: try: - bg_test = Image.open(io.BytesIO(await img_requestor(vip_bg["background"][i]))) + bg_test = Image.open(io.BytesIO(await ShopImg.img_requestor(vip_bg["background"][i]))) i += 1 except UnidentifiedImageError as result: err_str = f"ERR! [{GetTime()}] checking [{vip_user}] img\n```\n{result}\n" @@ -533,7 +526,7 @@ async def check_vip_img(): cm0.append(c) await user.send(cm0) # 发送私聊消息给用户 await bot.client.send(debug_ch, err_str) # 发送消息到debug频道 - vip_bg["background"][i] = illegal_img_169 #修改成16比9的图片 + vip_bg["background"][i] = BotVip.illegal_img_169 #修改成16比9的图片 vip_bg["status"] = False #需要重新加载图片 print(err_str) except Exception as result: @@ -573,9 +566,6 @@ async def check_vip_img_task(msg: Message, *arg): return - - - @bot.command(name="vip-shop") async def vip_shop_bg_set(msg: Message, icon: str = "err", *arg): logging(msg) @@ -584,7 +574,7 @@ async def vip_shop_bg_set(msg: Message, icon: str = "err", *arg): return try: - if not await vip_ck(msg): + if not await BotVip.vip_ck(msg): return x3 = "[None]" @@ -609,7 +599,7 @@ async def vip_shop_bg_set(msg: Message, icon: str = "err", *arg): print(f"[vip-shop] Au:{msg.author_id} img_type_not support") return #打开图片(测试) - bg_vip = Image.open(io.BytesIO(await img_requestor(x3))) + bg_vip = Image.open(io.BytesIO(await ShopImg.img_requestor(x3))) except UnidentifiedImageError as result: err_str = f"ERR! [{GetTime()}] vip_shop_imgck\n```\n{result}\n```" print(err_str) @@ -625,7 +615,7 @@ async def vip_shop_bg_set(msg: Message, icon: str = "err", *arg): #插入图片 VipShopBgDict['bg'][msg.author_id]["background"].append(x3) - cm = await get_vip_shop_bg_cm(msg) + cm = await BotVip.get_vip_shop_bg_cm(msg) #先让测试bot把这个卡片发到频道,如果发出去了说明json没有问题 await bot_upimg.client.send(cm_send_test, cm) print(f"[vip-shop] Au:{msg.author_id} cm_send_test success") @@ -651,7 +641,7 @@ async def vip_shop_bg_set_s(msg: Message, num: str = "err", *arg): return try: global VipShopBgDict - if not await vip_ck(msg): + if not await BotVip.vip_ck(msg): return if msg.author_id not in VipShopBgDict['bg']: await msg.reply("您尚未自定义商店背景图!") @@ -661,11 +651,11 @@ async def vip_shop_bg_set_s(msg: Message, num: str = "err", *arg): if num < len(VipShopBgDict['bg'][msg.author_id]["background"]): try: #打开用户需要切换的图片 bg_vip = Image.open( - io.BytesIO(await img_requestor(VipShopBgDict['bg'][msg.author_id]["background"][num]))) + io.BytesIO(await ShopImg.img_requestor(VipShopBgDict['bg'][msg.author_id]["background"][num]))) except UnidentifiedImageError as result: err_str = f"ERR! [{GetTime()}] vip_shop_s_imgck\n```\n{result}\n```" await msg.reply(f"图片违规!请重新上传\n{err_str}") - await replace_illegal_img(msg.author_id, num) #替换图片 + await BotVip.replace_illegal_img(msg.author_id, num) #替换图片 print(err_str) return # 图片检查通过,交换两个图片的位置 @@ -678,7 +668,7 @@ async def vip_shop_bg_set_s(msg: Message, num: str = "err", *arg): await msg.reply("请提供正确返回的图片序号,可以用`/vip-shop`进行查看") return - cm = await get_vip_shop_bg_cm(msg) + cm = await BotVip.get_vip_shop_bg_cm(msg) #先让测试bot把这个卡片发到频道,如果发出去了说明json没有问题 await bot_upimg.client.send(cm_send_test, cm) print(f"[vip-shop] Au:{msg.author_id} cm_send_test success") @@ -699,7 +689,7 @@ async def vip_shop_bg_set_d(msg: Message, num: str = "err", *arg): await msg.reply(f"请提供正确的图片序号!\n当前:`{num}`") return try: - if not await vip_ck(msg): + if not await BotVip.vip_ck(msg): return if msg.author_id not in VipShopBgDict['bg']: await msg.reply("您尚未自定义商店背景图!") @@ -717,7 +707,7 @@ async def vip_shop_bg_set_d(msg: Message, num: str = "err", *arg): await msg.reply("请提供正确返回的图片序号,可以用`/vip-shop`进行查看") return - cm = await get_vip_shop_bg_cm(msg) + cm = await BotVip.get_vip_shop_bg_cm(msg) #先让测试bot把这个卡片发到频道,如果发出去了说明json没有问题 await bot_upimg.client.send(cm_send_test, cm) print(f"[vip-shop] Au:{msg.author_id} cm_send_test success") @@ -759,7 +749,7 @@ async def vip_roll(msg: Message, vday: int = 7, vnum: int = 5, rday: float = 1.0 return # 设置开始抽奖 global VipRollDcit - cm = roll_vip_start(vnum, vday, rday) + cm = BotVip.roll_vip_start(vnum, vday, rday) roll_ch = await bot.client.fetch_public_channel(msg.ctx.channel.id) roll_send = await bot.client.send(roll_ch, cm) VipRollDcit[roll_send['msg_id']] = {} @@ -782,22 +772,22 @@ async def vip_roll_task(): continue else: print(f"[BOT.TASK] vip_roll_task msg:{msg_id}") - vday = VipRollDcit[msg_id]['days'] # vip天数 - vnum = VipRollDcit[msg_id]['nums'] # 奖品数量 + vday = VipRollDcit[msg_id]['days'] # vip天数 + vnum = VipRollDcit[msg_id]['nums'] # 奖品数量 # 结束抽奖 log_str = f"```\n[MsgID] {msg_id}\n" send_str = "恭喜 " # 人数大于奖品数量 - if len(VipRollDcit[msg_id]['user'])>vnum: - ran = random.sample(range(0, len(VipRollDcit[msg_id]['user'])), vnum) # 生成n个随机数 - else: # 生成一个从0到len-1的列表 如果只有一个用户,生成的是[0] + if len(VipRollDcit[msg_id]['user']) > vnum: + ran = random.sample(range(0, len(VipRollDcit[msg_id]['user'])), vnum) # 生成n个随机数 + else: # 生成一个从0到len-1的列表 如果只有一个用户,生成的是[0] ran = list(range(len(VipRollDcit[msg_id]['user']))) # 开始遍历 for j in ran: user_id = VipRollDcit[msg_id]['user'][j] user = await bot.client.fetch_user(user_id) # 设置用户的时间和个人信息 - time_vip = vip_time_stamp(user_id, vday) + time_vip = BotVip.vip_time_stamp(user_id, vday) VipUserDict[user_id] = {'time': time_vip, 'name_tag': f"{user.username}#{user.identify_num}"} # 创建卡片消息 cm = CardMessage() @@ -806,7 +796,7 @@ async def vip_roll_task(): Element.Image(src=icon_cm.ahri_kda2, size='sm'))) c.append(Module.Context(Element.Text(f"您抽中了{vday}天vip,可用/vhelp查看vip权益", Types.Text.KMD))) c.append( - Module.Countdown(datetime.now() + timedelta(seconds=vip_time_remain(user_id)), + Module.Countdown(datetime.now() + timedelta(seconds=BotVip.vip_time_remain(user_id)), mode=Types.CountdownMode.DAY)) c.append(Module.Divider()) c.append( @@ -847,7 +837,7 @@ async def vip_time_add(msg: Message, vday: int = 1, *arg): global VipUserDict # 给所有vip用户上天数 for vip, vinfo in VipUserDict.items(): - time_vip = vip_time_stamp(vip, vday) + time_vip = BotVip.vip_time_stamp(vip, vday) VipUserDict[vip]['time'] = time_vip await msg.reply(f"操作完成,已给所有vip用户增加 `{vday}` 天时长") @@ -861,7 +851,7 @@ async def vip_time_add(msg: Message, vday: int = 1, *arg): ##################################################################################### # 预加载用户的riot游戏id和玩家uuid(登录后Api获取) -from utils.FileManage import UserRiotName,SkinNotifyDict,EmojiDict,SkinRateDict +from utils.FileManage import UserRiotName, SkinNotifyDict, EmojiDict, SkinRateDict # 用来存放auth对象(无法直接保存到文件) UserAuthDict = {'AP': {}} @@ -885,12 +875,14 @@ def check_rate_err_user(user_id: str): """ return (user_id in SkinRateDict['err_user']) + # 判断uuid是否相等(用户有没有切换登录账户) def isSame_Authuuid(msg: Message): """UserShopDict[msg.author_id]["auth_user_id"] == UserRiotName[msg.author_id]["auth_user_id"] """ return UserShopDict[msg.author_id]["auth_user_id"] == UserRiotName[msg.author_id]["auth_user_id"] + # 检查全局用户登录速率 async def check_GloginRate(): global login_rate_limit @@ -936,8 +928,8 @@ async def login(msg: Message, user: str = 'err', passwd: str = 'err', apSave='', # 3.登录,获取用户的token auth = EzAuth() - resw = await auth.authorize(user,passwd) - UserAuthDict[msg.author_id] = {"auth": auth, "2fa": auth.is2fa } # 将对象插入 + resw = await auth.authorize(user, passwd) + UserAuthDict[msg.author_id] = {"auth": auth, "2fa": auth.is2fa} # 将对象插入 # 3.1 没有成功,是2fa用户,需要执行/tfa命令 if not resw['status']: cm1 = await get_card("登录中断,需要提供邮箱验证码", "请使用「/tfa 验证码」提供邮箱验证码", icon_cm.val_logo_gif) @@ -945,17 +937,13 @@ async def login(msg: Message, user: str = 'err', passwd: str = 'err', apSave='', return # 4.如果没有抛出异常,那就是完成登录了,设置用户的玩家uuid+昵称 - UserRiotName[msg.author_id] = { - 'auth_user_id': auth.user_id, - 'GameName': auth.Name, - 'TagLine': auth.Tag - } + UserRiotName[msg.author_id] = {'auth_user_id': auth.user_id, 'GameName': auth.Name, 'TagLine': auth.Tag} # 设置基础打印信息 text = f"登陆成功!欢迎回来,{UserRiotName[msg.author_id]['GameName']}#{UserRiotName[msg.author_id]['TagLine']}" info_text = "当前cookie有效期为2~3天,有任何问题请[点我](https://kook.top/gpbTwZ)" # 5.如果是vip用户,则执行下面的代码 - if await vip_ck(msg.author_id): + if await BotVip.vip_ck(msg.author_id): global VipShopBgDict #因为换了用户,所以需要修改状态码重新获取商店 if msg.author_id in VipShopBgDict['bg']: VipShopBgDict['bg'][msg.author_id]['status'] = False @@ -985,15 +973,15 @@ async def login(msg: Message, user: str = 'err', passwd: str = 'err', apSave='', await upd_card(send_msg['msg_id'], cm, channel_type=msg.channel_type) except EzAuthExp.WaitOvertimeError as result: print(f"ERR! [{GetTime()}] login Au:{msg.author_id} - {result}") - cm = await get_card("等待超时","auth wait overtime",icon_cm.lagging) + cm = await get_card("等待超时", "auth wait overtime", icon_cm.lagging) await upd_card(send_msg['msg_id'], cm, channel_type=msg.channel_type) except EzAuthExp.RatelimitError as result: err_str = f"ERR! [{GetTime()}] login Au:{msg.author_id} - {result}" # 更新全局速率限制 login_rate_limit = {'limit': True, 'time': time.time()} - print(err_str," set login_rate_limit = True") + print(err_str, " set login_rate_limit = True") # 这里是第一个出现速率限制err的用户,更新消息提示 - cm = await get_card(f"登录请求超速!请在{RATE_LIMITED_TIME}s后重试", "RatelimitError,try again later",icon_cm.lagging) + cm = await get_card(f"登录请求超速!请在{RATE_LIMITED_TIME}s后重试", "RatelimitError,try again later", icon_cm.lagging) await upd_card(send_msg['msg_id'], cm, channel_type=msg.channel_type) except client_exceptions.ClientResponseError as result: err_str = f"ERR! [{GetTime()}] login Au:{msg.author_id}\n```\n{traceback.format_exc()}\n```\n" @@ -1022,7 +1010,7 @@ async def login(msg: Message, user: str = 'err', passwd: str = 'err', apSave='', except requester.HTTPRequester.APIRequestFailed as result: #卡片消息发送失败 await APIRequestFailed_Handler("login", traceback.format_exc(), msg, bot, send_msg, cm) except Exception as result: # 其他错误 - err_str =f"[login] Au:{msg.author_id}\n```\n{traceback.format_exc()}\n```\n" + err_str = f"[login] Au:{msg.author_id}\n```\n{traceback.format_exc()}\n```\n" await upd_card(send_msg['msg_id'], err_str, channel_type=msg.channel_type) await BaseException_Handler("login", traceback.format_exc(), msg, bot, send_msg, cm) @@ -1034,7 +1022,7 @@ async def tfa_verify(msg: Message, tfa: str, *arg): await msg.reply(f"邮箱验证码长度错误,请确认您输入了正确的6位验证码\n当前参数:{tfa}") return - send_msg = {'msg_id':''} + send_msg = {'msg_id': ''} try: # 1. 先判断用户是否在dict里面 if msg.author_id not in UserAuthDict: @@ -1042,7 +1030,7 @@ async def tfa_verify(msg: Message, tfa: str, *arg): return # 1.1 在,且auth对象是ezauth auth = UserAuthDict[msg.author_id]['auth'] - assert isinstance(auth,EzAuth) + assert isinstance(auth, EzAuth) # 2.发送提示信息 cm0 = await get_card(f"两步验证码「{tfa}」获取成功", "小憩一下,很快就好啦!", icon_cm.val_logo_gif) @@ -1051,21 +1039,17 @@ async def tfa_verify(msg: Message, tfa: str, *arg): # 3.进行邮箱验证 res = await auth.email_verfiy(tfa) # 4.成功 - UserRiotName[msg.author_id] = { - 'auth_user_id': auth.user_id, - 'GameName': auth.Name, - 'TagLine': auth.Tag - } + UserRiotName[msg.author_id] = {'auth_user_id': auth.user_id, 'GameName': auth.Name, 'TagLine': auth.Tag} text = f"登陆成功!欢迎回来,{UserRiotName[msg.author_id]['GameName']}#{UserRiotName[msg.author_id]['TagLine']}" info_text = "当前cookie有效期为2~3天,有任何问题请[点我](https://kook.top/gpbTwZ)" cm = await get_card(text, info_text, icon_cm.correct) await upd_card(send_msg['msg_id'], cm, channel_type=msg.channel_type) - + except EzAuthExp.MultifactorError as result: if "multifactor_attempt_failed" in str(result): - cm = await get_card("两步验证码错误,请重试",str(result),icon_cm.lagging) + cm = await get_card("两步验证码错误,请重试", str(result), icon_cm.lagging) else: - cm = await get_card("邮箱验证错误,请重新login",str(result),icon_cm.lagging) + cm = await get_card("邮箱验证错误,请重新login", str(result), icon_cm.lagging) # 更新消息 await upd_card(send_msg['msg_id'], cm, channel_type=msg.channel_type) except Exception as result: # 其他错误 @@ -1086,13 +1070,13 @@ async def logout(msg: Message, *arg): log_text = f"[Logout] Au:{msg.author_id} - {UserRiotName[msg.author_id]['GameName']}#{UserRiotName[msg.author_id]['TagLine']}" # 如果id存在,删除auth对象 # 因为UserRiotName里面只存放了用户游戏名/uuid,且不作为是否登录的判断,所以不需要删除 - del UserAuthDict[msg.author_id] + del UserAuthDict[msg.author_id] # 如果是vip用户,删除本地保存的cookie cookie_path = f"./log/cookie/{msg.author_id}.cke" # 判断路径是否存在,存在直接删除 if os.path.exists(cookie_path): - os.remove(cookie_path) # 删除文件 - log_text+= " - rm cookie file" + os.remove(cookie_path) # 删除文件 + log_text += " - rm cookie file" text = f"已退出登录!下次再见,{UserRiotName[msg.author_id]['GameName']}#{UserRiotName[msg.author_id]['TagLine']}" cm = await get_card(text, "你会回来的,对吗?", icon_cm.crying_crab) @@ -1102,20 +1086,21 @@ async def logout(msg: Message, *arg): except Exception as result: # 其他错误 await BaseException_Handler("logout", traceback.format_exc(), msg, bot) + @bot.command(name='login-ap') -async def login_acpw(msg:Message,*arg): +async def login_acpw(msg: Message, *arg): logging(msg) try: if msg.author_id not in UserPwdReauth: await msg.reply(f"您没有保存账户密码或2fa用户,该命令无效") return - send_text='none' + send_text = 'none' if len(UserPwdReauth[msg.author_id]) == 0: send_text = "阿狸还没有用过您的账户密码来重新登录呢" else: send_text = '以下为账户密码登录日志\n' for i in UserPwdReauth[msg.author_id]: - send_text+=f"{i} - {UserPwdReauth[msg.author_id][i]}\n" + send_text += f"{i} - {UserPwdReauth[msg.author_id][i]}\n" # 发送信息 await msg.reply(send_text) except Exception as result: # 其他错误 @@ -1126,9 +1111,9 @@ async def login_acpw(msg:Message,*arg): async def login_reauth(kook_user_id: str): base_print = f"[{GetTime()}] Au:{kook_user_id} = " print(base_print + "auth_token failure,trying reauthorize()") - global UserAuthDict,UserRiotName + global UserAuthDict, UserRiotName auth = UserAuthDict[kook_user_id]['auth'] - assert isinstance(auth,EzAuth) + assert isinstance(auth, EzAuth) #用cookie重新登录,会返回一个bool是否成功 ret = await auth.reauthorize() if ret: #会返回一个bool是否成功,成功了重新赋值 @@ -1138,20 +1123,20 @@ async def login_reauth(kook_user_id: str): print(base_print + "reauthorize() Failed! T-T") # 失败打印 # 有保存账户密码+不是邮箱验证用户 if kook_user_id in UserAuthDict['AP'] and (not UserAuthDict[kook_user_id]['2fa']): - auth = EzAuth()# 用账户密码重新登录 + auth = EzAuth() # 用账户密码重新登录 resw = await auth.authorize(UserAuthDict['AP'][kook_user_id]['a'], UserAuthDict['AP'][kook_user_id]['p']) - if not resw['status']: # 需要邮箱验证,那就直接跳出 - print(base_print + "authorize() need 2fa, return False") + if not resw['status']: # 需要邮箱验证,那就直接跳出 + print(base_print + "authorize() need 2fa, return False") return False # 更新auth对象 UserAuthDict[kook_user_id]['auth'] = auth - auth.save_cookies(f"./log/cookie/{kook_user_id}.cke") # 保存cookie + auth.save_cookies(f"./log/cookie/{kook_user_id}.cke") # 保存cookie # 记录使用账户密码重新登录的时间 UserPwdReauth[kook_user_id][GetTime()] = UserRiotName[kook_user_id]['GameName'] print(base_print + "authflow() by AP") ret = True # 正好返回auth.reauthorize()的bool - return ret + return ret # 判断是否需要重新获取token @@ -1166,7 +1151,7 @@ async def check_reauth(def_name: str = "", msg: Union[Message, str] = ''): try: user_id = msg if isinstance(msg, str) else msg.author_id #如果是str就直接用 auth = UserAuthDict[user_id]['auth'] - assert isinstance(auth,EzAuth) + assert isinstance(auth, EzAuth) # 直接从对象中获取userdict userdict = auth.get_userdict() resp = await fetch_valorant_point(userdict) @@ -1214,7 +1199,6 @@ async def check_reauth(def_name: str = "", msg: Union[Message, str] = ''): return False - # 计算当前时间和明天早上8点的差值 def shop_time_remain(): today = datetime.today().strftime("%y-%m-%d %H:%M:%S") #今天日期+时间 @@ -1297,7 +1281,7 @@ async def get_daily_shop(msg: Message, *arg): # 开始画图 draw_time = time.time() #计算画图需要的时间 - is_vip = await vip_ck(msg.author_id) #判断用户是否为VIP + is_vip = await BotVip.vip_ck(msg.author_id) #判断用户是否为VIP img_ret = {'status': True, 'value': None} upload_flag = True # 初始化为一个展示错误的图片 @@ -1311,22 +1295,22 @@ async def get_daily_shop(msg: Message, *arg): # 如果没有设置背景图,那就设置为err background_img = ('err' if msg.author_id not in VipShopBgDict['bg'] else VipShopBgDict['bg'][msg.author_id]["background"][0]) - img_ret = await get_shop_img_169(list_shop, - vp=play_currency['vp'], - rp=play_currency['rp'], - bg_img_src=background_img) + img_ret = await ShopImg.get_shop_img_169(list_shop, + vp=play_currency['vp'], + rp=play_currency['rp'], + bg_img_src=background_img) else: # 普通用户 # 判断是否有缓存命中 cache_ret = await ShopRate.query_ShopCache(skinlist=list_shop) - if not cache_ret['status']: # 缓存没有命中 - img_ret = await get_shop_img_11(list_shop) - else: # 命中 + if not cache_ret['status']: # 缓存没有命中 + img_ret = await ShopImg.get_shop_img_11(list_shop) + else: # 命中 upload_flag = False dailyshop_img_src = cache_ret['img_url'] - log_time+="[cache] " + log_time += "[cache] " # img_ret 代表是否画图成功,如果是缓存命中,也当成功处理 - if img_ret['status']: + if img_ret['status']: bg = img_ret['value'] #获取图片 else: # 出现背景图片违规或其他问题 await msg.reply(img_ret['value']) @@ -1334,7 +1318,7 @@ async def get_daily_shop(msg: Message, *arg): return # 获取图片成功,打印画图耗时 - print(log_time+f"- [Drawing] {format(time.time() - draw_time,'.4f')} - [Au] {msg.author_id}") + print(log_time + f"- [Drawing] {format(time.time() - draw_time,'.4f')} - [Au] {msg.author_id}") # 判断是否需要上传,false不需要 if upload_flag: imgByteArr = io.BytesIO() @@ -1346,8 +1330,8 @@ async def get_daily_shop(msg: Message, *arg): VipShopBgDict['bg'][msg.author_id]['status'] = True # 设置商店图片缓存+图片缓存的时间 VipShopBgDict['cache'][msg.author_id] = {'cache_img': dailyshop_img_src, 'cache_time': time.time()} - else: # 非vip,更新缓存 - await ShopRate.update_ShopCache(skinlist=list_shop,img_url=dailyshop_img_src) + else: # 非vip,更新缓存 + await ShopRate.update_ShopCache(skinlist=list_shop, img_url=dailyshop_img_src) # 结束shop的总计时,结果为浮点数,保留两位小数 shop_using_time = format(time.perf_counter() - start, '.2f') @@ -1428,8 +1412,9 @@ async def get_night_market(msg: Message, *arg): resp = await fetch_daily_shop(userdict) #获取商店(夜市是相同接口) if "BonusStore" not in resp: # 如果没有这个字段,说明夜市取消了 NightMarketOff = False - cm1 = await get_card("嗷~ 夜市已关闭 或 Api没能正确返回结果","night_market closed! 'BonusStore' not in resp", icon_cm.duck) - await upd_card(send_msg['msg_id'], cm1, channel_type=msg.channel_type) # 更新消息 + cm1 = await get_card("嗷~ 夜市已关闭 或 Api没能正确返回结果", "night_market closed! 'BonusStore' not in resp", + icon_cm.duck) + await upd_card(send_msg['msg_id'], cm1, channel_type=msg.channel_type) # 更新消息 print("[night_market] night_market closed! 'BonusStore' not in resp") return @@ -1540,7 +1525,7 @@ async def get_user_card(msg: Message, *arg): } print(f"ERR![player_title] Au:{msg.author_id} uuid:{resp['Identity']['PlayerTitleID']}") # 可能遇到全新账户(没打过游戏)的情况 - if resp['Guns'] == None or resp['Sprays'] == None: + if resp['Guns'] == None or resp['Sprays'] == None: cm = await get_card(f"状态错误!您是否登录了一个全新的账户?", f"card: `{player_card}`\ntitle: `{player_title}`", icon_cm.whats_that) await upd_card(send_msg['msg_id'], cm, channel_type=msg.channel_type) @@ -1548,10 +1533,10 @@ async def get_user_card(msg: Message, *arg): # 获取玩家等级 resp = await fetch_player_level(userdict) - player_level = resp["Progress"]["Level"] # 玩家等级 - player_level_xp = resp["Progress"]["XP"] # 玩家等级经验值 + player_level = resp["Progress"]["Level"] # 玩家等级 + player_level_xp = resp["Progress"]["XP"] # 玩家等级经验值 last_fwin = resp["LastTimeGrantedFirstWin"] # 上次首胜时间 - next_fwin = resp["NextTimeFirstWinAvailable"]# 下次首胜重置 + next_fwin = resp["NextTimeFirstWinAvailable"] # 下次首胜重置 cm = CardMessage() c = Card(color='#fb4b57') c.append( @@ -1559,9 +1544,9 @@ async def get_user_card(msg: Message, *arg): f"玩家 {UserRiotName[msg.author_id]['GameName']}#{UserRiotName[msg.author_id]['TagLine']} 的个人信息")) c.append(Module.Container(Element.Image(src=player_card['data']['wideArt']))) #将图片插入进去 text = f"玩家称号:" + player_title['data']['displayName'] + "\n" - text+= f"玩家等级:{player_level} - 经验值:{player_level_xp}\n" - text+= f"上次首胜:{last_fwin}\n" - text+= f"首胜重置:{next_fwin}" + text += f"玩家等级:{player_level} - 经验值:{player_level_xp}\n" + text += f"上次首胜:{last_fwin}\n" + text += f"首胜重置:{next_fwin}" c.append(Module.Section(Element.Text(text, Types.Text.KMD))) #获取玩家的vp和r点剩余的text @@ -1636,7 +1621,6 @@ async def get_bundle(msg: Message, *arg): await bot.client.send(debug_ch, err_str) - # 设置rate的错误用户 @bot.command(name='ban-r') async def set_rate_err_user(msg: Message, user_id: str): @@ -1649,7 +1633,7 @@ async def set_rate_err_user(msg: Message, user_id: str): elif user_id in SkinRateDict['data']: for skin, info in SkinRateDict['data'][user_id].items(): # 找到这条评论,将其删除 - if not await ShopRate.remove_UserRate(skin,user_id): + if not await ShopRate.remove_UserRate(skin, user_id): await msg.reply(f"Au:{user_id} 删除 {skin} [{info['name']}] 错误") # 删除完该用户的所有评论之后,将其放入err_user @@ -1690,7 +1674,7 @@ async def rate_skin_add(msg: Message, *arg): # 将皮肤list插入到选择列表中,用户使用/rts命令选择 UserRtsDict[msg.author_id] = retlist # 获取选择列表的text - ret = await ShopRate.get_skinlist_rate_text(retlist,msg.author_id) + ret = await ShopRate.get_skinlist_rate_text(retlist, msg.author_id) text = f"```\n{ret['text']}```" cm = CardMessage() @@ -1742,12 +1726,12 @@ async def rate_skin_select(msg: Message, index: str = "err", rating: str = "err" S_skin = UserRtsDict[msg.author_id][_index] skin_uuid = S_skin['skin']['lv_uuid'] comment = " ".join(arg) #用户对此皮肤的评论 - point = _rating # 初始化分数 + point = _rating # 初始化分数 text1 = "" text2 = "" # 先从leancloud获取该皮肤的分数 skin_rate = await ShopRate.query_SkinRate(skin_uuid) - if skin_rate['status']: # 找到了 + if skin_rate['status']: # 找到了 #用户的评分和皮肤平均分差值不能超过32,避免有人乱刷分 if abs(float(_rating) - skin_rate['rating']) <= 32: # 计算分数 @@ -1755,9 +1739,9 @@ async def rate_skin_select(msg: Message, index: str = "err", rating: str = "err" else: # 差值过大,不计入皮肤平均值 point = skin_rate['rating'] text2 += f"由于您的评分和皮肤平均分差值大于32,所以您的评分不会计入皮肤平均分,但您的评论会进行保留\n" - + # 更新数据库中皮肤评分 - await ShopRate.update_SkinRate(skin_uuid,S_skin['skin']['displayName'],point) + await ShopRate.update_SkinRate(skin_uuid, S_skin['skin']['displayName'], point) # 用户之前没有评价过,新建键值 if msg.author_id not in SkinRateDict['data']: SkinRateDict['data'][msg.author_id] = {} @@ -1766,12 +1750,12 @@ async def rate_skin_select(msg: Message, index: str = "err", rating: str = "err" SkinRateDict['data'][msg.author_id][skin_uuid]['name'] = S_skin['skin']['displayName'] SkinRateDict['data'][msg.author_id][skin_uuid]['cmt'] = comment SkinRateDict['data'][msg.author_id][skin_uuid]['pit'] = point - SkinRateDict['data'][msg.author_id][skin_uuid]['time'] = int(time.time()) # 秒级 + SkinRateDict['data'][msg.author_id][skin_uuid]['time'] = int(time.time()) # 秒级 SkinRateDict['data'][msg.author_id][skin_uuid]['msg_id'] = msg.id # 数据库添加该评论 - await ShopRate.update_UserRate(skin_uuid,SkinRateDict['data'][msg.author_id][skin_uuid],msg.author_id) + await ShopRate.update_UserRate(skin_uuid, SkinRateDict['data'][msg.author_id][skin_uuid], msg.author_id) # 更新用户已评价的皮肤 - await ShopRate.update_UserCmt(msg.author_id,skin_uuid) + await ShopRate.update_UserCmt(msg.author_id, skin_uuid) text1 += f"评价成功!{S_skin['skin']['displayName']}" text2 += f"您的评分:{_rating}\n" @@ -1805,7 +1789,7 @@ async def rate_skin_select(msg: Message): if not cmpRet['status']: await msg.reply(f"获取昨日天选之子和丐帮帮主出错!请重试或联系开发者") return - + cm = CardMessage() c = Card(Module.Header(f"来看看昨日天选之子和丐帮帮主吧!"), Module.Divider()) # best @@ -1841,7 +1825,6 @@ async def rate_skin_select(msg: Message): await BaseException_Handler("rts", traceback.format_exc(), msg, bot, None, cm) - # 检查用户是否在错误用户里面 async def check_notify_err_user(msg: Message): """Return(bool): @@ -1881,7 +1864,7 @@ async def add_skin_notify(msg: Message, *arg): if await check_notify_err_user(msg): return # 检查用户的提醒栏位 - vip_status = await vip_ck(msg.author_id) + vip_status = await BotVip.vip_ck(msg.author_id) if msg.author_id in SkinNotifyDict['data'] and not vip_status: if len(SkinNotifyDict['data'][msg.author_id]) > NOTIFY_NUM: cm = await get_card(f"您的皮肤提醒栏位已满", f"想解锁更多栏位,可以来[支持一下](https://afdian.net/a/128ahri?tab=shop)阿狸呢!", @@ -2036,7 +2019,7 @@ async def auto_skin_notify(): SkinRateDict["cmp"]["worse"]["list_shop"] = list() SkinRateDict["cmp"]["worse"]["rating"] = 100 # 更新数据库中的记录,并重置计数器 - await ShopRate.update_ShopCmp(SkinRateDict["kkn"]["best"],SkinRateDict["kkn"]["worse"],'kook',True) + await ShopRate.update_ShopCmp(SkinRateDict["kkn"]["best"], SkinRateDict["kkn"]["worse"], 'kook', True) print(f"[BOT.TASK.NOTIFY] SkinRateDict/UserShopDict clear, sleep(10) [{GetTime()}]") #睡10s再开始遍历(避免时间不准) await asyncio.sleep(10) @@ -2084,10 +2067,10 @@ async def auto_skin_notify(): # 设置用户背景图,如果在则用,否则返回err background_img = ('err' if vip not in VipShopBgDict['bg'] else VipShopBgDict['bg'][vip]["background"][0]) - img_ret = await get_shop_img_169(list_shop, - vp=play_currency['vp'], - rp=play_currency['rp'], - bg_img_src=background_img) + img_ret = await ShopImg.get_shop_img_169(list_shop, + vp=play_currency['vp'], + rp=play_currency['rp'], + bg_img_src=background_img) if img_ret['status']: bg_shop = img_ret['value'] bg_shop.save(img_shop_path, format='PNG') @@ -2166,7 +2149,7 @@ async def auto_skin_notify(): 'entitlements_token': auth.entitlements_token } #vip用户在前面已经获取过商店了 - if await vip_ck(aid): + if await BotVip.vip_ck(aid): list_shop = UserShopDict[aid]["SkinsPanelLayout"]["SingleItemOffers"] else: resp = await fetch_daily_shop(userdict) # 获取每日商店 @@ -2219,6 +2202,7 @@ async def auto_skin_notify(): async def auto_skin_notify_task(): await auto_skin_notify() + # 手动执行notify task @bot.command(name='notify-test') async def auto_skin_notify_cmd(msg: Message, *arg): @@ -2226,15 +2210,16 @@ async def auto_skin_notify_cmd(msg: Message, *arg): if msg.author_id == master_id: await auto_skin_notify() + # 手动更新商店物品和价格 @bot.command(name='update_spb', aliases=['update', 'upd']) async def update_skin_price_bundle(msg: Message): logging(msg) try: if msg.author_id == master_id: - if await update_skins(msg): + if await ValFileUpd.update_skins(msg): await msg.reply(f"成功更新:商店皮肤") - if await update_bundle_url(msg, bot_upimg): + if await ValFileUpd.update_bundle_url(msg, bot_upimg): await msg.reply(f"成功更新:捆绑包") # 获取物品价格需要登录 auth = UserAuthDict[msg.author_id]['auth'] @@ -2243,13 +2228,14 @@ async def update_skin_price_bundle(msg: Message): 'access_token': auth.access_token, 'entitlements_token': auth.entitlements_token } - if await update_price(msg, userdict): + if await ValFileUpd.update_price(msg, userdict): await msg.reply(f"成功更新:物品价格") except Exception as result: err_str = f"ERR! [{GetTime()}] update_spb\n```\n{traceback.format_exc()}\n```" print(err_str) await msg.reply(err_str) + ####################################################################################################### ####################################################################################################### @@ -2284,8 +2270,9 @@ async def bot_log_list(msg: Message, *arg): await msg.reply(f"{err_str}") print(err_str) + @bot.command(name='mem') -async def proc_check(msg:Message,*arg): +async def proc_check(msg: Message, *arg): logging(msg) try: if msg.author_id == master_id: @@ -2296,6 +2283,7 @@ async def proc_check(msg:Message,*arg): await msg.reply(f"{err_str}") print(err_str) + #在阿狸开机的时候自动加载所有保存过的cookie @bot.task.add_date() async def loading_channel_cookie(): @@ -2374,6 +2362,7 @@ async def loading_channel_cookie(): print(log_not_exits) #打印路径不存在的用户 print(f"[BOT.TASK] loading api user cookie finished {GetTime()}") + # 开机 (如果是主文件就开机) if __name__ == '__main__': # 开机的时候打印一次时间,记录开启时间 From d63dffe3b2ee0b72478e6cbb42ea5b3d6e9964d7 Mon Sep 17 00:00:00 2001 From: musnow Date: Tue, 28 Feb 2023 21:30:26 +0800 Subject: [PATCH 16/24] refactor(api): rename def in api.py refactor(EzAuth): add RiotUserToken class, add return type to EzAuth --- code/api.py | 16 +++-- code/utils/valorant/EzAuth.py | 119 +++++++++++++++++----------------- 2 files changed, 70 insertions(+), 65 deletions(-) diff --git a/code/api.py b/code/api.py index d7b0b87..9b2218f 100644 --- a/code/api.py +++ b/code/api.py @@ -10,7 +10,7 @@ # 基础返回 @routes.get('/') -def hello_world(request): # put application's code here +async def hello_world(request): # put application's code here print(f"[{GetTime()}] [request] /") return web.Response(body=json.dumps( { @@ -29,7 +29,7 @@ def hello_world(request): # put application's code here # 提供4个皮肤uuid,返回图片 @routes.get('/shop-draw') -async def get_dailshop_img(request): +async def get_shop_draw(request): print(f"[{GetTime()}] [request] /shop-draw") try: ret = await ApiHandler.img_draw_request(request) @@ -54,7 +54,7 @@ async def get_dailshop_img(request): # 直接跳转图片(浏览器访问,get方法不安全) @routes.get('/shop-img') -async def get_dailshop_img(request): +async def get_shop_img(request): print(f"[{GetTime()}] [request] /shop-img") try: ret = await ApiHandler.login_request(request,"GET") @@ -82,7 +82,7 @@ async def get_dailshop_img(request): # 登录接口 @routes.post('/login') -async def get_dailshop_img(request): +async def post_login(request): print(f"[{GetTime()}] [request] /login") try: ret = await ApiHandler.login_request(request,"POST") @@ -129,20 +129,22 @@ async def post_tfa_code(request): content_type='application/json') @routes.post('/shop') -async def get_dailshop_img(request): +async def post_shop(request): print(f"[{GetTime()}] [request] /shop") try: body = await request.content.read() params = json.loads(body.decode('UTF8')) # 判断必须要的参数是否齐全 - if 'account' not in params or 'token' not in params: + if 'account' not in params or 'token' not in params: # 不全,报错 print(f"ERR! [{GetTime()}] params needed: token/account/passwd") - return { + ret = { 'code': 400, 'message': 'params needed: token/account/passwd', 'info': '缺少参数!示例: /shop-img?token=api凭证&account=Riot账户&passwd=Riot密码&img_src=自定义背景图(可选)', 'docs': 'https://github.com/Aewait/Kook-Valorant-Bot/blob/main/docs/valorant-shop-img-api.md' } + return web.Response(body=json.dumps(ret, indent=2, sort_keys=True, ensure_ascii=False), + content_type='application/json',status=200) # 画图请求,不需要检测token速率 ret = await ApiHandler.shop_get_request(params,params['account']) return web.Response(body=json.dumps(ret, indent=2, sort_keys=True, ensure_ascii=False), diff --git a/code/utils/valorant/EzAuth.py b/code/utils/valorant/EzAuth.py index 5f67f92..2db14c6 100644 --- a/code/utils/valorant/EzAuth.py +++ b/code/utils/valorant/EzAuth.py @@ -9,7 +9,7 @@ from collections import OrderedDict from re import compile -from utils.valorant import EzAuthExp +from . import EzAuthExp # get latest version: https://valorant-api.com/v1/version RiotClient = "RiotClient/63.0.9.4909983.4789131" TFA_TIME_LIMIT = 600 # 600s时间限制 @@ -29,6 +29,7 @@ class URLS: class SSLAdapter(HTTPAdapter): + def init_poolmanager(self, *a: Any, **k: Any) -> None: c = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) c.set_ciphers(':'.join(CIPHERS)) @@ -36,9 +37,19 @@ def init_poolmanager(self, *a: Any, **k: Any) -> None: return super(SSLAdapter, self).init_poolmanager(*a, **k) +# 用于valorant api调用的UserDict +class RiotUserToken: + + def __init__(self, user_id: str, access_token: str, entitlements: str, region: str) -> None: + self.user_id = user_id + self.access_token = access_token + self.entitlements_token = entitlements + self.region = region + + class EzAuth: - def __init__(self): + def __init__(self) -> None: self.session = requests.Session() self.session.headers = OrderedDict({ "User-Agent": f"{RiotClient} %s (Windows;10;;Professional, x64)", @@ -46,10 +57,10 @@ def __init__(self): "Accept": "application/json, text/plain, */*" }) self.session.mount('https://', SSLAdapter()) - self.is2fa = False # 2fa set to false - self.__mfa_start__ = 0 # 2fa start time + self.is2fa = False # 2fa set to false + self.__mfa_start__ = 0 # 2fa start time - def __set_userinfo(self): + def __set_userinfo(self) -> None: """set_user_info to value""" userinfo = self.get_userinfo() self.user_id = userinfo['sub'] @@ -58,24 +69,23 @@ def __set_userinfo(self): self.creationdata = userinfo['create_data'] self.typeban = userinfo['typeban'] - def __set_region(self): - self.Region_headers = {'Content-Type': 'application/json', 'Authorization': f'{self.token_type} {self.access_token}'} + def __set_region(self) -> None: + self.Region_headers = { + 'Content-Type': 'application/json', + 'Authorization': f'{self.token_type} {self.access_token}' + } self.Region = self.get_region(self.Region_headers) - - def __set_access_token(self,data:dict): + + def __set_access_token(self, data: dict) -> dict[str, Any]: """get access_token from response""" pattern = compile( - 'access_token=((?:[a-zA-Z]|\d|\.|-|_)*).*id_token=((?:[a-zA-Z]|\d|\.|-|_)*).*token_type=((?:[a-zA-Z]|\d|)*).*expires_in=(\d*)') + 'access_token=((?:[a-zA-Z]|\d|\.|-|_)*).*id_token=((?:[a-zA-Z]|\d|\.|-|_)*).*token_type=((?:[a-zA-Z]|\d|)*).*expires_in=(\d*)' + ) p_data = pattern.findall(data['response']['parameters']['uri'])[0] - tokens = { - "access_token":p_data[0], - "id_token":p_data[1], - "token_type":p_data[2], - "expires_in":p_data[3] - } + tokens = {"access_token": p_data[0], "id_token": p_data[1], "token_type": p_data[2], "expires_in": p_data[3]} return tokens - - def __set_info(self,tokens:dict): + + def __set_info(self, tokens: dict) -> None: """auth/reauth success, set entitlements_token, userinfo & region\n Args: return value of __set_access_token() """ @@ -93,7 +103,7 @@ def __set_info(self,tokens:dict): self.__set_userinfo() self.__set_region() - async def authorize(self, username, password): + async def authorize(self, username, password) -> dict: """Authenticate using username and password.\n if username & password empty, using cookie reauth\n Return: @@ -102,9 +112,9 @@ async def authorize(self, username, password): if False, using email_verify() to send verify code """ if username and password: - self.session.cookies.clear() # not reauth, clear cookie - - token = {"access_token":"","id_token":"","token_type":"Bearer","expires_in":'0'} + self.session.cookies.clear() # not reauth, clear cookie + + token = {"access_token": "", "id_token": "", "token_type": "Bearer", "expires_in": '0'} body = { "acr_values": "urn:riot:bronze", "claims": "", @@ -117,15 +127,9 @@ async def authorize(self, username, password): r = self.session.post(url=URLS.AUTH_URL, json=body) data = r.json() resp_type = data["type"] - - if resp_type != "response": # not reauth - body = { - "language": "en_US", - "password": password, - "remember": "true", - "type": "auth", - "username": username - } + + if resp_type != "response": # not reauth + body = {"language": "en_US", "password": password, "remember": "true", "type": "auth", "username": username} r = self.session.put(url=URLS.AUTH_URL, json=body) data = r.json() @@ -139,11 +143,11 @@ async def authorize(self, username, password): raise EzAuthExp.RatelimitError("auth_failure, rate_limited") # 2fa auth - elif 'multifactor' in r.text: + elif 'multifactor' in r.text: print(f"[EzAuth] 2fa user") - self.is2fa = True # is 2fa user + self.is2fa = True # is 2fa user self.__mfa_start__ = time.time() - return {"status":False,"auth":self,"2fa_status":self.is2fa} + return {"status": False, "auth": self, "2fa_status": self.is2fa} else: raise EzAuthExp.UnkownError(r.text) @@ -155,15 +159,15 @@ async def authorize(self, username, password): else: raise EzAuthExp.UnkownError(r.text) - return {"status":True,"auth":self,"2fa_status":self.is2fa} + return {"status": True, "auth": self, "2fa_status": self.is2fa} - async def email_verfiy(self,vcode:str): + async def email_verfiy(self, vcode: str) -> dict: """email_verfiy after trying authorize Return {"status":True,"auth":self,"2fa":self.is2fa} """ # no need to 2fa if self.__mfa_start__ == 0: - return {"status":True,"auth":self,"2fa":self.is2fa} + return {"status": True, "auth": self, "2fa": self.is2fa} # check time if (time.time() - self.__mfa_start__) <= TFA_TIME_LIMIT: authdata = { @@ -177,13 +181,13 @@ async def email_verfiy(self,vcode:str): pass elif "auth_failure" in r.text: raise EzAuthExp.MultifactorError("2fa auth_failue") - elif "multifactor_attempt_failed" in r.text: # verify code err + elif "multifactor_attempt_failed" in r.text: # verify code err raise EzAuthExp.MultifactorError("2fa auth_failue, multifactor_attempt_failed") else: raise EzAuthExp.MultifactorError("2fa auth_failue, unkown err") - else: # 2fa wait overtime + else: # 2fa wait overtime raise EzAuthExp.WaitOvertimeError("2fa wait overtime, wait failed") - + # get access_token from response if "access_token" in r.text: token = self.__set_access_token(data) @@ -193,13 +197,13 @@ async def email_verfiy(self,vcode:str): raise EzAuthExp.UnkownError(r.text) self.__mfa_start__ = 0 - return {"status":True,"auth":self,"2fa":self.is2fa} - + return {"status": True, "auth": self, "2fa": self.is2fa} + async def reauthorize(self) -> bool: """reauthorize using cookie """ try: - await self.authorize("","") + await self.authorize("", "") return True except Exception as result: print(f"[EzAuth] reauthoreize err!\n{result}") @@ -247,9 +251,9 @@ def get_userinfo(self): typeban = "PERMANENT_BAN" if data3 == [] or "PBE_LOGIN_TIME_BAN" in data3 or "LEGACY_BAN" in data3: typeban = "None" - return {'sub':Sub, 'name':Name, 'tag':Tag, 'create_data':Createdat, 'typeban':typeban} + return {'sub': Sub, 'name': Name, 'tag': Tag, 'create_data': Createdat, 'typeban': typeban} - def get_region(self,headers): + def get_region(self, headers) -> str: """headers {'Content-Type': 'application/json', 'Authorization': f'{self.token_type} {self.access_token}'} """ json = {"id_token": self.id_token} @@ -259,7 +263,7 @@ def get_region(self,headers): Region = data['affinities']['live'] return Region - def print(self): + def print(self) -> None: print("=" * 50) print(f"Accestoken: {self.access_token}") print("-" * 50) @@ -276,7 +280,7 @@ def print(self): print(f"Bantype: {self.typeban}") print("=" * 50) - def get_userdict(self): + def get_userdict(self) -> RiotUserToken: """Return = { 'auth_user_id': self.user_id, 'access_token': self.access_token, @@ -284,24 +288,23 @@ def get_userdict(self): 'region':self.region } """ - return { - 'auth_user_id': self.user_id, - 'access_token': self.access_token, - 'entitlements_token': self.entitlements_token, - 'region': self.Region - } + ret = RiotUserToken(user_id=self.user_id, + access_token=self.access_token, + entitlements=self.entitlements_token, + region=self.Region) + return ret - def save_cookies(self,path:str): + def save_cookies(self, path: str) -> None: """dump cookies_dict to path (w+) """ cookies = requests.utils.dict_from_cookiejar(self.session.cookies) - with open(path,"w+") as f: + with open(path, "w+") as f: f.write(json.dumps(cookies)) - def load_cookies(self,path:str): + def load_cookies(self, path: str) -> None: """load cookies_dic from path (rb) """ - with open(path,"r") as f: + with open(path, "r") as f: load_cookies = json.loads(f.read()) - + self.session.cookies = requests.utils.cookiejar_from_dict(load_cookies) \ No newline at end of file From 6b53f7c543490f536d435d8a7fe9856c55ab45a1 Mon Sep 17 00:00:00 2001 From: musnow Date: Tue, 28 Feb 2023 22:17:54 +0800 Subject: [PATCH 17/24] refactor(val): add params type, return value refacotor(ValFileUpd): add return value --- code/utils/valorant/EzAuth.py | 7 +- code/utils/valorant/Val.py | 116 +++++++++++++++--------------- code/utils/valorant/ValFileUpd.py | 16 ++--- 3 files changed, 69 insertions(+), 70 deletions(-) diff --git a/code/utils/valorant/EzAuth.py b/code/utils/valorant/EzAuth.py index 2db14c6..8be4f3e 100644 --- a/code/utils/valorant/EzAuth.py +++ b/code/utils/valorant/EzAuth.py @@ -11,7 +11,8 @@ from . import EzAuthExp # get latest version: https://valorant-api.com/v1/version -RiotClient = "RiotClient/63.0.9.4909983.4789131" +X_RIOT_CLIENTVERSION = "RiotClient/63.0.9.4909983.4789131" +X_RIOT_CLIENTVPLATFROM = "ew0KCSJwbGF0Zm9ybVR5cGUiOiAiUEMiLA0KCSJwbGF0Zm9ybU9TIjogIldpbmRvd3MiLA0KCSJwbGF0Zm9ybU9TVmVyc2lvbiI6ICIxMC4wLjE5MDQyLjEuMjU2LjY0Yml0IiwNCgkicGxhdGZvcm1DaGlwc2V0IjogIlVua25vd24iDQp9" TFA_TIME_LIMIT = 600 # 600s时间限制 CIPHERS = [ @@ -52,7 +53,7 @@ class EzAuth: def __init__(self) -> None: self.session = requests.Session() self.session.headers = OrderedDict({ - "User-Agent": f"{RiotClient} %s (Windows;10;;Professional, x64)", + "User-Agent": f"{X_RIOT_CLIENTVERSION} %s (Windows;10;;Professional, x64)", "Accept-Language": "en-US,en;q=0.9", "Accept": "application/json, text/plain, */*" }) @@ -94,7 +95,7 @@ def __set_info(self, tokens: dict) -> None: self.token_type = tokens['token_type'] self.base_headers = { - "User-Agent": f"{RiotClient} %s (Windows;10;;Professional, x64)", + "User-Agent": f"{X_RIOT_CLIENTVERSION} %s (Windows;10;;Professional, x64)", "Authorization": f"{self.token_type} {self.access_token}", } self.session.headers.update(self.base_headers) diff --git a/code/utils/valorant/Val.py b/code/utils/valorant/Val.py index da99a19..9056047 100644 --- a/code/utils/valorant/Val.py +++ b/code/utils/valorant/Val.py @@ -1,18 +1,18 @@ # encoding: utf-8: import json import aiohttp -from khl import Bot, Message -from khl.card import Card, CardMessage, Element, Module, Types +from khl import Message +from khl.card import Card, Element, Module, Types # 预加载文件 -from utils.FileManage import GameIdDict, ValErrDict, ValBundleList, ValItersList, ValPriceList, ValSkinList +from .EzAuth import X_RIOT_CLIENTVERSION,X_RIOT_CLIENTVPLATFROM,RiotUserToken +from ..FileManage import GameIdDict, ValErrDict, ValItersList, ValPriceList, ValSkinList SKIN_ICON_ERR = "https://img.kookapp.cn/assets/2023-02/ekwdy7PiQC0e803m.png" -X_RIOT_CLIENTVERSION = "release-06.01-shipping-8-820493" ####################################保存用户的游戏ID操作####################################### #保存用户id -async def saveid_main(msg: Message, game_id: str): +async def saveid_main(msg: Message, game_id: str) -> None: global GameIdDict flag = 0 # 如果用户id已有,则进行修改 @@ -28,13 +28,13 @@ async def saveid_main(msg: Message, game_id: str): # 显示已有id的个数 -async def saveid_count(msg: Message): +async def saveid_count(msg: Message) -> None: countD = len(GameIdDict) await msg.reply(f"目前狸狸已经记下了`{countD}`个小伙伴的id喽~") # 实现读取用户游戏ID并返回 -async def myid_main(msg: Message): +async def myid_main(msg: Message) -> None: if msg.author_id in GameIdDict.keys(): flag = 1 #找到了对应用户的id await msg.reply(f'游戏id: ' + GameIdDict[msg.author_id]) @@ -47,7 +47,7 @@ async def myid_main(msg: Message): # 查询游戏错误码 -async def val_errcode(msg: Message, num: str = "-1"): +async def val_errcode(msg: Message, num: str = "-1") -> None: if num == "-1": await msg.reply( '目前支持查询的错误信息有:\n```\n0-1,4-5,7-21,29,31,33,38,43-46,49-70,81,84,128,152,1067,9001,9002,9003\n```\n注:van和val错误码都可用本命令查询' @@ -59,7 +59,7 @@ async def val_errcode(msg: Message, num: str = "-1"): #关于dx报错的解决方法 -async def dx123(msg: Message): +async def dx123(msg: Message) -> None: await msg.reply( '报错弹窗内容为`The following component(s) are required to run this program:DirectX Runtime`\n需要下载微软官方驱动安装,官网搜索[DirectX End-User Runtime Web Installer]\n你还可以下载本狸亲测可用的DX驱动 [链接](https://pan.baidu.com/s/1145Ll8vGtByMW6OKk6Zi2Q),暗号是1067哦!\n狸狸记得之前玩其他游戏的时候,也有遇到过这个问题呢~' ) @@ -69,14 +69,14 @@ async def dx123(msg: Message): #从list中获取价格 -def fetch_item_price_bylist(item_id): +def fetch_item_price_bylist(item_id) -> dict | None: for item in ValPriceList['Offers']: #遍历查找指定uuid if item_id == item['OfferID']: return item #从list中获取等级(这个需要手动更新) -def fetch_item_iters_bylist(iter_id): +def fetch_item_iters_bylist(iter_id) -> dict | None: for iter in ValItersList['data']: #遍历查找指定uuid if iter_id == iter['uuid']: res = {'data': iter} #所以要手动创建一个带data的dict作为返回值 @@ -84,7 +84,7 @@ def fetch_item_iters_bylist(iter_id): #从list中获取皮肤 -def fetch_skin_bylist(item_id): +def fetch_skin_bylist(item_id) -> dict | None: res = {} #下面我们要操作的是获取通行证的皮肤,但是因为遍历的时候已经跳过data了,返回的时候就不好返回 for item in ValSkinList['data']: #遍历查找指定uuid if item_id == item['levels'][0]['uuid']: @@ -102,7 +102,7 @@ def fetch_skin_bylist(item_id): #从list中,通过皮肤名字获取皮肤列表 -def fetch_skin_list_byname(name): +def fetch_skin_list_byname(name) ->list[dict]: wplist = list() #包含该名字的皮肤list for skin in ValSkinList['data']: if name in skin['displayName']: @@ -112,7 +112,7 @@ def fetch_skin_list_byname(name): #从list中通过皮肤lv0uuid获取皮肤等级 -def fetch_skin_iters_bylist(item_id): +def fetch_skin_iters_bylist(item_id) -> dict | None: for it in ValSkinList['data']: if it['levels'][0]['uuid'] == item_id: res_iters = fetch_item_iters_bylist(it['contentTierUuid']) @@ -120,7 +120,7 @@ def fetch_skin_iters_bylist(item_id): # 用名字查询捆绑包包含什么枪 -async def fetch_bundle_weapen_byname(name): +async def fetch_bundle_weapen_byname(name)->list[dict]: # 捆绑包的所有皮肤 WeapenList = list() for skin in ValSkinList['data']: @@ -138,13 +138,13 @@ async def fetch_bundle_weapen_byname(name): #获取用户游戏id(从使用对象修改成使用文件中的内容) -async def fetch_user_gameID(auth): +async def fetch_user_gameID(ru:RiotUserToken) -> dict: url = "https://pd.ap.a.pvp.net/name-service/v2/players" - payload = json.dumps([auth['auth_user_id']]) + payload = json.dumps([ru.user_id]) headers = { "Content-Type": "application/json", - "X-Riot-Entitlements-JWT": auth['entitlements_token'], - "Authorization": "Bearer " + auth['access_token'] + "X-Riot-Entitlements-JWT": ru.entitlements_token, + "Authorization": "Bearer " + ru.access_token } async with aiohttp.ClientSession() as session: async with session.put(url, headers=headers, data=payload) as response: @@ -153,12 +153,12 @@ async def fetch_user_gameID(auth): # 获取每日商店 -async def fetch_daily_shop(u): - url = "https://pd.ap.a.pvp.net/store/v2/storefront/" + u['auth_user_id'] +async def fetch_daily_shop(ru:RiotUserToken)-> dict: + url = "https://pd.ap.a.pvp.net/store/v2/storefront/" + ru.user_id headers = { "Content-Type": "application/json", - "X-Riot-Entitlements-JWT": u['entitlements_token'], - "Authorization": "Bearer " + u['access_token'] + "X-Riot-Entitlements-JWT": ru.entitlements_token, + "Authorization": "Bearer " + ru.access_token } async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers) as response: @@ -167,12 +167,12 @@ async def fetch_daily_shop(u): # Api获取玩家的vp和r点 -async def fetch_valorant_point(u): - url = "https://pd.ap.a.pvp.net/store/v1/wallet/" + u['auth_user_id'] +async def fetch_valorant_point(ru:RiotUserToken)-> dict: + url = "https://pd.ap.a.pvp.net/store/v1/wallet/" + ru.user_id headers = { "Content-Type": "application/json", - "X-Riot-Entitlements-JWT": u['entitlements_token'], - "Authorization": "Bearer " + u['access_token'] + "X-Riot-Entitlements-JWT": ru.entitlements_token, + "Authorization": "Bearer " + ru.access_token } async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers) as response: @@ -181,20 +181,20 @@ async def fetch_valorant_point(u): # 获取vp和r点的dict -async def fetch_vp_rp_dict(u): - resp = await fetch_valorant_point(u) +async def fetch_vp_rp_dict(ru:RiotUserToken)-> dict[str,int]: + resp = await fetch_valorant_point(ru) vp = resp["Balances"]["85ad13f7-3d1b-5128-9eb2-7cd8ee0b5741"] #vp rp = resp["Balances"]["e59aa87c-4cbf-517a-5983-6e81511be9b7"] #R点 return {'vp': vp, 'rp': rp} # 获取商品价格(所有) -async def fetch_item_price_all(u): +async def fetch_item_price_all(ru:RiotUserToken)-> dict: url = "https://pd.ap.a.pvp.net/store/v1/offers/" headers = { "Content-Type": "application/json", - "X-Riot-Entitlements-JWT": u['entitlements_token'], - "Authorization": "Bearer " + u['access_token'] + "X-Riot-Entitlements-JWT": ru.entitlements_token, + "Authorization": "Bearer " + ru.access_token } async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers) as response: @@ -204,8 +204,8 @@ async def fetch_item_price_all(u): # 获取商品价格(用uuid获取单个价格) -async def fetch_item_price_uuid(u, item_id: str): - res = await fetch_item_price_all(u) #获取所有价格 +async def fetch_item_price_uuid(ru:RiotUserToken, item_id: str)-> str: + res = await fetch_item_price_all(ru) #获取所有价格 for item in res['Offers']: #遍历查找指定uuid if item_id == item['OfferID']: @@ -215,7 +215,7 @@ async def fetch_item_price_uuid(u, item_id: str): # 获取皮肤等级(史诗/传说) -async def fetch_item_iters(iters_id: str): +async def fetch_item_iters(iters_id: str)-> dict: url = "https://valorant-api.com/v1/contenttiers/" + iters_id headers = {'Connection': 'close'} params = {"language": "zh-TW"} @@ -227,7 +227,7 @@ async def fetch_item_iters(iters_id: str): # 获取所有皮肤 -async def fetch_skins_all(): +async def fetch_skins_all()->dict: url = "https://valorant-api.com/v1/weapons/skins" headers = {'Connection': 'close'} params = {"language": "zh-TW"} @@ -239,7 +239,7 @@ async def fetch_skins_all(): # 获取所有皮肤捆绑包 -async def fetch_bundles_all(): +async def fetch_bundles_all()->dict: url = "https://valorant-api.com/v1/bundles" headers = {'Connection': 'close'} params = {"language": "zh-TW"} @@ -251,12 +251,12 @@ async def fetch_bundles_all(): # 获取获取玩家当前装备的卡面和称号 -async def fetch_player_loadout(u): - url = f"https://pd.ap.a.pvp.net/personalization/v2/players/{u['auth_user_id']}/playerloadout" +async def fetch_player_loadout(ru:RiotUserToken)->dict: + url = f"https://pd.ap.a.pvp.net/personalization/v2/players/{ru.user_id}/playerloadout" headers = { "Content-Type": "application/json", - "X-Riot-Entitlements-JWT": u['entitlements_token'], - "Authorization": "Bearer " + u['access_token'], + "X-Riot-Entitlements-JWT": ru.entitlements_token, + "Authorization": "Bearer " + ru.access_token, 'Connection': 'close' } async with aiohttp.ClientSession() as session: @@ -267,16 +267,14 @@ async def fetch_player_loadout(u): # 获取合约(任务)进度 -# client version from https://valorant-api.com/v1/version -async def fetch_player_contract(u): +async def fetch_player_contract(ru:RiotUserToken)->dict: #url="https://pd.ap.a.pvp.net/contract-definitions/v2/definitions/story" - url = f"https://pd.ap.a.pvp.net/contracts/v1/contracts/" + u['auth_user_id'] + url = f"https://pd.ap.a.pvp.net/contracts/v1/contracts/" + ru.user_id headers = { "Content-Type": "application/json", - "X-Riot-Entitlements-JWT": u['entitlements_token'], - "Authorization": "Bearer " + u['access_token'], - "X-Riot-ClientPlatform": - "ew0KCSJwbGF0Zm9ybVR5cGUiOiAiUEMiLA0KCSJwbGF0Zm9ybU9TIjogIldpbmRvd3MiLA0KCSJwbGF0Zm9ybU9TVmVyc2lvbiI6ICIxMC4wLjE5MDQyLjEuMjU2LjY0Yml0IiwNCgkicGxhdGZvcm1DaGlwc2V0IjogIlVua25vd24iDQp9", + "X-Riot-Entitlements-JWT": ru.entitlements_token, + "Authorization": "Bearer " + ru.access_token, + "X-Riot-ClientPlatform": X_RIOT_CLIENTVPLATFROM, "X-Riot-ClientVersion": X_RIOT_CLIENTVERSION } async with aiohttp.ClientSession() as session: @@ -286,12 +284,12 @@ async def fetch_player_contract(u): return res # 获取玩家的等级信息 -async def fetch_player_level(u): - url = "https://pd.ap.a.pvp.net/account-xp/v1/players/"+ u['auth_user_id'] +async def fetch_player_level(ru:RiotUserToken) -> dict: + url = "https://pd.ap.a.pvp.net/account-xp/v1/players/"+ ru.user_id headers = { "Content-Type": "application/json", - "X-Riot-Entitlements-JWT": u['entitlements_token'], - "Authorization": "Bearer " + u['access_token'], + "X-Riot-Entitlements-JWT": ru.entitlements_token, + "Authorization": "Bearer " + ru.access_token, } async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers) as response: @@ -300,7 +298,7 @@ async def fetch_player_level(u): return res # 获取玩家当前通行证情况,uuid -async def fetch_contract_uuid(id): +async def fetch_contract_uuid(id:str) -> dict: url = "https://valorant-api.com/v1/contracts/" + id headers = {'Connection': 'close'} params = {"language": "zh-TW"} @@ -312,7 +310,7 @@ async def fetch_contract_uuid(id): # 获取玩家卡面,uuid -async def fetch_playercard_uuid(id): +async def fetch_playercard_uuid(id:str)-> dict: url = "https://valorant-api.com/v1/playercards/" + id headers = {'Connection': 'close'} params = {"language": "zh-TW"} @@ -324,7 +322,7 @@ async def fetch_playercard_uuid(id): # 获取玩家称号,uuid -async def fetch_title_uuid(id): +async def fetch_title_uuid(id:str)-> dict: url = "https://valorant-api.com/v1/playertitles/" + id headers = {'Connection': 'close'} params = {"language": "zh-TW"} @@ -336,7 +334,7 @@ async def fetch_title_uuid(id): # 获取喷漆,uuid -async def fetch_spary_uuid(id): +async def fetch_spary_uuid(id:str)-> dict: url = "https://valorant-api.com/v1/sprays/" + id headers = {'Connection': 'close'} params = {"language": "zh-TW"} @@ -348,7 +346,7 @@ async def fetch_spary_uuid(id): # 获取吊坠,uuid -async def fetch_buddies_uuid(id): +async def fetch_buddies_uuid(id:str)->dict: url = "https://valorant-api.com/v1/buddies/levels/" + id headers = {'Connection': 'close'} params = {"language": "zh-TW"} @@ -360,7 +358,7 @@ async def fetch_buddies_uuid(id): # 获取皮肤,通过lv0的uuid -async def fetch_skinlevel_uuid(id): +async def fetch_skinlevel_uuid(id:str)->dict: url = f"https://valorant-api.com/v1/weapons/skinlevels/" + id headers = {'Connection': 'close'} params = {"language": "zh-TW"} @@ -406,7 +404,7 @@ async def get_reward(reward): # 创建一个玩家任务和通信证的卡片消息 -async def create_cm_contract(msg: Message): +async def create_cm_contract(msg: Message) -> Card: # 预加载用户token(其实已经没用了) with open("./log/UserAuthID.json", 'r', encoding='utf-8') as frau: UserTokenDict = json.load(frau) diff --git a/code/utils/valorant/ValFileUpd.py b/code/utils/valorant/ValFileUpd.py index c208401..f23523d 100644 --- a/code/utils/valorant/ValFileUpd.py +++ b/code/utils/valorant/ValFileUpd.py @@ -1,15 +1,15 @@ import traceback -import json import io from khl import Message, Bot from PIL import Image -from utils.Gtime import GetTime -from utils.ShopImg import img_requestor -from utils.valorant.Val import fetch_skins_all, fetch_item_price_all, fetch_bundles_all, ValBundleList, ValSkinList, ValPriceList +from ..Gtime import GetTime +from ..ShopImg import img_requestor +from ..FileManage import ValBundleList +from .Val import fetch_skins_all, fetch_item_price_all, fetch_bundles_all, ValSkinList, ValPriceList # 更新本地保存的皮肤 -async def update_skins(msg: Message): +async def update_skins(msg: Message) -> bool: try: global ValSkinList skins = await fetch_skins_all() @@ -26,14 +26,14 @@ async def update_skins(msg: Message): # 更新捆绑包 -async def update_bundle_url(msg: Message, bot_upimg: Bot): +async def update_bundle_url(msg: Message, bot_upimg: Bot) -> bool: try: global ValBundleList resp = await fetch_bundles_all() #从官方获取最新list if len(resp['data']) == len(ValBundleList): #长度相同代表没有更新 print(f"[{GetTime()}] len is the same, doesn't need update!") await msg.reply("BundleList_len相同,无需更新") - return + return True for b in resp['data']: flag = 0 @@ -64,7 +64,7 @@ async def update_bundle_url(msg: Message, bot_upimg: Bot): # 因为下方获取物品价格的操作需要authtoken,自动更新容易遇到token失效的情况 -async def update_price(msg: Message, userdict): +async def update_price(msg: Message, userdict) -> bool: try: global ValPriceList # 调用api获取价格列表 From 241245914a7a25d318820cc9186ca5e7f2b2f772 Mon Sep 17 00:00:00 2001 From: musnow Date: Wed, 1 Mar 2023 10:26:03 +0800 Subject: [PATCH 18/24] refactor(main): using RiotUserToken in main & apihandler --- code/main.py | 79 ++++++++++++++--------------------- code/utils/api/ApiHandler.py | 6 +-- code/utils/valorant/EzAuth.py | 12 +++--- 3 files changed, 40 insertions(+), 57 deletions(-) diff --git a/code/main.py b/code/main.py index 740f7ad..23685e8 100644 --- a/code/main.py +++ b/code/main.py @@ -20,7 +20,7 @@ from utils.KookApi import (icon_cm, status_active_game, status_active_music, status_delete, bot_offline, upd_card, get_card) from utils.valorant.Val import * -from utils.valorant.EzAuth import EzAuth, EzAuthExp +from utils.valorant.EzAuth import EzAuth, EzAuthExp,RiotUserToken from utils.Gtime import GetTime, GetTimeStampOf8AM # bot的token文件 @@ -121,7 +121,8 @@ async def Vhelp(msg: Message, *arg): @bot.on_message() async def atAhri(msg: Message): try: - if f"(met){bot.me.id}(met)" in msg.content: + me = await bot.client.fetch_me() + if f"(met){me.id}(met)" in msg.content: logging(msg) if msg.author_id == master_id: text = Help.help_develop() @@ -1152,9 +1153,9 @@ async def check_reauth(def_name: str = "", msg: Union[Message, str] = ''): user_id = msg if isinstance(msg, str) else msg.author_id #如果是str就直接用 auth = UserAuthDict[user_id]['auth'] assert isinstance(auth, EzAuth) - # 直接从对象中获取userdict - userdict = auth.get_userdict() - resp = await fetch_valorant_point(userdict) + # 直接从对象中获取user的Token + riotUser = auth.get_riotuser_token() + resp = await fetch_valorant_point(riotUser) # resp={'httpStatus': 400, 'errorCode': 'BAD_CLAIMS', 'message': 'Failure validating/decoding RSO Access Token'} # 如果没有这个键,会直接报错进except; 如果有这个键,就可以继续执行下面的内容 test = resp['httpStatus'] @@ -1251,15 +1252,13 @@ async def get_daily_shop(msg: Message, *arg): else: send_msg = await msg.reply(cm) #记录消息id用于后续更新 - #计算获取每日商店要多久 + # 计算获取每日商店要多久 start = time.perf_counter() #开始计时 - #从auth的dict中获取对象 + # 从auth的dict中获取对象 auth = UserAuthDict[msg.author_id]['auth'] - userdict = { - 'auth_user_id': auth.user_id, - 'access_token': auth.access_token, - 'entitlements_token': auth.entitlements_token - } + assert isinstance(auth, EzAuth) + riotUser = auth.get_riotuser_token() + # 开始判断是否需要获取商店 log_time = "" a_time = time.time() global UserShopDict, VipShopBgDict @@ -1269,7 +1268,7 @@ async def get_daily_shop(msg: Message, *arg): timeout = shop_time_remain() # 通过当前时间计算商店剩余时间 log_time += f"[Dict_shop] {format(time.time()-a_time,'.4f')} " else: - resp = await fetch_daily_shop(userdict) #本地没有,api获取每日商店 + resp = await fetch_daily_shop(riotUser) #本地没有,api获取每日商店 list_shop = resp["SkinsPanelLayout"]["SingleItemOffers"] # 商店刷出来的4把枪 timeout = resp["SkinsPanelLayout"]["SingleItemOffersRemainingDurationInSeconds"] # 剩余时间 timeout = time.strftime("%H:%M:%S", time.gmtime(timeout)) # 将秒数转为标准时间 @@ -1291,7 +1290,7 @@ async def get_daily_shop(msg: Message, *arg): upload_flag = False #有缓存图,直接使用本地已有链接 dailyshop_img_src = VipShopBgDict['cache'][msg.author_id]['cache_img'] elif is_vip: # 本地缓存路径不存在,或者缓存过期 - play_currency = await fetch_vp_rp_dict(userdict) #获取用户的vp和rp + play_currency = await fetch_vp_rp_dict(riotUser) #获取用户的vp和rp # 如果没有设置背景图,那就设置为err background_img = ('err' if msg.author_id not in VipShopBgDict['bg'] else VipShopBgDict['bg'][msg.author_id]["background"][0]) @@ -1404,12 +1403,10 @@ async def get_night_market(msg: Message, *arg): #计算获取时间 start = time.perf_counter() #开始计时 auth = UserAuthDict[msg.author_id]['auth'] - userdict = { - 'auth_user_id': auth.user_id, - 'access_token': auth.access_token, - 'entitlements_token': auth.entitlements_token - } - resp = await fetch_daily_shop(userdict) #获取商店(夜市是相同接口) + assert isinstance(auth, EzAuth) + riotUser = auth.get_riotuser_token() + # 获取商店(夜市是相同接口) + resp = await fetch_daily_shop(riotUser) if "BonusStore" not in resp: # 如果没有这个字段,说明夜市取消了 NightMarketOff = False cm1 = await get_card("嗷~ 夜市已关闭 或 Api没能正确返回结果", "night_market closed! 'BonusStore' not in resp", @@ -1506,12 +1503,9 @@ async def get_user_card(msg: Message, *arg): send_msg = await msg.reply(cm) #记录消息id用于后续更新 auth = UserAuthDict[msg.author_id]['auth'] - userdict = { - 'auth_user_id': auth.user_id, - 'access_token': auth.access_token, - 'entitlements_token': auth.entitlements_token - } - resp = await fetch_player_loadout(userdict) #获取玩家装备栏 + assert isinstance(auth, EzAuth) + riotUser = auth.get_riotuser_token() + resp = await fetch_player_loadout(riotUser) #获取玩家装备栏 player_card = await fetch_playercard_uuid(resp['Identity']['PlayerCardID']) #玩家卡面id player_title = await fetch_title_uuid(resp['Identity']['PlayerTitleID']) #玩家称号id if 'data' not in player_card or player_card['status'] != 200: @@ -1532,7 +1526,7 @@ async def get_user_card(msg: Message, *arg): return # 获取玩家等级 - resp = await fetch_player_level(userdict) + resp = await fetch_player_level(riotUser) player_level = resp["Progress"]["Level"] # 玩家等级 player_level_xp = resp["Progress"]["XP"] # 玩家等级经验值 last_fwin = resp["LastTimeGrantedFirstWin"] # 上次首胜时间 @@ -1550,7 +1544,7 @@ async def get_user_card(msg: Message, *arg): c.append(Module.Section(Element.Text(text, Types.Text.KMD))) #获取玩家的vp和r点剩余的text - resp = await fetch_vp_rp_dict(userdict) + resp = await fetch_vp_rp_dict(riotUser) text = f"(emj)r点(emj)[3986996654014459/X3cT7QzNsu03k03k] RP {resp['rp']} " text += f"(emj)vp(emj)[3986996654014459/qGVLdavCfo03k03k] VP {resp['vp']}\n" c.append(Module.Section(Element.Text(text, Types.Text.KMD))) @@ -2038,13 +2032,10 @@ async def auto_skin_notify(): shop_text = "err" start = time.perf_counter() #开始计时 auth = UserAuthDict[vip]['auth'] - userdict = { - 'auth_user_id': auth.user_id, - 'access_token': auth.access_token, - 'entitlements_token': auth.entitlements_token - } + assert isinstance(auth, EzAuth) + riotUser = auth.get_riotuser_token() a_time = time.time() # 获取token的时间 - resp = await fetch_daily_shop(userdict) # 获取每日商店 + resp = await fetch_daily_shop(riotUser) # 获取每日商店 # 判断夜市有没有开,只会判断一次 global NightMarketOff #true代表夜市没有开启 @@ -2063,7 +2054,7 @@ async def auto_skin_notify(): #直接获取商店图片 draw_time = time.time() #开始计算画图需要的时间 img_shop_path = f"./log/img_temp_vip/shop/{vip}.png" - play_currency = await fetch_vp_rp_dict(userdict) #获取用户的vp和rp + play_currency = await fetch_vp_rp_dict(riotUser) #获取用户的vp和rp # 设置用户背景图,如果在则用,否则返回err background_img = ('err' if vip not in VipShopBgDict['bg'] else VipShopBgDict['bg'][vip]["background"][0]) @@ -2143,16 +2134,13 @@ async def auto_skin_notify(): if aid in UserAuthDict: if await check_reauth("定时获取玩家商店", aid) == True: # 重新登录,如果为假说明重新登录失败 auth = UserAuthDict[aid]['auth'] - userdict = { - 'auth_user_id': auth.user_id, - 'access_token': auth.access_token, - 'entitlements_token': auth.entitlements_token - } + assert isinstance(auth, EzAuth) + riotUser = auth.get_riotuser_token() #vip用户在前面已经获取过商店了 if await BotVip.vip_ck(aid): list_shop = UserShopDict[aid]["SkinsPanelLayout"]["SingleItemOffers"] else: - resp = await fetch_daily_shop(userdict) # 获取每日商店 + resp = await fetch_daily_shop(riotUser) # 获取每日商店 list_shop = resp["SkinsPanelLayout"]["SingleItemOffers"] # 商店刷出来的4把枪 await ShopRate.check_shop_rate(vip, list_shop) #计算非vip用户商店得分 @@ -2223,12 +2211,9 @@ async def update_skin_price_bundle(msg: Message): await msg.reply(f"成功更新:捆绑包") # 获取物品价格需要登录 auth = UserAuthDict[msg.author_id]['auth'] - userdict = { - 'auth_user_id': auth.user_id, - 'access_token': auth.access_token, - 'entitlements_token': auth.entitlements_token - } - if await ValFileUpd.update_price(msg, userdict): + assert isinstance(auth, EzAuth) + riotUser = auth.get_riotuser_token() + if await ValFileUpd.update_price(msg, riotUser): await msg.reply(f"成功更新:物品价格") except Exception as result: err_str = f"ERR! [{GetTime()}] update_spb\n```\n{traceback.format_exc()}\n```" diff --git a/code/utils/api/ApiHandler.py b/code/utils/api/ApiHandler.py index 94e9a89..d731731 100644 --- a/code/utils/api/ApiHandler.py +++ b/code/utils/api/ApiHandler.py @@ -150,13 +150,13 @@ async def shop_get_request(params,account:str): return { "code":200,"message":"缓存信息失效,需要重新登录", "info":"cache reauthorize failed,please /login" } # 3 获取每日商店 - userdict = auth.get_userdict() - resp = await fetch_daily_shop(userdict) + riotUser = auth.get_riotuser_token() + resp = await fetch_daily_shop(riotUser) print(f'[{GetTime()}] [Api] fetch_daily_shop success') list_shop = resp["SkinsPanelLayout"]["SingleItemOffers"] # 商店刷出来的4把枪 res_vprp = {'vp': 0, 'rp': 0} # 先初始化为0 if isimgRatio or isRaw: - res_vprp = await fetch_vp_rp_dict(userdict) # 只有16-9的图片需获取vp和r点 + res_vprp = await fetch_vp_rp_dict(riotUser) # 只有16-9的图片需获取vp和r点 # 如果用户需要raw,则返回皮肤uuid和vp rp的dict if isRaw: return { "code":0,"message":"获取原始接口返回值成功","info":"get raw response success","storefront":resp,"wallet":res_vprp} diff --git a/code/utils/valorant/EzAuth.py b/code/utils/valorant/EzAuth.py index 8be4f3e..f1373bf 100644 --- a/code/utils/valorant/EzAuth.py +++ b/code/utils/valorant/EzAuth.py @@ -281,13 +281,11 @@ def print(self) -> None: print(f"Bantype: {self.typeban}") print("=" * 50) - def get_userdict(self) -> RiotUserToken: - """Return = { - 'auth_user_id': self.user_id, - 'access_token': self.access_token, - 'entitlements_token': self.entitlements_token, - 'region':self.region - } + def get_riotuser_token(self) -> RiotUserToken: + """RiotUserToken(user_id=self.user_id, + access_token=self.access_token, + entitlements=self.entitlements_token, + region=self.Region) """ ret = RiotUserToken(user_id=self.user_id, access_token=self.access_token, From e658528b67d8b2a0016aa22ec33f57073c82d062 Mon Sep 17 00:00:00 2001 From: musnow Date: Wed, 1 Mar 2023 21:37:42 +0800 Subject: [PATCH 19/24] fix(main): add del auth in start up task, using on_startup to replace add_date --- code/main.py | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/code/main.py b/code/main.py index 23685e8..1808b21 100644 --- a/code/main.py +++ b/code/main.py @@ -2270,8 +2270,8 @@ async def proc_check(msg: Message, *arg): #在阿狸开机的时候自动加载所有保存过的cookie -@bot.task.add_date() -async def loading_channel_cookie(): +@bot.on_startup +async def loading_cache(bot:Bot): try: global debug_ch, cm_send_test cm_send_test = await bot_upimg.client.fetch_public_channel(config['channel']["img_upload_ch"]) @@ -2302,21 +2302,15 @@ async def loading_channel_cookie(): if ret_bool: # True登陆成功 UserAuthDict[user] = {"auth": auth, "2fa": False} #将对象插入 log_str_success += f"({user})" - #print(f"[BOT.TASK] Au:{user} - load cookie success!") - #不用重新修改UserRiotName里面的游戏名和uuid - #因为UserRiotName是在login的时候保存的,只要用户没有切换账户 - #那么玩家id和uuid都是不会变化的,也没必要重新加载 else: + del auth # 删除对象 log_str_failed += f"({user}) " - #print(f"[BOT.TASK] Au:{user} - load cookie failed!") continue else: log_not_exits += f"({user}) " continue # 结束任务 - print(log_str_success) #打印正常的用户 - print(log_str_failed) #打印失败的用户 - print(log_not_exits) #打印路径不存在的用户 + print(log_str_success + "\n" + log_str_failed + "\n" + log_not_exits) print(f"[BOT.TASK] loading user cookie finished {GetTime()}") # api缓存的用户列表 @@ -2335,16 +2329,14 @@ async def loading_channel_cookie(): UserAuthDict[user] = {"auth": auth, "2fa": False} #将对象插入 log_str_success += f"({user})" else: + del auth # 删除对象 log_str_failed += f"({user}) " - #print(f"[BOT.TASK] Au:{user} - load cookie failed!") continue else: log_not_exits += f"({user}) " continue # 结束任务 - print(log_str_success) #打印正常的用户 - print(log_str_failed) #打印失败的用户 - print(log_not_exits) #打印路径不存在的用户 + print(log_str_success + "\n" + log_str_failed + "\n" + log_not_exits) print(f"[BOT.TASK] loading api user cookie finished {GetTime()}") From 49efe0f5b2444d339147dca56303d186a1ea3521 Mon Sep 17 00:00:00 2001 From: musnow Date: Fri, 3 Mar 2023 21:02:15 +0800 Subject: [PATCH 20/24] refactor(main): using BotLog to replace from BotLog import def --- code/main.py | 197 +++++++++++++++++++++++++-------------------------- 1 file changed, 98 insertions(+), 99 deletions(-) diff --git a/code/main.py b/code/main.py index 1808b21..d9fe6a9 100644 --- a/code/main.py +++ b/code/main.py @@ -14,17 +14,16 @@ from aiohttp import client_exceptions from PIL import Image, UnidentifiedImageError # 用于合成图片 -from utils import ShopRate, ShopImg, Help, GrantRoles, Translate, BotVip, Other +from utils import ShopRate, ShopImg, Help, GrantRoles, Translate, BotVip, BotLog, Other from utils.valorant import ValFileUpd -from utils.BotLog import logging, log_bot_list, log_bot_user, log_bot_list_text, APIRequestFailed_Handler, BaseException_Handler, get_proc_info from utils.KookApi import (icon_cm, status_active_game, status_active_music, status_delete, bot_offline, upd_card, get_card) from utils.valorant.Val import * -from utils.valorant.EzAuth import EzAuth, EzAuthExp,RiotUserToken +from utils.valorant.EzAuth import EzAuth, EzAuthExp from utils.Gtime import GetTime, GetTimeStampOf8AM # bot的token文件 -from utils.FileManage import config, Save_All_File, ApiAuthLog, VipUserDict +from utils.FileManage import config, ApiAuthLog, Save_All_File # 用读取来的 config 初始化 bot,字段对应即可 bot = Bot(token=config['token']['bot']) # 只用来上传图片的bot @@ -66,7 +65,7 @@ async def Save_File_Task(): @bot.command(name='kill') async def KillBot(msg: Message, num: str = '124124', *arg): - logging(msg) + BotLog.logging(msg) if msg.author_id == master_id and int(num) == config['no']: # 保存所有文件 await Save_All_File(False) @@ -85,19 +84,19 @@ async def KillBot(msg: Message, num: str = '124124', *arg): # hello命令,一般用于测试阿狸在不在线 @bot.command(name='hello', aliases=['HELLO']) async def world(msg: Message): - logging(msg) + BotLog.logging(msg) await msg.reply('你好呀~') # help命令,触发指令为 `/Ahri`,因为help指令和其他机器人冲突 @bot.command(name='Ahri', aliases=['ahri', '阿狸']) async def Ahri(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) try: cm = Help.help_main(start_time) await msg.reply(cm) except Exception as result: - await BaseException_Handler("ahri", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") + await BotLog.BaseException_Handler("ahri", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") err_str = f"ERR! [{GetTime()}] ahri\n```\n{traceback.format_exc()}\n```" #发送错误信息到指定频道 await bot.client.send(debug_ch, err_str) @@ -106,12 +105,12 @@ async def Ahri(msg: Message, *arg): # help命令(瓦洛兰特相关) @bot.command(name='Vhelp', aliases=['vhelp']) async def Vhelp(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) try: cm = Help.help_val() await msg.reply(cm) except Exception as result: - await BaseException_Handler("vhelp", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") + await BotLog.BaseException_Handler("vhelp", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") err_str = f"ERR! [{GetTime()}] vhelp\n```\n{traceback.format_exc()}\n```" #发送错误信息到指定频道 await bot.client.send(debug_ch, err_str) @@ -123,7 +122,7 @@ async def atAhri(msg: Message): try: me = await bot.client.fetch_me() if f"(met){me.id}(met)" in msg.content: - logging(msg) + BotLog.logging(msg) if msg.author_id == master_id: text = Help.help_develop() await msg.reply(text) @@ -143,7 +142,7 @@ async def atAhri(msg: Message): # 倒计时函数,单位为秒,默认60秒 @bot.command() async def countdown(msg: Message, time: int = 60, *args): - logging(msg) + BotLog.logging(msg) if args != (): await msg.reply(f"参数错误,countdown命令只支持1个参数\n正确用法: `/countdown 120` 生成一个120s的倒计时") return @@ -158,7 +157,7 @@ async def countdown(msg: Message, time: int = 60, *args): cm.append(c1) await msg.reply(cm) except Exception as result: - await BaseException_Handler("countdown", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") + await BotLog.BaseException_Handler("countdown", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") err_str = f"ERR! [{GetTime()}] countdown\n```\n{traceback.format_exc()}\n```" #发送错误信息到指定频道 await bot.client.send(debug_ch, err_str) @@ -167,7 +166,7 @@ async def countdown(msg: Message, time: int = 60, *args): # 掷骰子 saying `!roll 1 100` in channel,or `/roll 1 100 5` to dice 5 times once @bot.command() async def roll(msg: Message, t_min: int = 1, t_max: int = 100, n: int = 1, *args): - logging(msg) + BotLog.logging(msg) if args != (): await msg.reply( f"参数错误,roll命令只支持3个参数\n正确用法:\n```\n/roll 1 100 生成一个1到100之间的随机数\n/roll 1 100 3 生成三个1到100之间的随机数\n```") @@ -182,7 +181,7 @@ async def roll(msg: Message, t_min: int = 1, t_max: int = 100, n: int = 1, *args result = [random.randint(t_min, t_max) for i in range(n)] await msg.reply(f'掷出来啦: {result}') except Exception as result: - await BaseException_Handler("roll", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") + await BotLog.BaseException_Handler("roll", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") err_str = f"ERR! [{GetTime()}] roll\n```\n{traceback.format_exc()}\n```" #发送错误信息到指定频道 await bot.client.send(debug_ch, err_str) @@ -191,7 +190,7 @@ async def roll(msg: Message, t_min: int = 1, t_max: int = 100, n: int = 1, *args # 返回天气 @bot.command(name='we') async def Weather(msg: Message, city: str = "err"): - logging(msg) + BotLog.logging(msg) if city == "err": await msg.reply(f"函数参数错误,城市: `{city}`\n") return @@ -199,7 +198,7 @@ async def Weather(msg: Message, city: str = "err"): try: await Other.weather(msg, city) except Exception as result: - await BaseException_Handler("Weather", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") + await BotLog.BaseException_Handler("Weather", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") err_str = f"ERR! [{GetTime()}] Weather\n```\n{traceback.format_exc()}\n```" #发送错误信息到指定频道 await bot.client.send(debug_ch, err_str) @@ -211,7 +210,7 @@ async def Weather(msg: Message, city: str = "err"): # 在不修改代码的前提下设置上色功能的服务器和监听消息 @bot.command() async def Color_Set_GM(msg: Message, Card_Msg_id: str): - logging(msg) + BotLog.logging(msg) if msg.author_id == master_id: await GrantRoles.Color_SetGm(msg, Card_Msg_id) @@ -225,7 +224,7 @@ async def Grant_Roles(b: Bot, event: Event): # 给用户上色(在发出消息后,机器人自动添加回应) @bot.command(name='Color_Set', aliases=['color_set']) async def Color_Set(msg: Message): - logging(msg) + BotLog.logging(msg) if msg.author_id == master_id: await GrantRoles.Color_SetMsg(bot, msg) @@ -242,21 +241,21 @@ async def thanks_sponser(): # 普通翻译指令 @bot.command(name='TL', aliases=['tl']) async def translation(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) await Translate.translate_main(msg, ' '.join(arg)) #查看当前占用的实时翻译栏位 @bot.command() async def CheckTL(msg: Message): - logging(msg) + BotLog.logging(msg) await msg.reply(f"目前已使用栏位:{Translate.checkTL()}/{len(Translate.ListTL)}") # 关闭所有栏位的实时翻译(避免有些人用完不关) @bot.command(name='ShutdownTL', aliases=['SDTL']) async def ShutdownTL(msg: Message): - logging(msg) + BotLog.logging(msg) if msg.author.id != master_id: return #这条命令只有bot的作者可以调用 await Translate.Shutdown_TL(bot, msg) @@ -271,21 +270,21 @@ async def TL_Realtime(msg: Message, *arg): if word == "/TLOFF" or word == "/tloff" or word == '/tlon' or word == '/TLON': return # 翻译 - logging(msg) + BotLog.logging(msg) await Translate.translate_main(msg, ' '.join(arg)) # 开启实时翻译功能 @bot.command(name='TLON', aliases=['tlon']) async def TLON(msg: Message): - logging(msg) + BotLog.logging(msg) await Translate.Open_TL(msg) # 关闭实时翻译功能 @bot.command(name='TLOFF', aliases=['tloff']) async def TLOFF(msg: Message): - logging(msg) + BotLog.logging(msg) await Translate.Close_TL(msg) @@ -297,7 +296,7 @@ async def TLOFF(msg: Message): # 开始打游戏 @bot.command() async def gaming(msg: Message, game: int = 1): - logging(msg) + BotLog.logging(msg) #await bot.client.update_playing_game(3,1)# 英雄联盟 if game == 1: ret = await status_active_game(453027) # 瓦洛兰特 @@ -310,7 +309,7 @@ async def gaming(msg: Message, game: int = 1): # 开始听歌 @bot.command() async def singing(msg: Message, music: str = "err", singer: str = "err"): - logging(msg) + BotLog.logging(msg) if music == "err" or singer == "err": await msg.reply(f"函数参数错误,music: `{music}` singer: `{singer}`") return @@ -322,7 +321,7 @@ async def singing(msg: Message, music: str = "err", singer: str = "err"): # 停止打游戏1/听歌2 @bot.command(name='sleeping') async def sleeping(msg: Message, d: int = 1): - logging(msg) + BotLog.logging(msg) ret = await status_delete(d) if d == 1: await msg.reply(f"{ret['message']},阿狸下号休息啦!") @@ -342,7 +341,7 @@ async def Login_Forbidden_send(msg: Message): # 手动设置禁止登录的全局变量状态 @bot.command(name='lf') async def Login_Forbidden_Change(msg: Message): - logging(msg) + BotLog.logging(msg) if msg.author_id == master_id: global Login_Forbidden if Login_Forbidden: @@ -356,7 +355,7 @@ async def Login_Forbidden_Change(msg: Message): # 存储用户游戏id @bot.command() async def saveid(msg: Message, *args): - logging(msg) + BotLog.logging(msg) if args == (): await msg.reply(f"您没有提供您的游戏id:`{args}`") return @@ -372,7 +371,7 @@ async def saveid(msg: Message, *args): # 已保存id总数 @bot.command(name='saveid-a') async def saveid_all(msg: Message): - logging(msg) + BotLog.logging(msg) try: await saveid_count(msg) except Exception as result: @@ -384,7 +383,7 @@ async def saveid_all(msg: Message): # 实现读取用户游戏ID并返回 @bot.command(name="myid", aliases=['MYID']) # 这里的aliases是别名 async def myid(msg: Message, *args): - logging(msg) + BotLog.logging(msg) if args != (): await msg.reply(f"`/myid`命令不需要参数!") return @@ -400,7 +399,7 @@ async def myid(msg: Message, *args): # 查询游戏错误码 @bot.command(name='val', aliases=['van', 'VAN', 'VAL']) async def val_err(msg: Message, numS: str = "-1", *arg): - logging(msg) + BotLog.logging(msg) try: await val_errcode(msg, numS) except Exception as result: @@ -410,20 +409,20 @@ async def val_err(msg: Message, numS: str = "-1", *arg): #关于dx报错的解决方法 @bot.command(name='DX', aliases=['dx']) # 新增别名dx async def dx(msg: Message): - logging(msg) + BotLog.logging(msg) await dx123(msg) ###########################################vip###################################################### #用来存放roll的频道/服务器/回应用户的dict -from utils.FileManage import VipShopBgDict, VipRollDcit, UserPwdReauth +from utils.FileManage import VipShopBgDict, VipRollDcit, UserPwdReauth,VipUserDict # 新建vip的uuid,第一个参数是天数,第二个参数是数量 @bot.command(name="vip-a") async def get_vip_uuid(msg: Message, day: int = 30, num: int = 10): - logging(msg) + BotLog.logging(msg) try: if msg.author_id == master_id: text = await BotVip.create_vip_uuid(num, day) @@ -446,7 +445,7 @@ async def get_vip_uuid(msg: Message, day: int = 30, num: int = 10): # 兑换vip @bot.command(name="vip-u", aliases=['兑换']) async def buy_vip_uuid(msg: Message, uuid: str = 'err', *arg): - logging(msg) + BotLog.logging(msg) if uuid == 'err': await msg.reply(f"只有输入vip的兑换码才可以操作哦!uuid: `{uuid}`") return @@ -456,7 +455,7 @@ async def buy_vip_uuid(msg: Message, uuid: str = 'err', *arg): global VipShopBgDict #在用户兑换vip的时候就创建此键值 VipShopBgDict['cache'][msg.author_id] = {'cache_time': 0, 'cache_img': None} except Exception as result: - await BaseException_Handler("vip-u", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") + await BotLog.BaseException_Handler("vip-u", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") err_str = f"ERR! [{GetTime()}] vip-u\n```\n{traceback.format_exc()}\n```" #发送错误信息到指定频道 await bot.client.send(debug_ch, err_str) @@ -465,7 +464,7 @@ async def buy_vip_uuid(msg: Message, uuid: str = 'err', *arg): # 看vip剩余时间 @bot.command(name="vip-c") async def check_vip_timeremain(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) try: if not await BotVip.vip_ck(msg): return @@ -474,7 +473,7 @@ async def check_vip_timeremain(msg: Message, *arg): ret_cm = await BotVip.vip_time_remain_cm(ret_t) await msg.reply(ret_cm) except Exception as result: - await BaseException_Handler("vip-c", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") + await BotLog.BaseException_Handler("vip-c", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") err_str = f"ERR! [{GetTime()}] vip-c\n```\n{traceback.format_exc()}\n```" #发送错误信息到指定频道 await bot.client.send(debug_ch, err_str) @@ -483,7 +482,7 @@ async def check_vip_timeremain(msg: Message, *arg): # 看vip用户列表 @bot.command(name="vip-l") async def list_vip_user(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) try: if msg.author_id == master_id: text = await BotVip.fetch_vip_user() @@ -558,7 +557,7 @@ async def check_vip_img_task(): @bot.command(name="vip-img") async def check_vip_img_task(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) if msg.author_id == master_id: await check_vip_img() await msg.reply("背景图片diy检查完成!") @@ -569,7 +568,7 @@ async def check_vip_img_task(msg: Message, *arg): @bot.command(name="vip-shop") async def vip_shop_bg_set(msg: Message, icon: str = "err", *arg): - logging(msg) + BotLog.logging(msg) if icon != 'err' and ('http' not in icon or '](' not in icon): await msg.reply(f"请提供正确的图片url!\n当前:`{icon}`") return @@ -627,16 +626,16 @@ async def vip_shop_bg_set(msg: Message, icon: str = "err", *arg): print(f"[vip-shop] Au:{msg.author_id} add ", x3) except requester.HTTPRequester.APIRequestFailed as result: - await APIRequestFailed_Handler("vip_shop", traceback.format_exc(), msg, bot, None, cm) + await BotLog.APIRequestFailed_Handler("vip_shop", traceback.format_exc(), msg, bot, None, cm) VipShopBgDict['bg'][msg.author_id]["background"].remove(x3) #删掉里面的图片 print(f"[vip_shop] Au:{msg.author_id} remove(err_img)") except Exception as result: - await BaseException_Handler("vip_shop", traceback.format_exc(), msg, bot, None, cm, "建议加入帮助频道找我康康到底是啥问题") + await BotLog.BaseException_Handler("vip_shop", traceback.format_exc(), msg, bot, None, cm, "建议加入帮助频道找我康康到底是啥问题") @bot.command(name="vip-shop-s") async def vip_shop_bg_set_s(msg: Message, num: str = "err", *arg): - logging(msg) + BotLog.logging(msg) if num == 'err': await msg.reply(f"请提供正确的图片序号!\n当前:`{num}`") return @@ -678,14 +677,14 @@ async def vip_shop_bg_set_s(msg: Message, num: str = "err", *arg): print(f"[vip-shop-s] Au:{msg.author_id} switch to [{VipShopBgDict['bg'][msg.author_id]['background'][0]}]") except requester.HTTPRequester.APIRequestFailed as result: - await APIRequestFailed_Handler("vip_shop_s", traceback.format_exc(), msg, bot, None, cm) + await BotLog.APIRequestFailed_Handler("vip_shop_s", traceback.format_exc(), msg, bot, None, cm) except Exception as result: - await BaseException_Handler("vip_shop_s", traceback.format_exc(), msg, bot, None, cm, "您可能需要重新执行操作") + await BotLog.BaseException_Handler("vip_shop_s", traceback.format_exc(), msg, bot, None, cm, "您可能需要重新执行操作") @bot.command(name="vip-shop-d") async def vip_shop_bg_set_d(msg: Message, num: str = "err", *arg): - logging(msg) + BotLog.logging(msg) if num == 'err': await msg.reply(f"请提供正确的图片序号!\n当前:`{num}`") return @@ -717,9 +716,9 @@ async def vip_shop_bg_set_d(msg: Message, num: str = "err", *arg): print(f"[vip-shop-d] Au:{msg.author_id} delete [{del_img_url}]") except requester.HTTPRequester.APIRequestFailed as result: - await APIRequestFailed_Handler("vip_shop_d", traceback.format_exc(), msg, bot, None, cm) + await BotLog.APIRequestFailed_Handler("vip_shop_d", traceback.format_exc(), msg, bot, None, cm) except Exception as result: - await BaseException_Handler("vip_shop_d", traceback.format_exc(), msg, bot, None, cm, "您可能需要重新执行操作") + await BotLog.BaseException_Handler("vip_shop_d", traceback.format_exc(), msg, bot, None, cm, "您可能需要重新执行操作") # 判断消息的emoji回应,并记录id @@ -744,7 +743,7 @@ async def vip_roll_log(b: Bot, event: Event): # 开启一波抽奖 @bot.command(name='vip-r', aliases=['vip-roll']) async def vip_roll(msg: Message, vday: int = 7, vnum: int = 5, rday: float = 1.0): - logging(msg) + BotLog.logging(msg) if msg.author_id != master_id: await msg.reply(f"您没有权限执行本命令") return @@ -829,7 +828,7 @@ async def vip_roll_task(): # 给所有vip用户添加时间,避免出现某些错误的时候浪费vip时间 @bot.command(name='vip-ta') async def vip_time_add(msg: Message, vday: int = 1, *arg): - logging(msg) + BotLog.logging(msg) if msg.author_id != master_id: await msg.reply(f"您没有权限执行此命令!") return @@ -852,7 +851,7 @@ async def vip_time_add(msg: Message, vday: int = 1, *arg): ##################################################################################### # 预加载用户的riot游戏id和玩家uuid(登录后Api获取) -from utils.FileManage import UserRiotName, SkinNotifyDict, EmojiDict, SkinRateDict +from utils.FileManage import UserRiotName, SkinNotifyDict, EmojiDict, SkinRateDict,ValBundleList # 用来存放auth对象(无法直接保存到文件) UserAuthDict = {'AP': {}} @@ -898,7 +897,7 @@ async def check_GloginRate(): #查询当前有多少用户登录了 @bot.command(name="ckau") async def check_UserAuthDict_len(msg: Message): - logging(msg) + BotLog.logging(msg) sz = len(UserAuthDict) res = f"UserAuthDict_len: `{sz}`" print(res) @@ -909,7 +908,7 @@ async def check_UserAuthDict_len(msg: Message): @bot.command(name='login') async def login(msg: Message, user: str = 'err', passwd: str = 'err', apSave='', *arg): print(f"[{GetTime()}] Au:{msg.author_id}_{msg.author.username}#{msg.author.identify_num} = /login {apSave}") - log_bot_user(msg.author_id) #这个操作只是用来记录用户和cmd总数的 + BotLog.log_bot_user(msg.author_id) #这个操作只是用来记录用户和cmd总数的 global Login_Forbidden, login_rate_limit, UserRiotName, UserAuthDict if not isinstance(msg, PrivateMessage): # 不是私聊的话,禁止调用本命令 await msg.reply(f"为了避免您的账户信息泄漏,请「私聊」使用本命令!\n用法:`/login 账户 密码`") @@ -1009,11 +1008,11 @@ async def login(msg: Message, user: str = 'err', passwd: str = 'err', apSave='', cm = await get_card(text, text_sub, icon_cm.that_it) await upd_card(send_msg['msg_id'], cm, channel_type=msg.channel_type) except requester.HTTPRequester.APIRequestFailed as result: #卡片消息发送失败 - await APIRequestFailed_Handler("login", traceback.format_exc(), msg, bot, send_msg, cm) + await BotLog.APIRequestFailed_Handler("login", traceback.format_exc(), msg, bot, send_msg, cm) except Exception as result: # 其他错误 err_str = f"[login] Au:{msg.author_id}\n```\n{traceback.format_exc()}\n```\n" await upd_card(send_msg['msg_id'], err_str, channel_type=msg.channel_type) - await BaseException_Handler("login", traceback.format_exc(), msg, bot, send_msg, cm) + await BotLog.BaseException_Handler("login", traceback.format_exc(), msg, bot, send_msg, cm) @bot.command(name='tfa') @@ -1054,13 +1053,13 @@ async def tfa_verify(msg: Message, tfa: str, *arg): # 更新消息 await upd_card(send_msg['msg_id'], cm, channel_type=msg.channel_type) except Exception as result: # 其他错误 - await BaseException_Handler("tfa", traceback.format_exc(), msg, bot) + await BotLog.BaseException_Handler("tfa", traceback.format_exc(), msg, bot) # 退出登录 @bot.command(name='logout') async def logout(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) try: global UserRiotName, UserAuthDict if msg.author_id not in UserAuthDict: #使用not in判断是否不存在 @@ -1085,12 +1084,12 @@ async def logout(msg: Message, *arg): print(log_text) except Exception as result: # 其他错误 - await BaseException_Handler("logout", traceback.format_exc(), msg, bot) + await BotLog.BaseException_Handler("logout", traceback.format_exc(), msg, bot) @bot.command(name='login-ap') async def login_acpw(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) try: if msg.author_id not in UserPwdReauth: await msg.reply(f"您没有保存账户密码或2fa用户,该命令无效") @@ -1105,7 +1104,7 @@ async def login_acpw(msg: Message, *arg): # 发送信息 await msg.reply(send_text) except Exception as result: # 其他错误 - await BaseException_Handler("login-ap", traceback.format_exc(), msg, bot) + await BotLog.BaseException_Handler("login-ap", traceback.format_exc(), msg, bot) # cookie重新登录 @@ -1230,7 +1229,7 @@ def is_CacheLatest(kook_user_id: str): # 获取每日商店的命令 @bot.command(name='shop', aliases=['SHOP']) async def get_daily_shop(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) if arg != (): await msg.reply(f"`/shop`命令不需要参数。您是否想`/login`?") return @@ -1359,7 +1358,7 @@ async def get_daily_shop(msg: Message, *arg): return except requester.HTTPRequester.APIRequestFailed as result: #卡片消息发送失败 - await APIRequestFailed_Handler("shop", traceback.format_exc(), msg, bot, send_msg, cm) + await BotLog.APIRequestFailed_Handler("shop", traceback.format_exc(), msg, bot, send_msg, cm) except Exception as result: err_str = f"ERR! [{GetTime()}] shop\n```\n{traceback.format_exc()}\n```" if "SkinsPanelLayout" in str(result): @@ -1368,13 +1367,13 @@ async def get_daily_shop(msg: Message, *arg): cm = await get_card(f"键值错误,需要重新登录", btext, icon_cm.whats_that) await upd_card(send_msg['msg_id'], cm, channel_type=msg.channel_type) else: - await BaseException_Handler("shop", traceback.format_exc(), msg, bot, send_msg, cm) + await BotLog.BaseException_Handler("shop", traceback.format_exc(), msg, bot, send_msg, cm) # 获取夜市 @bot.command(name='night', aliases=['NIGHT']) async def get_night_market(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) global NightMarketOff if arg != (): await msg.reply(f"`/night`命令不需要参数。您是否想`/login`?") @@ -1453,15 +1452,15 @@ async def get_night_market(msg: Message, *arg): return except requester.HTTPRequester.APIRequestFailed as result: #卡片消息发送失败 - await APIRequestFailed_Handler("night", traceback.format_exc(), msg, bot, send_msg, cm) + await BotLog.APIRequestFailed_Handler("night", traceback.format_exc(), msg, bot, send_msg, cm) except Exception as result: # 其他错误 - await BaseException_Handler("night", traceback.format_exc(), msg, bot, send_msg, cm) + await BotLog.BaseException_Handler("night", traceback.format_exc(), msg, bot, send_msg, cm) # 设置全局变量,打开/关闭夜市 @bot.command(name='open-nm') async def open_night_market(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) try: if msg.author_id == master_id: global NightMarketOff @@ -1482,7 +1481,7 @@ async def open_night_market(msg: Message, *arg): # 获取玩家卡面(添加point的别名) @bot.command(name='uinfo', aliases=['point', 'UINFO', 'POINT']) async def get_user_card(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) if arg != (): await msg.reply(f"`/uinfo`命令不需要参数。您是否想`/login`?") return @@ -1558,7 +1557,7 @@ async def get_user_card(msg: Message, *arg): return except requester.HTTPRequester.APIRequestFailed as result: #卡片消息发送失败 - await APIRequestFailed_Handler("uinfo", traceback.format_exc(), msg, bot, send_msg, cm) + await BotLog.APIRequestFailed_Handler("uinfo", traceback.format_exc(), msg, bot, send_msg, cm) except Exception as result: err_str = f"ERR! [{GetTime()}] uinfo\n```\n{traceback.format_exc()}\n```" if "Identity" in str(result) or "Balances" in str(result): @@ -1566,13 +1565,13 @@ async def get_user_card(msg: Message, *arg): cm2 = await get_card(f"键值错误,需要重新登录", f"KeyError:{result}, please re-login", icon_cm.lagging) await upd_card(send_msg['msg_id'], cm2, channel_type=msg.channel_type) else: - await BaseException_Handler("uinfo", traceback.format_exc(), msg, bot, send_msg, cm) + await BotLog.BaseException_Handler("uinfo", traceback.format_exc(), msg, bot, send_msg, cm) # 获取捆绑包信息(无需登录) @bot.command(name='bundle', aliases=['skin']) async def get_bundle(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) if arg == (): await msg.reply(f"函数参数错误,name: `{arg}`\n") return @@ -1651,7 +1650,7 @@ async def clear_rate_err_user(): # 给一个皮肤评分(灵感来自微信小程序”瓦的小卖铺“) @bot.command(name="rate", aliases=['评分']) async def rate_skin_add(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) if check_rate_err_user(msg.author_id): await msg.reply(f"您有过不良评论记录,阿狸现已不允许您使用相关功能\n后台存放了所有用户的评论内容和评论时间。在此提醒,请不要在评论的时候发送不雅言论!") return @@ -1685,15 +1684,15 @@ async def rate_skin_add(msg: Message, *arg): await msg.reply(cm) except requester.HTTPRequester.APIRequestFailed as result: #卡片消息发送失败 - await APIRequestFailed_Handler("rate", traceback.format_exc(), msg, bot, None, cm) + await BotLog.APIRequestFailed_Handler("rate", traceback.format_exc(), msg, bot, None, cm) except Exception as result: # 其他错误 - await BaseException_Handler("rate", traceback.format_exc(), msg, bot, None, cm) + await BotLog.BaseException_Handler("rate", traceback.format_exc(), msg, bot, None, cm) #选择皮肤(这个命令必须跟着上面的命令用) @bot.command(name="rts") async def rate_skin_select(msg: Message, index: str = "err", rating: str = "err", *arg): - logging(msg) + BotLog.logging(msg) if check_rate_err_user(msg.author_id): await msg.reply(f"您有过不良评论记录,阿狸现已不允许您使用相关功能\n后台存放了所有用户的评论内容和评论时间。在此提醒,请不要在评论的时候发送不雅言论!") return @@ -1765,15 +1764,15 @@ async def rate_skin_select(msg: Message, index: str = "err", rating: str = "err" await msg.reply(f"您需要执行 `/rate 皮肤名` 来查找皮肤\n再使用 `/rts` 进行选择") except requester.HTTPRequester.APIRequestFailed as result: #卡片消息发送失败 - await APIRequestFailed_Handler("rts", traceback.format_exc(), msg, bot, None, cm) + await BotLog.APIRequestFailed_Handler("rts", traceback.format_exc(), msg, bot, None, cm) except Exception as result: # 其他错误 - await BaseException_Handler("rts", traceback.format_exc(), msg, bot, None, cm) + await BotLog.BaseException_Handler("rts", traceback.format_exc(), msg, bot, None, cm) # 查看昨日牛人/屌丝 @bot.command(name="kkn") async def rate_skin_select(msg: Message): - logging(msg) + BotLog.logging(msg) if check_rate_err_user(msg.author_id): await msg.reply(f"您有过不良评论记录,阿狸现已不允许您使用相关功能\n后台存放了所有用户的评论内容和评论时间。在此提醒,请不要在评论的时候发送不雅言论!") return @@ -1814,9 +1813,9 @@ async def rate_skin_select(msg: Message): print(f"[{GetTime()}] [kkn] reply success") except requester.HTTPRequester.APIRequestFailed as result: #卡片消息发送失败 - await APIRequestFailed_Handler("rts", traceback.format_exc(), msg, bot, None, cm) + await BotLog.APIRequestFailed_Handler("rts", traceback.format_exc(), msg, bot, None, cm) except Exception as result: # 其他错误 - await BaseException_Handler("rts", traceback.format_exc(), msg, bot, None, cm) + await BotLog.BaseException_Handler("rts", traceback.format_exc(), msg, bot, None, cm) # 检查用户是否在错误用户里面 @@ -1850,7 +1849,7 @@ async def check_notify_err_user(msg: Message): #设置提醒(出现xx皮肤) @bot.command(name="notify-add", aliases=['notify-a']) async def add_skin_notify(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) if arg == (): await msg.reply(f"你没有提供皮肤参数!skin: `{arg}`") return @@ -1906,13 +1905,13 @@ async def add_skin_notify(msg: Message, *arg): await msg.reply(cm) except Exception as result: # 其他错误 - await BaseException_Handler("notify-add", traceback.format_exc(), msg, bot, None, cm) + await BotLog.BaseException_Handler("notify-add", traceback.format_exc(), msg, bot, None, cm) #选择皮肤(这个命令必须跟着上面的命令用) @bot.command(name="sts") async def select_skin_notify(msg: Message, n: str = "err", *arg): - logging(msg) + BotLog.logging(msg) if n == "err" or '-' in n: await msg.reply(f"参数不正确!请选择您需要提醒的皮肤序号") return @@ -1946,17 +1945,17 @@ async def select_skin_notify(msg: Message, n: str = "err", *arg): except requester.HTTPRequester.APIRequestFailed as result: #消息发送失败 err_str = f"ERR! [{GetTime()}] sts\n```\n{traceback.format_exc()}\n```\n" await bot.client.send(debug_ch, err_str) - await APIRequestFailed_Handler("sts", traceback.format_exc(), msg, bot, None) + await BotLog.APIRequestFailed_Handler("sts", traceback.format_exc(), msg, bot, None) except Exception as result: # 其他错误 err_str = f"ERR! [{GetTime()}] sts\n```\n{traceback.format_exc()}\n```\n" await bot.client.send(debug_ch, err_str) - await BaseException_Handler("sts", traceback.format_exc(), msg, bot, None) + await BotLog.BaseException_Handler("sts", traceback.format_exc(), msg, bot, None) # 显示当前设置好了的皮肤通知 @bot.command(name="notify-list", aliases=['notify-l']) async def list_skin_notify(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) try: if await check_notify_err_user(msg): return @@ -1972,13 +1971,13 @@ async def list_skin_notify(msg: Message, *arg): except Exception as result: err_str = f"ERR! [{GetTime()}] notify-list\n```\n{traceback.format_exc()}\n```" await bot.client.send(debug_ch, err_str) - await BaseException_Handler("notify-list", traceback.format_exc(), msg, bot, None) + await BotLog.BaseException_Handler("notify-list", traceback.format_exc(), msg, bot, None) # 删除已有皮肤通知 @bot.command(name="notify-del", aliases=['notify-d']) async def delete_skin_notify(msg: Message, uuid: str = "err", *arg): - logging(msg) + BotLog.logging(msg) if uuid == 'err': await msg.reply(f"请提供正确的皮肤uuid:`{uuid}`") return @@ -1997,7 +1996,7 @@ async def delete_skin_notify(msg: Message, uuid: str = "err", *arg): except Exception as result: err_str = f"ERR! [{GetTime()}] notify-del\n```\n{traceback.format_exc()}\n```" await bot.client.send(debug_ch, err_str) - await BaseException_Handler("notify-del", traceback.format_exc(), msg, bot, None) + await BotLog.BaseException_Handler("notify-del", traceback.format_exc(), msg, bot, None) #独立函数,为了封装成命令+定时 @@ -2194,7 +2193,7 @@ async def auto_skin_notify_task(): # 手动执行notify task @bot.command(name='notify-test') async def auto_skin_notify_cmd(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) if msg.author_id == master_id: await auto_skin_notify() @@ -2202,7 +2201,7 @@ async def auto_skin_notify_cmd(msg: Message, *arg): # 手动更新商店物品和价格 @bot.command(name='update_spb', aliases=['update', 'upd']) async def update_skin_price_bundle(msg: Message): - logging(msg) + BotLog.logging(msg) try: if msg.author_id == master_id: if await ValFileUpd.update_skins(msg): @@ -2228,11 +2227,11 @@ async def update_skin_price_bundle(msg: Message): # 显示当前阿狸加入了多少个服务器,以及用户数量 @bot.command(name='log-list', aliases=['log-l', 'log']) async def bot_log_list(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) try: if msg.author_id == master_id: - retDict = await log_bot_list(msg) # 获取用户/服务器列表 - res_text = await log_bot_list_text(retDict) # 获取text + retDict = await BotLog.log_bot_list(msg) # 获取用户/服务器列表 + res_text = await BotLog.log_bot_list_text(retDict) # 获取text cm = CardMessage() c = Card( @@ -2258,10 +2257,10 @@ async def bot_log_list(msg: Message, *arg): @bot.command(name='mem') async def proc_check(msg: Message, *arg): - logging(msg) + BotLog.logging(msg) try: if msg.author_id == master_id: - cm = await get_proc_info() + cm = await BotLog.get_proc_info() await msg.reply(cm) except: err_str = f"ERR! [{GetTime()}] mem\n```\n{traceback.format_exc()}\n```" From 72b147d9ba91b9c4fa708a9b7eb7b8eae79276db Mon Sep 17 00:00:00 2001 From: musnow Date: Fri, 3 Mar 2023 21:13:13 +0800 Subject: [PATCH 21/24] fix(BotLog): add return value, reset params of exception handler refactor(main): modify def params base on changes in BotLog --- code/main.py | 122 +++++++++++++++---------------------- code/utils/BotLog.py | 140 ++++++++++++++++++++++++------------------- 2 files changed, 124 insertions(+), 138 deletions(-) diff --git a/code/main.py b/code/main.py index d9fe6a9..3e2e6d8 100644 --- a/code/main.py +++ b/code/main.py @@ -9,23 +9,21 @@ import copy import zhconv import asyncio -from khl import (Bot, Event, EventTypes, Message, PrivateMessage, requester) +from khl import (Bot, Event, EventTypes, Message, PrivateMessage, requester,Channel) from khl.card import Card, CardMessage, Element, Module, Types, Struct from aiohttp import client_exceptions from PIL import Image, UnidentifiedImageError # 用于合成图片 -from utils import ShopRate, ShopImg, Help, GrantRoles, Translate, BotVip, BotLog, Other -from utils.valorant import ValFileUpd -from utils.KookApi import (icon_cm, status_active_game, status_active_music, status_delete, bot_offline, upd_card, +from .utils import ShopRate, ShopImg, Help, GrantRoles, Translate, BotVip, BotLog, Other +from .utils.valorant import ValFileUpd +from .utils.KookApi import (icon_cm, status_active_game, status_active_music, status_delete, bot_offline, upd_card, get_card) -from utils.valorant.Val import * -from utils.valorant.EzAuth import EzAuth, EzAuthExp -from utils.Gtime import GetTime, GetTimeStampOf8AM +from .utils.valorant.Val import * +from .utils.valorant.EzAuth import EzAuth, EzAuthExp +from .utils.Gtime import GetTime, GetTimeStampOf8AM # bot的token文件 -from utils.FileManage import config, ApiAuthLog, Save_All_File -# 用读取来的 config 初始化 bot,字段对应即可 -bot = Bot(token=config['token']['bot']) +from .utils.FileManage import config,bot,ApiAuthLog,Save_All_File # 只用来上传图片的bot bot_upimg = Bot(token=config['token']['img_upload_token']) @@ -33,8 +31,8 @@ master_id = config['master_id'] #在bot一开机的时候就获取log频道作为全局变量 -debug_ch = None -cm_send_test = None +debug_ch:Channel +cm_send_test:Channel NOTIFY_NUM = 3 # 非vip用户皮肤提醒栏位 VIP_BG_SIZE = 4 # vip用户背景图片数量限制 RATE_LIMITED_TIME = 180 # 全局登录速率超速等待秒数 @@ -96,10 +94,7 @@ async def Ahri(msg: Message, *arg): cm = Help.help_main(start_time) await msg.reply(cm) except Exception as result: - await BotLog.BaseException_Handler("ahri", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") - err_str = f"ERR! [{GetTime()}] ahri\n```\n{traceback.format_exc()}\n```" - #发送错误信息到指定频道 - await bot.client.send(debug_ch, err_str) + await BotLog.BaseException_Handler("ahri", traceback.format_exc(),msg,debug_send=debug_ch) # help命令(瓦洛兰特相关) @@ -110,10 +105,7 @@ async def Vhelp(msg: Message, *arg): cm = Help.help_val() await msg.reply(cm) except Exception as result: - await BotLog.BaseException_Handler("vhelp", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") - err_str = f"ERR! [{GetTime()}] vhelp\n```\n{traceback.format_exc()}\n```" - #发送错误信息到指定频道 - await bot.client.send(debug_ch, err_str) + await BotLog.BaseException_Handler("vhelp", traceback.format_exc(),msg,debug_send=debug_ch) # 当有人@机器人的时候进行回复,可识别出是否为机器人作者 @@ -130,9 +122,7 @@ async def atAhri(msg: Message): await msg.reply(f"呀,听说有人想我了,是吗?\n输入`/ahri` 或 `/vhelp` 打开帮助面板,和阿狸一起玩吧!") print(f"[atAhri] Au:{msg.author_id} msg.reply success!") except: - err_str = f"ERR! [{GetTime()}] atAhri\n```\n{traceback.format_exc()}\n```" - await msg.reply(f"{err_str}") - print(err_str) + await BotLog.BaseException_Handler("at_help", traceback.format_exc(),msg) ################################################################################################# @@ -157,10 +147,7 @@ async def countdown(msg: Message, time: int = 60, *args): cm.append(c1) await msg.reply(cm) except Exception as result: - await BotLog.BaseException_Handler("countdown", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") - err_str = f"ERR! [{GetTime()}] countdown\n```\n{traceback.format_exc()}\n```" - #发送错误信息到指定频道 - await bot.client.send(debug_ch, err_str) + await BotLog.BaseException_Handler("countdown", traceback.format_exc(), msg,debug_send=debug_ch) # 掷骰子 saying `!roll 1 100` in channel,or `/roll 1 100 5` to dice 5 times once @@ -181,10 +168,7 @@ async def roll(msg: Message, t_min: int = 1, t_max: int = 100, n: int = 1, *args result = [random.randint(t_min, t_max) for i in range(n)] await msg.reply(f'掷出来啦: {result}') except Exception as result: - await BotLog.BaseException_Handler("roll", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") - err_str = f"ERR! [{GetTime()}] roll\n```\n{traceback.format_exc()}\n```" - #发送错误信息到指定频道 - await bot.client.send(debug_ch, err_str) + await BotLog.BaseException_Handler("roll", traceback.format_exc(), msg,debug_send=debug_ch) # 返回天气 @@ -198,10 +182,7 @@ async def Weather(msg: Message, city: str = "err"): try: await Other.weather(msg, city) except Exception as result: - await BotLog.BaseException_Handler("Weather", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") - err_str = f"ERR! [{GetTime()}] Weather\n```\n{traceback.format_exc()}\n```" - #发送错误信息到指定频道 - await bot.client.send(debug_ch, err_str) + await BotLog.BaseException_Handler("Weather", traceback.format_exc(), msg,debug_send=debug_ch) ################################ grant roles for user ########################################## @@ -455,10 +436,7 @@ async def buy_vip_uuid(msg: Message, uuid: str = 'err', *arg): global VipShopBgDict #在用户兑换vip的时候就创建此键值 VipShopBgDict['cache'][msg.author_id] = {'cache_time': 0, 'cache_img': None} except Exception as result: - await BotLog.BaseException_Handler("vip-u", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") - err_str = f"ERR! [{GetTime()}] vip-u\n```\n{traceback.format_exc()}\n```" - #发送错误信息到指定频道 - await bot.client.send(debug_ch, err_str) + await BotLog.BaseException_Handler("vip-u", traceback.format_exc(), msg,debug_send=debug_ch) # 看vip剩余时间 @@ -473,11 +451,7 @@ async def check_vip_timeremain(msg: Message, *arg): ret_cm = await BotVip.vip_time_remain_cm(ret_t) await msg.reply(ret_cm) except Exception as result: - await BotLog.BaseException_Handler("vip-c", traceback.format_exc(), msg, bot, None, None, "建议加入帮助频道找我康康到底是啥问题") - err_str = f"ERR! [{GetTime()}] vip-c\n```\n{traceback.format_exc()}\n```" - #发送错误信息到指定频道 - await bot.client.send(debug_ch, err_str) - + await BotLog.BaseException_Handler("vip-c", traceback.format_exc(), msg,debug_send=debug_ch) # 看vip用户列表 @bot.command(name="vip-l") @@ -494,9 +468,7 @@ async def list_vip_user(msg: Message, *arg): else: await msg.reply("您没有权限操作此命令!") except Exception as result: - err_str = f"ERR! [{GetTime()}] list_vip_user\n```\n{traceback.format_exc()}\n```" - print(err_str) - await msg.reply(err_str) + await BotLog.BaseException_Handler("vip-l", traceback.format_exc(), msg) async def check_vip_img(): @@ -626,11 +598,11 @@ async def vip_shop_bg_set(msg: Message, icon: str = "err", *arg): print(f"[vip-shop] Au:{msg.author_id} add ", x3) except requester.HTTPRequester.APIRequestFailed as result: - await BotLog.APIRequestFailed_Handler("vip_shop", traceback.format_exc(), msg, bot, None, cm) + await BotLog.APIRequestFailed_Handler("vip_shop", traceback.format_exc(), msg, bot,cm) VipShopBgDict['bg'][msg.author_id]["background"].remove(x3) #删掉里面的图片 print(f"[vip_shop] Au:{msg.author_id} remove(err_img)") except Exception as result: - await BotLog.BaseException_Handler("vip_shop", traceback.format_exc(), msg, bot, None, cm, "建议加入帮助频道找我康康到底是啥问题") + await BotLog.BaseException_Handler("vip_shop", traceback.format_exc(), msg) @bot.command(name="vip-shop-s") @@ -677,9 +649,9 @@ async def vip_shop_bg_set_s(msg: Message, num: str = "err", *arg): print(f"[vip-shop-s] Au:{msg.author_id} switch to [{VipShopBgDict['bg'][msg.author_id]['background'][0]}]") except requester.HTTPRequester.APIRequestFailed as result: - await BotLog.APIRequestFailed_Handler("vip_shop_s", traceback.format_exc(), msg, bot, None, cm) + await BotLog.APIRequestFailed_Handler("vip_shop_s", traceback.format_exc(), msg, bot, cm) except Exception as result: - await BotLog.BaseException_Handler("vip_shop_s", traceback.format_exc(), msg, bot, None, cm, "您可能需要重新执行操作") + await BotLog.BaseException_Handler("vip_shop_s", traceback.format_exc(), msg) @bot.command(name="vip-shop-d") @@ -716,9 +688,9 @@ async def vip_shop_bg_set_d(msg: Message, num: str = "err", *arg): print(f"[vip-shop-d] Au:{msg.author_id} delete [{del_img_url}]") except requester.HTTPRequester.APIRequestFailed as result: - await BotLog.APIRequestFailed_Handler("vip_shop_d", traceback.format_exc(), msg, bot, None, cm) + await BotLog.APIRequestFailed_Handler("vip_shop_d", traceback.format_exc(), msg, bot, cm) except Exception as result: - await BotLog.BaseException_Handler("vip_shop_d", traceback.format_exc(), msg, bot, None, cm, "您可能需要重新执行操作") + await BotLog.BaseException_Handler("vip_shop_d", traceback.format_exc(), msg) # 判断消息的emoji回应,并记录id @@ -1008,11 +980,11 @@ async def login(msg: Message, user: str = 'err', passwd: str = 'err', apSave='', cm = await get_card(text, text_sub, icon_cm.that_it) await upd_card(send_msg['msg_id'], cm, channel_type=msg.channel_type) except requester.HTTPRequester.APIRequestFailed as result: #卡片消息发送失败 - await BotLog.APIRequestFailed_Handler("login", traceback.format_exc(), msg, bot, send_msg, cm) + await BotLog.APIRequestFailed_Handler("login", traceback.format_exc(), msg, bot, cm,send_msg=send_msg) except Exception as result: # 其他错误 err_str = f"[login] Au:{msg.author_id}\n```\n{traceback.format_exc()}\n```\n" await upd_card(send_msg['msg_id'], err_str, channel_type=msg.channel_type) - await BotLog.BaseException_Handler("login", traceback.format_exc(), msg, bot, send_msg, cm) + await BotLog.BaseException_Handler("login", traceback.format_exc(), msg, send_msg=send_msg,help="请加入帮助频道咨询,或尝试重新执行login命令") @bot.command(name='tfa') @@ -1053,7 +1025,7 @@ async def tfa_verify(msg: Message, tfa: str, *arg): # 更新消息 await upd_card(send_msg['msg_id'], cm, channel_type=msg.channel_type) except Exception as result: # 其他错误 - await BotLog.BaseException_Handler("tfa", traceback.format_exc(), msg, bot) + await BotLog.BaseException_Handler("tfa", traceback.format_exc(), msg,help="请加入帮助频道咨询,或尝试重新执行login命令") # 退出登录 @@ -1084,7 +1056,7 @@ async def logout(msg: Message, *arg): print(log_text) except Exception as result: # 其他错误 - await BotLog.BaseException_Handler("logout", traceback.format_exc(), msg, bot) + await BotLog.BaseException_Handler("logout", traceback.format_exc(), msg) @bot.command(name='login-ap') @@ -1104,7 +1076,7 @@ async def login_acpw(msg: Message, *arg): # 发送信息 await msg.reply(send_text) except Exception as result: # 其他错误 - await BotLog.BaseException_Handler("login-ap", traceback.format_exc(), msg, bot) + await BotLog.BaseException_Handler("login-ap", traceback.format_exc(), msg) # cookie重新登录 @@ -1358,7 +1330,7 @@ async def get_daily_shop(msg: Message, *arg): return except requester.HTTPRequester.APIRequestFailed as result: #卡片消息发送失败 - await BotLog.APIRequestFailed_Handler("shop", traceback.format_exc(), msg, bot, send_msg, cm) + await BotLog.APIRequestFailed_Handler("shop", traceback.format_exc(), msg, bot,cm,send_msg=send_msg) except Exception as result: err_str = f"ERR! [{GetTime()}] shop\n```\n{traceback.format_exc()}\n```" if "SkinsPanelLayout" in str(result): @@ -1367,7 +1339,7 @@ async def get_daily_shop(msg: Message, *arg): cm = await get_card(f"键值错误,需要重新登录", btext, icon_cm.whats_that) await upd_card(send_msg['msg_id'], cm, channel_type=msg.channel_type) else: - await BotLog.BaseException_Handler("shop", traceback.format_exc(), msg, bot, send_msg, cm) + await BotLog.BaseException_Handler("shop", traceback.format_exc(), msg, send_msg=send_msg) # 获取夜市 @@ -1452,9 +1424,9 @@ async def get_night_market(msg: Message, *arg): return except requester.HTTPRequester.APIRequestFailed as result: #卡片消息发送失败 - await BotLog.APIRequestFailed_Handler("night", traceback.format_exc(), msg, bot, send_msg, cm) + await BotLog.APIRequestFailed_Handler("night", traceback.format_exc(), msg, bot,cm,send_msg=send_msg) except Exception as result: # 其他错误 - await BotLog.BaseException_Handler("night", traceback.format_exc(), msg, bot, send_msg, cm) + await BotLog.BaseException_Handler("night", traceback.format_exc(), msg, send_msg=send_msg) # 设置全局变量,打开/关闭夜市 @@ -1557,7 +1529,7 @@ async def get_user_card(msg: Message, *arg): return except requester.HTTPRequester.APIRequestFailed as result: #卡片消息发送失败 - await BotLog.APIRequestFailed_Handler("uinfo", traceback.format_exc(), msg, bot, send_msg, cm) + await BotLog.APIRequestFailed_Handler("uinfo", traceback.format_exc(), msg, bot, cm,send_msg=send_msg) except Exception as result: err_str = f"ERR! [{GetTime()}] uinfo\n```\n{traceback.format_exc()}\n```" if "Identity" in str(result) or "Balances" in str(result): @@ -1565,7 +1537,7 @@ async def get_user_card(msg: Message, *arg): cm2 = await get_card(f"键值错误,需要重新登录", f"KeyError:{result}, please re-login", icon_cm.lagging) await upd_card(send_msg['msg_id'], cm2, channel_type=msg.channel_type) else: - await BotLog.BaseException_Handler("uinfo", traceback.format_exc(), msg, bot, send_msg, cm) + await BotLog.BaseException_Handler("uinfo", traceback.format_exc(), msg, send_msg=send_msg) # 获取捆绑包信息(无需登录) @@ -1684,9 +1656,9 @@ async def rate_skin_add(msg: Message, *arg): await msg.reply(cm) except requester.HTTPRequester.APIRequestFailed as result: #卡片消息发送失败 - await BotLog.APIRequestFailed_Handler("rate", traceback.format_exc(), msg, bot, None, cm) + await BotLog.APIRequestFailed_Handler("rate", traceback.format_exc(), msg, bot,cm) except Exception as result: # 其他错误 - await BotLog.BaseException_Handler("rate", traceback.format_exc(), msg, bot, None, cm) + await BotLog.BaseException_Handler("rate", traceback.format_exc(), msg) #选择皮肤(这个命令必须跟着上面的命令用) @@ -1764,9 +1736,9 @@ async def rate_skin_select(msg: Message, index: str = "err", rating: str = "err" await msg.reply(f"您需要执行 `/rate 皮肤名` 来查找皮肤\n再使用 `/rts` 进行选择") except requester.HTTPRequester.APIRequestFailed as result: #卡片消息发送失败 - await BotLog.APIRequestFailed_Handler("rts", traceback.format_exc(), msg, bot, None, cm) + await BotLog.APIRequestFailed_Handler("rts", traceback.format_exc(), msg, bot, cm) except Exception as result: # 其他错误 - await BotLog.BaseException_Handler("rts", traceback.format_exc(), msg, bot, None, cm) + await BotLog.BaseException_Handler("rts", traceback.format_exc(), msg) # 查看昨日牛人/屌丝 @@ -1813,9 +1785,9 @@ async def rate_skin_select(msg: Message): print(f"[{GetTime()}] [kkn] reply success") except requester.HTTPRequester.APIRequestFailed as result: #卡片消息发送失败 - await BotLog.APIRequestFailed_Handler("rts", traceback.format_exc(), msg, bot, None, cm) + await BotLog.APIRequestFailed_Handler("rts", traceback.format_exc(), msg, bot, cm) except Exception as result: # 其他错误 - await BotLog.BaseException_Handler("rts", traceback.format_exc(), msg, bot, None, cm) + await BotLog.BaseException_Handler("rts", traceback.format_exc(), msg) # 检查用户是否在错误用户里面 @@ -1905,7 +1877,7 @@ async def add_skin_notify(msg: Message, *arg): await msg.reply(cm) except Exception as result: # 其他错误 - await BotLog.BaseException_Handler("notify-add", traceback.format_exc(), msg, bot, None, cm) + await BotLog.BaseException_Handler("notify-add", traceback.format_exc(), msg) #选择皮肤(这个命令必须跟着上面的命令用) @@ -1945,11 +1917,11 @@ async def select_skin_notify(msg: Message, n: str = "err", *arg): except requester.HTTPRequester.APIRequestFailed as result: #消息发送失败 err_str = f"ERR! [{GetTime()}] sts\n```\n{traceback.format_exc()}\n```\n" await bot.client.send(debug_ch, err_str) - await BotLog.APIRequestFailed_Handler("sts", traceback.format_exc(), msg, bot, None) + await BotLog.APIRequestFailed_Handler("sts", traceback.format_exc(), msg, bot) except Exception as result: # 其他错误 err_str = f"ERR! [{GetTime()}] sts\n```\n{traceback.format_exc()}\n```\n" await bot.client.send(debug_ch, err_str) - await BotLog.BaseException_Handler("sts", traceback.format_exc(), msg, bot, None) + await BotLog.BaseException_Handler("sts", traceback.format_exc(), msg) # 显示当前设置好了的皮肤通知 @@ -1971,7 +1943,7 @@ async def list_skin_notify(msg: Message, *arg): except Exception as result: err_str = f"ERR! [{GetTime()}] notify-list\n```\n{traceback.format_exc()}\n```" await bot.client.send(debug_ch, err_str) - await BotLog.BaseException_Handler("notify-list", traceback.format_exc(), msg, bot, None) + await BotLog.BaseException_Handler("notify-list", traceback.format_exc(), msg) # 删除已有皮肤通知 @@ -1996,7 +1968,7 @@ async def delete_skin_notify(msg: Message, uuid: str = "err", *arg): except Exception as result: err_str = f"ERR! [{GetTime()}] notify-del\n```\n{traceback.format_exc()}\n```" await bot.client.send(debug_ch, err_str) - await BotLog.BaseException_Handler("notify-del", traceback.format_exc(), msg, bot, None) + await BotLog.BaseException_Handler("notify-del", traceback.format_exc(), msg) #独立函数,为了封装成命令+定时 diff --git a/code/utils/BotLog.py b/code/utils/BotLog.py index cfd4329..cd93efe 100644 --- a/code/utils/BotLog.py +++ b/code/utils/BotLog.py @@ -1,16 +1,14 @@ import json -import copy import traceback +from copy import deepcopy from khl import Message, PrivateMessage, Bot -from khl.card import Card, CardMessage, Element, Module, Types, Struct -from utils.KookApi import guild_list, guild_view, upd_card, get_card, icon_cm +from khl.card import Card, CardMessage, Element, Module, Types from PIL import Image, ImageDraw, ImageFont -from copy import deepcopy - -from utils.Gtime import GetTime # 用户数量的记录文件 -from utils.FileManage import BotUserDict +from .FileManage import bot,BotUserDict, FileManage +from .Gtime import GetTime +from .KookApi import guild_list, guild_view, upd_card, get_card, icon_cm # 记录私聊的用户信息 @@ -25,9 +23,8 @@ def log_bot_user(user_id: str): # 记录服务器中的用户信息 -def log_bot_guild(user_id: str, guild_id: str, time): +def log_bot_guild(user_id: str, guild_id: str, time) -> str: global BotUserDict - # BotUserDict['cmd_total']+=1 log_bot_user(user_id) # 服务器不存在,新的用户服务器 if guild_id not in BotUserDict['guild']['data']: @@ -46,7 +43,7 @@ def log_bot_guild(user_id: str, guild_id: str, time): # 在控制台打印msg内容,用作日志 -def logging(msg: Message): +def logging(msg: Message) -> None: try: now_time = GetTime() if isinstance(msg, PrivateMessage): @@ -70,7 +67,7 @@ def logging(msg: Message): # 画图,把当前加入的服务器总数等等信息以图片形式显示在README中 -async def log_bot_img(): +async def log_bot_img() -> None: bg = deepcopy(log_base_img) # 新建一个画布 draw = ImageDraw.Draw(bg) # 让bg这个图层能被写字 # 第一个参数 standard_text_position 是固定参数坐标 , 第二个是文字内容 , 第三个是字体 , 第四个是字体颜色 @@ -91,43 +88,38 @@ async def log_bot_img(): # bot用户记录dict处理 -async def log_bot_list(msg: Message): +async def log_bot_list(msg: Message) -> FileManage: global BotUserDict - try: - # 加入的服务器数量,api获取 - Glist = await guild_list() - Glist = Glist['data']['meta']['total'] - # api正常返回结果,赋值给全局变量 - BotUserDict['guild']['guild_total'] = Glist - # dict里面保存的服务器,有用户活跃的服务器数量 - BotUserDict['guild']['guild_active'] = len(BotUserDict['guild']['data']) - # 计算用户总数 - BotUserDict['user']['user_total'] = len(BotUserDict['user']['data']) - # 遍历列表,获取服务器名称 - tempDict = copy.deepcopy(BotUserDict) - for gu in tempDict['guild']['data']: - if 'name' not in tempDict['guild']['data'][gu]: - Gret = await guild_view(gu) - if Gret['code'] !=0: # 没有正常返回,可能是服务器被删除 - del BotUserDict['guild']['data'][gu] # 删除键值 - print(f"[log_bot_list] G:{gu} guild-view {Gret}") - continue - # 正常返回,赋值 - BotUserDict['guild']['data'][gu]['name'] = Gret['data']['name'] - else: + # 加入的服务器数量,api获取 + Glist = await guild_list() + Glist = Glist['data']['meta']['total'] + # api正常返回结果,赋值给全局变量 + BotUserDict['guild']['guild_total'] = Glist + # dict里面保存的服务器,有用户活跃的服务器数量 + BotUserDict['guild']['guild_active'] = len(BotUserDict['guild']['data']) + # 计算用户总数 + BotUserDict['user']['user_total'] = len(BotUserDict['user']['data']) + # 遍历列表,获取服务器名称 + tempDict = deepcopy(BotUserDict) + for gu in tempDict['guild']['data']: + if 'name' not in tempDict['guild']['data'][gu]: + Gret = await guild_view(gu) + if Gret['code'] != 0: # 没有正常返回,可能是服务器被删除 + del BotUserDict['guild']['data'][gu] # 删除键值 + print(f"[log_bot_list] G:{gu} guild-view {Gret}") continue - # 保存图片和文件 - await log_bot_img() - print("[log_bot_list] file handling finish, return BotUserDict") - return BotUserDict - except: - err_str = f"ERR! [{GetTime()}] log-list\n```\n{traceback.format_exc()}\n```" - await msg.reply(f"{err_str}") - print(err_str) + # 正常返回,赋值 + BotUserDict['guild']['data'][gu]['name'] = Gret['data']['name'] + else: + continue + # 保存图片和文件 + await log_bot_img() + print("[log_bot_list] file handling finish, return BotUserDict") + return BotUserDict # 通过log_bot_list分选出两列服务器名和服务器用户数 -async def log_bot_list_text(logDict: dict): +async def log_bot_list_text(logDict: dict) -> dict[str, str]: i = 1 text_name = "No 服务器名\n" text_user = "用户数\n" @@ -146,7 +138,20 @@ async def log_bot_list_text(logDict: dict): # 出现kook api异常的通用处理 -async def APIRequestFailed_Handler(def_name: str, excp, msg: Message, bot: Bot, send_msg=None, cm: CardMessage = None): +async def APIRequestFailed_Handler(def_name: str, + excp: str, + msg: Message, + bot: Bot, + cm: CardMessage = None, + send_msg: dict[str, str] = {}) -> None: + """Args: + - def_name: name of def to print in log + - excp: taraceback.fromat_exc() + - msg: khl.Message + - bot: khl.Bot + - cm: khl.card.CardMessage, for json.dumps / resend + - send_msg: return value of msg.reply or bot.send + """ err_str = f"ERR! [{GetTime()}] {def_name} Au:{msg.author_id} APIRequestFailed\n{excp}" print(err_str) text = f"啊哦,出现了一些问题" @@ -168,7 +173,7 @@ async def APIRequestFailed_Handler(def_name: str, excp, msg: Message, bot: Bot, text_sub = f"阿狸无法向您发出私信,请检查你的隐私设置" cm0 = await get_card(text, text_sub, icon_cm.lagging) - if send_msg != None: # 非none则执行更新消息,而不是直接发送 + if send_msg: # 非none则执行更新消息,而不是直接发送 await upd_card(send_msg['msg_id'], cm0, channel_type=msg.channel_type) else: await msg.reply(cm0) @@ -176,12 +181,19 @@ async def APIRequestFailed_Handler(def_name: str, excp, msg: Message, bot: Bot, # 基础错误的处理,带login提示(部分命令不需要这个提示) async def BaseException_Handler(def_name: str, - excp, + excp: str, msg: Message, - bot: Bot, - send_msg=None, - cm: CardMessage = None, - help="您可能需要重新执行/login操作"): + send_msg: dict[str, str] = {}, + debug_send = None, + help="建议加入帮助频道找我康康到底是啥问题") -> None: # type: ignore + """Args: + - def_name: name of def to print in log + - excp: taraceback.fromat_exc() + - msg: khl.Message + - send_msg: return value of msg.reply or bot.send + - debug_send: Channel obj for sending err_str, send if not None + - help: str for help_info, replyed in msg.reply + """ err_str = f"ERR! [{GetTime()}] {def_name} Au:{msg.author_id}\n```\n{excp}\n```" print(err_str) cm0 = CardMessage() @@ -192,28 +204,30 @@ async def BaseException_Handler(def_name: str, c.append(Module.Divider()) c.append(Module.Section('有任何问题,请加入帮助服务器与我联系', Element.Button('帮助', 'https://kook.top/gpbTwZ', Types.Click.LINK))) cm0.append(c) - if send_msg != None: # 非none则执行更新消息,而不是直接发送 + if send_msg: # 非{}则执行更新消息,而不是直接发送 await upd_card(send_msg['msg_id'], cm0, channel_type=msg.channel_type) else: await msg.reply(cm0) + # 如果debug_send不是None,则发送信息到报错频道 + if debug_send: + await bot.client.send(debug_send, err_str) ############################################################################################# -import psutil,os +import psutil, os + + # 获取进程信息 -async def get_proc_info(): +async def get_proc_info() -> CardMessage: p = psutil.Process(os.getpid()) - text =f"霸占的CPU百分比:{p.cpu_percent()} %\n" - text+=f"占用的MEM百分比:{format(p.memory_percent(), '.3f')} %\n" - text+=f"吃下的物理内存:{format((p.memory_info().rss / 1024 / 1024), '.4f')} MB\n" - text+=f"开辟的虚拟内存:{format((p.memory_info().vms / 1024 / 1024), '.4f')} MB\n" - text+=f"IO信息:\n{p.io_counters()}" + text = f"霸占的CPU百分比:{p.cpu_percent()} %\n" + text += f"占用的MEM百分比:{format(p.memory_percent(), '.3f')} %\n" + text += f"吃下的物理内存:{format((p.memory_info().rss / 1024 / 1024), '.4f')} MB\n" + text += f"开辟的虚拟内存:{format((p.memory_info().vms / 1024 / 1024), '.4f')} MB\n" + text += f"IO信息:\n{p.io_counters()}" cm = CardMessage() - c = Card( - Module.Header(f"来看看阿狸当前的负载吧!"), - Module.Context(f"记录于 {GetTime()}"),Module.Divider(), - Module.Section(Element.Text(text,Types.Text.KMD)) - ) + c = Card(Module.Header(f"来看看阿狸当前的负载吧!"), Module.Context(f"记录于 {GetTime()}"), Module.Divider(), + Module.Section(Element.Text(text, Types.Text.KMD))) cm.append(c) return cm \ No newline at end of file From f8f02f3daf16718f62a18e9c9a415daae5614c40 Mon Sep 17 00:00:00 2001 From: musnow Date: Fri, 3 Mar 2023 22:00:03 +0800 Subject: [PATCH 22/24] fix(main): add try/except in vip-r --- code/main.py | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/code/main.py b/code/main.py index 3e2e6d8..2a7f9de 100644 --- a/code/main.py +++ b/code/main.py @@ -716,22 +716,26 @@ async def vip_roll_log(b: Bot, event: Event): @bot.command(name='vip-r', aliases=['vip-roll']) async def vip_roll(msg: Message, vday: int = 7, vnum: int = 5, rday: float = 1.0): BotLog.logging(msg) - if msg.author_id != master_id: - await msg.reply(f"您没有权限执行本命令") - return - # 设置开始抽奖 - global VipRollDcit - cm = BotVip.roll_vip_start(vnum, vday, rday) - roll_ch = await bot.client.fetch_public_channel(msg.ctx.channel.id) - roll_send = await bot.client.send(roll_ch, cm) - VipRollDcit[roll_send['msg_id']] = {} - VipRollDcit[roll_send['msg_id']]['time'] = time.time() + rday * 86400 - VipRollDcit[roll_send['msg_id']]['nums'] = vnum - VipRollDcit[roll_send['msg_id']]['days'] = vday - VipRollDcit[roll_send['msg_id']]['channel_id'] = msg.ctx.channel.id - VipRollDcit[roll_send['msg_id']]['guild_id'] = msg.ctx.guild.id - VipRollDcit[roll_send['msg_id']]['user'] = list() - print(f"[vip-roll] card message send to {msg.ctx.channel.id}") + try: + if msg.author_id != master_id: + await msg.reply(f"您没有权限执行本命令") + return + # 设置开始抽奖 + global VipRollDcit + cm = BotVip.roll_vip_start(vnum, vday, rday) + roll_ch = await bot.client.fetch_public_channel(msg.ctx.channel.id) + roll_send = await bot.client.send(roll_ch, cm) + VipRollDcit[roll_send['msg_id']] = { # type: ignore + 'time': time.time() + rday * 86400, + 'nums': vnum, + 'days': vday, + 'channel_id': msg.ctx.channel.id, + 'guild_id': msg.ctx.guild.id, + 'user': [] + } + print(f"[vip-roll] card message send to {msg.ctx.channel.id}") + except: + await BotLog.BaseException_Handler("vip-r",traceback.format_exc(),msg) @bot.task.add_interval(seconds=80) @@ -1291,11 +1295,13 @@ async def get_daily_shop(msg: Message, *arg): print(log_time + f"- [Drawing] {format(time.time() - draw_time,'.4f')} - [Au] {msg.author_id}") # 判断是否需要上传,false不需要 if upload_flag: + # 上传图片 imgByteArr = io.BytesIO() bg.save(imgByteArr, format='PNG') - imgByte = imgByteArr.getvalue() - dailyshop_img_src = await bot_upimg.client.create_asset(imgByte) # 上传图片 - if is_vip: # 如果在bg里面代表有自定义背景图,需更新status + imgByte = imgByteArr.getvalue() + dailyshop_img_src = await bot_upimg.client.create_asset(imgByte) # type: ignore + # 如果在bg里面代表有自定义背景图,需更新status + if is_vip: if msg.author_id in VipShopBgDict['bg']: VipShopBgDict['bg'][msg.author_id]['status'] = True # 设置商店图片缓存+图片缓存的时间 @@ -1743,7 +1749,7 @@ async def rate_skin_select(msg: Message, index: str = "err", rating: str = "err" # 查看昨日牛人/屌丝 @bot.command(name="kkn") -async def rate_skin_select(msg: Message): +async def show_shoprate(msg: Message): BotLog.logging(msg) if check_rate_err_user(msg.author_id): await msg.reply(f"您有过不良评论记录,阿狸现已不允许您使用相关功能\n后台存放了所有用户的评论内容和评论时间。在此提醒,请不要在评论的时候发送不雅言论!") From ca67287cfc076ffb1a199abbf43c69809cf4fa60 Mon Sep 17 00:00:00 2001 From: musnow Date: Fri, 3 Mar 2023 22:01:03 +0800 Subject: [PATCH 23/24] feat(FileManage): add bot refactor(utils): using 'from . import' to replace 'from utils. import' --- code/utils/BotVip.py | 8 ++++---- code/utils/FileManage.py | 6 ++++-- code/utils/GrantRoles.py | 8 +++----- code/utils/KookApi.py | 4 +--- code/utils/ShopImg.py | 4 ++-- code/utils/ShopRate.py | 4 ++-- code/utils/Translate.py | 2 +- code/utils/valorant/EzAuth.py | 4 ++-- 8 files changed, 19 insertions(+), 21 deletions(-) diff --git a/code/utils/BotVip.py b/code/utils/BotVip.py index 540eab9..90cf888 100644 --- a/code/utils/BotVip.py +++ b/code/utils/BotVip.py @@ -7,10 +7,10 @@ from khl import Message, Bot, Channel from khl.card import Card, CardMessage, Element, Module, Types from datetime import datetime, timedelta -from utils.KookApi import icon_cm,bot -from utils.Gtime import GetTime -from utils.FileManage import VipShopBgDict,config -from utils.ShopImg import img_requestor +from .KookApi import icon_cm +from .Gtime import GetTime +from .FileManage import bot,VipShopBgDict,config +from .ShopImg import img_requestor #下图用于替换违规的vip图片 diff --git a/code/utils/FileManage.py b/code/utils/FileManage.py index 2fe6d11..ff4b149 100644 --- a/code/utils/FileManage.py +++ b/code/utils/FileManage.py @@ -3,8 +3,7 @@ import traceback from utils.Gtime import GetTime -FileList = [] - +FileList = [] # 用于保存需要写入到磁盘的文件 def open_file(path): with open(path, 'r', encoding='utf-8') as f: @@ -154,4 +153,7 @@ async def save_aio(self): AfdWebhook = FileManage("./log/AfdWebhook.json") # 爱发电的wh请求 +# 实例化一个khl的bot,方便其他模组调用 +from khl import Bot +bot = Bot(token=config['token']['bot']) print(f"[FileManage] load all files") # 走到这里代表所有文件都打开了 \ No newline at end of file diff --git a/code/utils/GrantRoles.py b/code/utils/GrantRoles.py index e2ff122..67156e8 100644 --- a/code/utils/GrantRoles.py +++ b/code/utils/GrantRoles.py @@ -1,14 +1,12 @@ import json -import time import aiohttp from khl import Bot, Message, PublicMessage, Event from khl.card import Card, CardMessage, Element, Module, Types -from utils.Gtime import GetTime # 预加载文件 -from utils.FileManage import SponsorDict, ColorIdDict, EmojiDict -from utils.KookApi import kook_headers - +from .FileManage import SponsorDict, ColorIdDict, EmojiDict +from .KookApi import kook_headers +from .Gtime import GetTime # 用于记录使用表情回应获取ID颜色的用户 def save_userid_color(userid: str, emoji: str): diff --git a/code/utils/KookApi.py b/code/utils/KookApi.py index 5656389..ccb73bd 100644 --- a/code/utils/KookApi.py +++ b/code/utils/KookApi.py @@ -4,9 +4,7 @@ from khl import Bot, ChannelPrivacyTypes from khl.card import Card, CardMessage, Module, Element, Types -from utils.FileManage import config -# 下方更新卡片消息需要bot -bot = Bot(token=config['token']['bot']) +from .FileManage import config,bot # kook的base_url和headers kook_base_url = "https://www.kookapp.cn" kook_headers = {f'Authorization': f"Bot {config['token']['bot']}"} diff --git a/code/utils/ShopImg.py b/code/utils/ShopImg.py index 2f1419c..31c80c2 100644 --- a/code/utils/ShopImg.py +++ b/code/utils/ShopImg.py @@ -9,8 +9,8 @@ import requests import zhconv from PIL import Image, ImageDraw, ImageFont, UnidentifiedImageError -from utils.valorant.Val import * -from utils.Gtime import * +from .valorant.Val import * +from .Gtime import * font_color = '#ffffff' # 文字颜色:白色 #用于临时存放图片的dict diff --git a/code/utils/ShopRate.py b/code/utils/ShopRate.py index 8648192..0e3d00e 100644 --- a/code/utils/ShopRate.py +++ b/code/utils/ShopRate.py @@ -4,8 +4,8 @@ import traceback from khl.card import Card, CardMessage, Module, Element, Types -from utils.valorant import Val -from utils.FileManage import config,SkinRateDict,GetTime +from .valorant import Val +from .FileManage import config,SkinRateDict,GetTime PLATFORM = config['platform'] # 平台 # 初始化leancloud diff --git a/code/utils/Translate.py b/code/utils/Translate.py index 7206ee9..6e29b8a 100644 --- a/code/utils/Translate.py +++ b/code/utils/Translate.py @@ -6,7 +6,7 @@ from khl.card import Card, CardMessage, Element, Module, Types # 读取彩云的key -from utils.FileManage import config +from .FileManage import config # 彩云key CyKey = config['caiyun'] diff --git a/code/utils/valorant/EzAuth.py b/code/utils/valorant/EzAuth.py index f1373bf..7329a3d 100644 --- a/code/utils/valorant/EzAuth.py +++ b/code/utils/valorant/EzAuth.py @@ -296,7 +296,7 @@ def get_riotuser_token(self) -> RiotUserToken: def save_cookies(self, path: str) -> None: """dump cookies_dict to path (w+) """ - cookies = requests.utils.dict_from_cookiejar(self.session.cookies) + cookies = requests.utils.dict_from_cookiejar(self.session.cookies) # type: ignore with open(path, "w+") as f: f.write(json.dumps(cookies)) @@ -306,4 +306,4 @@ def load_cookies(self, path: str) -> None: with open(path, "r") as f: load_cookies = json.loads(f.read()) - self.session.cookies = requests.utils.cookiejar_from_dict(load_cookies) \ No newline at end of file + self.session.cookies = requests.utils.cookiejar_from_dict(load_cookies) # type: ignore \ No newline at end of file From 26b74c4013af0c2416f4180b64a1d7fc4b2bcc11 Mon Sep 17 00:00:00 2001 From: musnow Date: Fri, 3 Mar 2023 22:07:25 +0800 Subject: [PATCH 24/24] docs(api/README): update docs --- README.md | 2 +- docs/valorant-shop-img-api.md | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index fe1befc..1476707 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -

Kook-Valorant--bot

+

Kook-Valorant-Bot

这是一个KOOK的「Valorant」小机器人

diff --git a/docs/valorant-shop-img-api.md b/docs/valorant-shop-img-api.md index e4bd0d6..1b73c1e 100644 --- a/docs/valorant-shop-img-api.md +++ b/docs/valorant-shop-img-api.md @@ -2,7 +2,7 @@ > Api展示页 https://val.musnow.top/ > -> Api根连接 https://val.musnow.top/api/ +> Api根连接 https://val.musnow.top/api/v2/ Api是一个网页链接,能够方便的被用户使用或被开发者调用,以实现特定功能。 @@ -29,7 +29,7 @@ Api是一个网页链接,能够方便的被用户使用或被开发者调用 由于该接口会直接跳转到图片,所以不支持开启了邮箱验证的用户,也不建议开发者调用 ~~~ -https://val.musnow.top/api/shop-img?token=API的密钥&account=账户&passwd=密码 +https://val.musnow.top/api/v2/shop-img?token=API的密钥&account=账户&passwd=密码 ~~~ 补充好上面的链接后,直接丢浏览器里面打开就OK。可以浏览器收藏一下,方便后续查看! @@ -41,18 +41,18 @@ https://val.musnow.top/api/shop-img?token=API的密钥&account=账户&passwd=密 若要添加自定义背景图,则链接应该如下 ~~~ -https://val.musnow.top/api/shop-img?token=API的密钥&account=账户&passwd=密码&img_src=背景图片链接 +https://val.musnow.top/api/v2/shop-img?token=API的密钥&account=账户&passwd=密码&img_src=背景图片链接 ~~~ 如果背景图是正方形(1-1) ~~~ -https://val.musnow.top/api/shop-img?token=API的密钥&account=账户&passwd=密码&img_src=背景图片链接&img_ratio=1 +https://val.musnow.top/api/v2/shop-img?token=API的密钥&account=账户&passwd=密码&img_src=背景图片链接&img_ratio=1 ~~~ 自定义背景图请求示例(16-9) ~~~ -https://val.musnow.top/api/shop-img?token=API的密钥&account=账户&passwd=密码&img_src=https://img.kookapp.cn/assets/2022-09/KV5krdRx080qo0f0.jpg +https://val.musnow.top/api/v2/shop-img?token=API的密钥&account=账户&passwd=密码&img_src=https://img.kookapp.cn/assets/2022-09/KV5krdRx080qo0f0.jpg ~~~ 结果示例图(16-9) @@ -87,7 +87,7 @@ https://val.musnow.top/api/shop-img?token=API的密钥&account=账户&passwd=密 注意,请求此接口之前,请先请求 `/login` 和 `/tfa` ~~~ -https://val.musnow.top/api/shop +https://val.musnow.top/api/v2/shop ~~~ 请求方法: `POST` @@ -167,7 +167,7 @@ https://valorant-api.com/v1/competitivetiers/{competitivetierUuid} 该接口用于登录,后台将会根据account将用户的登录信息缓存到内存中 ~~~ -https://val.musnow.top/api/login +https://val.musnow.top/api/v2/login ~~~ 请求方法:`POST` @@ -197,7 +197,7 @@ https://val.musnow.top/api/login 您需要先请求 `/shop-url` 接口,在用户获取到验证码后,再请求本接口;若在10min内没有收到 `/tfa` 接口请求,后台会以**邮箱验证超时**关闭该账户的会话。 ~~~ -https://val.musnow.top/api/tfa +https://val.musnow.top/api/v2/tfa ~~~ 请求方法:`POST` @@ -296,7 +296,7 @@ best/worse应该包含如下字段,其中`user_id`如果么有可以留空( ~~~python import requests -url = "https://val.musnow.top/api/shop" +url = "https://val.musnow.top/api/v2/shop" params = { "token":"api-token", "account": "拳头账户", @@ -329,7 +329,7 @@ return res.json() ```python def ApiRq2(list_shop:list,background='',img_ratio='0'): - url = "https://val.musnow.top/api/shop-draw" + url = "https://val.musnow.top/api/v2/shop-draw" params = { "token":"api-token", "list_shop": list_shop, @@ -372,7 +372,7 @@ time: 3.822338727999977 ```python def ApiRq3(best,worse,platform): - url = "https://val.musnow.top/api/shop-cmp" + url = "https://val.musnow.top/api/v2/shop-cmp" params = { "token":"api-token", "best":best,