From b0b521de32520590beff2429602fd6cdf8897b75 Mon Sep 17 00:00:00 2001 From: KimigaiiWuyi <444835641@qq.com> Date: Sun, 24 Oct 2021 01:38:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=90=8E=E5=85=88=E7=9C=8B?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=AE=B0=E5=BD=95=E5=92=8C=E6=8C=87=E4=BB=A4?= =?UTF-8?q?=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 64 +++++++----- __init__.py | 282 ++++++++++++++++++++++++++++++++------------------- getDB.py | 201 ++++++++++++++++++++++++++++-------- readme/4.PNG | Bin 0 -> 21569 bytes 4 files changed, 373 insertions(+), 174 deletions(-) create mode 100644 readme/4.PNG diff --git a/README.md b/README.md index c79f8e61..ae14ed9d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # GenshinUID / 原神UID查询 -一个HoshinoBot插件,用于查询原神UID信息,用于查询树脂/探索派遣状态,推送树脂快满了。 +一个HoshinoBot插件,用于查询原神UID信息,用于查询树脂/探索派遣状态,推送树脂快满了,每日签到。 **一定要读更新记录和指令!!** @@ -46,6 +46,14 @@ $ pip3 install -r requirements.txt ## 更新记录 +#### 2021-10-24 + +**重要:目前Cookies池又采用了新的方式(去除冗余),如果你是上个版本的使用者,请在更新后使用群聊命令:优化Cookies,无损迁移旧版本全部Cookies;(如果你是上上个版本的使用者,更新后使用命令:迁移Cookies)** + +修复:可能会导致的添加cookies问题 + +新增:绑定Cookies后可以实现米游社签到,如果开启自动签到之后,可以每天0:30准时签到,具体使用可以前往[指令](#指令)处查阅。 + #### 2021-10-17 **重要:目前Cookies池采用了新的方式,如果你是之前版本的使用者,请在更新后使用群聊命令:迁移Cookies,无损迁移旧版本全部Cookies** @@ -148,29 +156,33 @@ $ pip3 install -r requirements.txt (**括号内为可选词缀**,以下所有可以输出图片的,**命令后跟图可自定义背景图片**): -| 触发前缀 | 触发后缀/备注 | 效果 | 举例 | 备注 | -| :--------------------- | ---------------------- | ---------------------------------- | ------------------ | ---------------------------------------- | -| uid | | 获取角色信息一览(带武器信息) | uid123456789 | | -| uid | (上期)深渊 | 获取角色深渊总览(层数为最后一层) | uid123456789深渊 | | -| uid | (上期)深渊9/10/11/12 | 获取角色深渊某一层数据 | uid123456789深渊12 | | -| mys | | 角色信息(带武器信息,冒险等级) | mys123456 | 米游社通行证 | -| mys | (上期)深渊 | 获取角色深渊总览(层数为最后一层) | mys123456深渊 | 米游社通行证 | -| mys | (上期)深渊9/10/11/12 | 获取角色深渊某一层数据 | mys123456深渊12 | 米游社通行证 | -| UID | | 获取角色信息一览(不带武器信息) | UID123456789 | 旧版本,比例更和谐 | -| 绑定uid | | 当前qq号关联绑定uid | 绑定uid123456789 | 查询前缀前置条件 | -| 绑定mys | | 当前qq号关联绑定米游社通行证 | 绑定mys12345678 | 查询前缀前置条件 | -| 查询 | | 查询当前绑定角色信息一览 | 查询 | **必须**绑定过mys/uid | -| 查询(上期)深渊 | | 查询当前绑定角色深渊总览 | 查询深渊 | **必须**绑定过mys/uid | -| 查询(上期)深渊\d | | 查询当前绑定角色深渊某一层数据 | 查询深渊10 | **必须**绑定过mys/uid | -| 添加 | | 向cookies池添加cookies | 添加 _ga=balabala | **私聊**bot,注意空格 | -| 查询 @人 | | 获取@的群友的角色信息一览 | 查询 @Wuyi | | -| 查询(上期)深渊 @人 | | 获取@的群友的深渊信息一览 | 查询深渊 @Wuyi | | -| 查询(上期)深渊\d @人 | | 获取@的群友的深渊某一层数据 | 查询深渊10 @Wuyi | | -| 当前状态 | | 获取树脂、每日委托、派遣等信息 | 当前状态 | **必须**绑定过CK和uid | -| 开启推送 | | 开启推送,超过140树脂提醒旅行者 | 开启推送 | 群聊/私聊都可
**必须**绑定过CK和uid | -| 关闭推送 | | 关闭树脂快满的提醒 | 关闭推送 | 都可以 | -| 校验全部Cookies | | 校验当前池内全部Cookies状态 | 校验全部Cookies | **群聊** | -| 迁移Cookies | | 迁移旧版本全部Cookies | 迁移Cookies | **群聊** | +| 触发前缀 | 触发后缀/备注 | 效果 | 举例 | 备注 | +| :--------------------- | ---------------------- | ----------------------------------- | ------------------ | ---------------------------------------- | +| uid | | 获取角色信息一览(带武器信息) | uid123456789 | | +| uid | (上期)深渊 | 获取角色深渊总览(层数为最后一层) | uid123456789深渊 | | +| uid | (上期)深渊9/10/11/12 | 获取角色深渊某一层数据 | uid123456789深渊12 | | +| mys | | 角色信息(带武器信息,冒险等级) | mys123456 | 米游社通行证 | +| mys | (上期)深渊 | 获取角色深渊总览(层数为最后一层) | mys123456深渊 | 米游社通行证 | +| mys | (上期)深渊9/10/11/12 | 获取角色深渊某一层数据 | mys123456深渊12 | 米游社通行证 | +| UID | | 获取角色信息一览(不带武器信息) | UID123456789 | 旧版本,比例更和谐 | +| 绑定uid | | 当前qq号关联绑定uid | 绑定uid123456789 | 查询前缀前置条件 | +| 绑定mys | | 当前qq号关联绑定米游社通行证 | 绑定mys12345678 | 查询前缀前置条件 | +| 查询 | | 查询当前绑定角色信息一览 | 查询 | **必须**绑定过mys/uid | +| 查询(上期)深渊 | | 查询当前绑定角色深渊总览 | 查询深渊 | **必须**绑定过mys/uid | +| 查询(上期)深渊\d | | 查询当前绑定角色深渊某一层数据 | 查询深渊10 | **必须**绑定过mys/uid | +| 添加 | | 向cookies池添加cookies | 添加 _ga=balabala | **私聊**bot,注意空格 | +| 查询 @人 | | 获取@的群友的角色信息一览 | 查询 @Wuyi | | +| 查询(上期)深渊 @人 | | 获取@的群友的深渊信息一览 | 查询深渊 @Wuyi | | +| 查询(上期)深渊\d @人 | | 获取@的群友的深渊某一层数据 | 查询深渊10 @Wuyi | | +| 当前状态 | | 获取树脂、每日委托、派遣等信息 | 当前状态 | **必须**绑定过CK和uid | +| 开启推送 | | 开启推送,超过140树脂提醒旅行者 | 开启推送 | 群聊/私聊都可
**必须**绑定过CK和uid | +| 关闭推送 | | 关闭树脂快满的提醒 | 关闭推送 | 都可以 | +| 校验全部Cookies | | 校验当前池内全部Cookies状态 | 校验全部Cookies | **群聊** | +| 迁移Cookies | | 迁移旧版本(上上个版本)全部Cookies | 迁移Cookies | **群聊** | +| 优化Cookies | | 优化上个版本全部Cookies | 优化Cookies | **群聊** | +| 签到 | | 米游社签到 | 签到 | **必须**绑定过CK和uid | +| 开启自动签到 | | 开启每日米游社签到 | 开启自动签到 | 群聊/私聊都可
**必须**绑定过CK和uid | +| 关闭自动签到 | | 关闭每日米游社签到 | 关闭自动签到 | 群聊/私聊都可
**必须**绑定过CK和uid | ### 深渊查询: @@ -180,6 +192,10 @@ $ pip3 install -r requirements.txt ![3](https://raw.githubusercontent.com/KimigaiiWuyi/GenshinUID/main/readme/3.png) +### 签到: + +![3](https://raw.githubusercontent.com/KimigaiiWuyi/GenshinUID/main/readme/4.png) + ## 相关仓库 - [PaimonBot](https://github.com/XiaoMiku01/PaimonBot) - 插件原始代码来自于它 diff --git a/__init__.py b/__init__.py index b2b0b34f..46b774f2 100644 --- a/__init__.py +++ b/__init__.py @@ -1,5 +1,5 @@ from .getImg import draw_pic,draw_abyss_pic,draw_abyss0_pic -from .getDB import connectDB,selectDB,cookiesDB,cacheDB,deletecache,CheckDB,TransDB,OpenPush,GetMysInfo,GetDaily +from .getDB import connectDB,selectDB,cookiesDB,cacheDB,deletecache,CheckDB,TransDB,OpenPush,GetMysInfo,GetDaily,GetSignList,MysSign,GetSignInfo,OpCookies from nonebot import * from hoshino import Service,R,priv,util @@ -21,63 +21,48 @@ FILE_PATH = os.path.dirname(__file__) FILE2_PATH = os.path.join(FILE_PATH,'mys') Texture_PATH = os.path.join(FILE2_PATH,'texture2d') +daily_im = ''' +============== +(还剩{}补充满) +============== +原粹树脂:{}/160 +每日委托:{}/4 +探索派遣:{}/{} +======== +{}''' @sv.scheduled_job('cron', hour='0') async def delete(): deletecache() -@sv.scheduled_job('interval', minutes=30) -async def push(): +@sv.scheduled_job('cron', hour='0',minute="30") +async def dailysign(): conn = sqlite3.connect('ID_DATA.db') c = conn.cursor() - cursor = c.execute("SELECT * FROM NewCookies WHERE StatusA != ?",("off",)) + cursor = c.execute("SELECT * FROM NewCookiesTable WHERE StatusB != ?",("off",)) c_data = cursor.fetchall() for row in c_data: - raw_data = await GetDaily(str(row[1])) - dailydata = raw_data["data"] - resin_num = dailydata["current_resin"] - if resin_num >= row[5]: - re_time = dailydata["resin_recovery_time"] - m, s = divmod(int(re_time), 60) - h, m = divmod(m, 60) - time = "%02d小时%02d分钟%02d秒" % (h, m, s) + + im = await sign(str(row[0])) - task_num = dailydata["finished_task_num"] - travel_num = dailydata["current_expedition_num"] - max_travel_num = dailydata["max_expedition_num"] - travel_data = dailydata["expeditions"] - - travel_str = '' - - for i in travel_data: - name = i["avatar_side_icon"].split('/')[-1].split('.')[0].split('_')[-1] - statu = i['status'] - if statu == "Finished": - travel_str = travel_str + f"{name} : 完成\n" - else: - remain_time = i['remained_time'] - m1, s1 = divmod(int(remain_time), 60) - h1, m1 = divmod(m1, 60) - remain_time_str = "还剩%02d小时%02d分钟%02d秒" % (h1, m1, s1) - travel_str = travel_str + f"{name} : {remain_time_str}\n" - im = f''' -============== -你的树脂快满了!!! -(还剩{time}补充满) -============== -原粹树脂:{resin_num}/160 -每日委托:{task_num}/4 -探索派遣:{travel_num}/{max_travel_num} -======== -{travel_str} -'''.strip() - - if row[2] == "on": - await bot.send_private_msg(user_id = row[4],message = im) - else: - await bot.send_group_msg(group_id = row[2],message = f"[CQ:at,qq={row[4]}]" + "\n" + im) + if row[4] == "on": + await bot.send_private_msg(user_id = row[2],message = im) else: - pass + await bot.send_group_msg(group_id = row[4],message = f"[CQ:at,qq={row[2]}]" + "\n" + im) + +@sv.scheduled_job('interval', minutes=30) +async def push(): + daily_data = await daily() + if daily_data != None: + for i in daily_data: + if i['gid'] == "on": + await bot.send_private_msg(user_id = i['qid'],message = i['message']) + else: + await bot.send_group_msg(group_id = i['gid'],message = f"[CQ:at,qq={i['qid']}]" + "\n" + i['message']) + else: + pass + + @bot.on_message('private') async def setting(ctx): @@ -88,55 +73,112 @@ async def setting(ctx): if '添加 ' in message: try: mes = message.replace('添加 ','') - ltuid = re.search(r"ltuid=(\d*)", mes) - mysid_data = ltuid.group(0).split('=') + aid = re.search(r"account_id=(\d*)", mes) + mysid_data = aid.group(0).split('=') mysid = mysid_data[1] - - mys_data = await GetMysInfo(mysid,mes) + cookie = ';'.join(filter(lambda x: x.split('=')[0] in ["cookie_token", "account_id"], [i.strip() for i in mes.split(';')])) + mys_data = await GetMysInfo(mysid,cookie) mys_data = mys_data[0] uid = mys_data['data']['list'][0]['game_role_id'] - await cookiesDB(uid,mes) + await cookiesDB(uid,cookie,userid) await bot.send_msg(self_id=sid, user_id=userid, group_id=gid, message=f'添加Cookies成功!Cookies属于个人重要信息,如果你是在不知情的情况下添加,请马上修改米游社账户密码,保护个人隐私!') except: - await bot.send_msg(self_id=sid, user_id=userid, group_id=gid, message=f'校验失败!') + await bot.send_msg(self_id=sid, user_id=userid, group_id=gid, message=f'校验失败!请输入正确的Cookies!') elif '开启推送' in message: try: uid = await selectDB(userid,mode = "uid") - im = await OpenPush(int(uid[0]),userid,"on") + im = await OpenPush(int(uid[0]),userid,"on","StatusA") await bot.send_msg(self_id=sid, user_id=userid, group_id=gid, message=im) except: await bot.send_msg(self_id=sid, user_id=userid, group_id=gid, message="未找到uid绑定记录。") elif '关闭推送' in message: try: uid = await selectDB(userid,mode = "uid") - im = await OpenPush(int(uid[0]),userid,"off") + im = await OpenPush(int(uid[0]),userid,"off","StatusA") + await bot.send_msg(self_id=sid, user_id=userid, group_id=gid, message=im) + except: + await bot.send_msg(self_id=sid, user_id=userid, group_id=gid, message="未找到uid绑定记录。") + elif '开启自动签到' in message: + try: + uid = await selectDB(userid,mode = "uid") + im = await OpenPush(int(uid[0]),userid,"on","StatusB") + await bot.send_msg(self_id=sid, user_id=userid, group_id=gid, message=im) + except: + await bot.send_msg(self_id=sid, user_id=userid, group_id=gid, message="未找到uid绑定记录。") + elif '关闭自动签到' in message: + try: + uid = await selectDB(userid,mode = "uid") + im = await OpenPush(int(uid[0]),userid,"off","StatusA") await bot.send_msg(self_id=sid, user_id=userid, group_id=gid, message=im) except: await bot.send_msg(self_id=sid, user_id=userid, group_id=gid, message="未找到uid绑定记录。") -@sv.on_fullmatch('开启推送') +@sv.on_prefix('开启') +async def _(bot:HoshinoBot, ev: CQEvent): + message = ev.message.extract_plain_text() + m = ''.join(re.findall('[\u4e00-\u9fa5]',message)) + if m == "自动签到": + try: + gid = ev.group_id + qid = ev.sender["user_id"] + uid = await selectDB(ev.sender['user_id'],mode = "uid") + im = await OpenPush(int(uid[0]),ev.sender['user_id'],str(gid),"StatusB") + await bot.send(ev,im,at_sender=True) + except: + await bot.send(ev,"未绑定uid信息!",at_sender=True) + elif m == "推送": + try: + gid = ev.group_id + qid = ev.sender["user_id"] + uid = await selectDB(ev.sender['user_id'],mode = "uid") + im = await OpenPush(int(uid[0]),ev.sender['user_id'],str(gid),"StatusA") + await bot.send(ev,im,at_sender=True) + except: + await bot.send(ev,"未绑定uid信息!",at_sender=True) + +@sv.on_prefix('关闭') +async def _(bot:HoshinoBot, ev: CQEvent): + message = ev.message.extract_plain_text() + m = ''.join(re.findall('[\u4e00-\u9fa5]',message)) + if m == "自动签到": + try: + gid = ev.group_id + qid = ev.sender["user_id"] + uid = await selectDB(ev.sender['user_id'],mode = "uid") + im = await OpenPush(int(uid[0]),ev.sender['user_id'],"off","StatusB") + await bot.send(ev,im,at_sender=True) + except: + await bot.send(ev,"未绑定uid信息!",at_sender=True) + elif m == "推送": + try: + gid = ev.group_id + qid = ev.sender["user_id"] + uid = await selectDB(ev.sender['user_id'],mode = "uid") + im = await OpenPush(int(uid[0]),ev.sender['user_id'],"off","StatusA") + await bot.send(ev,im,at_sender=True) + except: + await bot.send(ev,"未绑定uid信息!",at_sender=True) + +@sv.on_fullmatch('签到') async def _(bot:HoshinoBot, ev: CQEvent): try: - gid = ev.group_id qid = ev.sender["user_id"] uid = await selectDB(ev.sender['user_id'],mode = "uid") - im = await OpenPush(int(uid[0]),ev.sender['user_id'],str(gid)) + uid = uid[0] + im = await sign(uid) await bot.send(ev,im,at_sender=True) except: - await bot.send(ev,"未绑定uid信息!",at_sender=True) + pass -@sv.on_fullmatch('关闭推送') +@sv.on_fullmatch('优化Cookies') async def _(bot:HoshinoBot, ev: CQEvent): try: - gid = ev.group_id - qid = ev.sender["user_id"] - uid = await selectDB(ev.sender['user_id'],mode = "uid") - im = await OpenPush(int(uid[0]),ev.sender['user_id'],"off") + im = await OpCookies() await bot.send(ev,im,at_sender=True) except: - await bot.send(ev,"未绑定uid信息!",at_sender=True) - + pass + @sv.on_fullmatch('校验全部Cookies') async def _(bot:HoshinoBot, ev: CQEvent): im = await CheckDB() @@ -152,45 +194,8 @@ async def _(bot:HoshinoBot, ev: CQEvent): try: uid = await selectDB(ev.sender['user_id'],mode = "uid") uid = uid[0] - raw_data = await GetDaily(uid) - dailydata = raw_data["data"] - resin_num = dailydata["current_resin"] - re_time = dailydata["resin_recovery_time"] - m, s = divmod(int(re_time), 60) - h, m = divmod(m, 60) - time = "%02d小时%02d分钟%02d秒" % (h, m, s) - - task_num = dailydata["finished_task_num"] - travel_num = dailydata["current_expedition_num"] - max_travel_num = dailydata["max_expedition_num"] - travel_data = dailydata["expeditions"] - - travel_str = '' - - for i in travel_data: - name = i["avatar_side_icon"].split('/')[-1].split('.')[0].split('_')[-1] - statu = i['status'] - if statu == "Finished": - travel_str = travel_str + f"{name} : 完成\n" - else: - remain_time = i['remained_time'] - m1, s1 = divmod(int(remain_time), 60) - h1, m1 = divmod(m1, 60) - remain_time_str = "还剩%02d小时%02d分钟%02d秒" % (h1, m1, s1) - travel_str = travel_str + f"{name} : {remain_time_str}\n" - - im = f''' -: -============== -(还剩{time}补充满) -============== -原粹树脂:{resin_num}/160 -每日委托:{task_num}/4 -探索派遣:{travel_num}/{max_travel_num} -======== -{travel_str} -'''.strip() - + mes = await daily("ask",uid) + im = mes[0]['message'] except: im = "没有找到绑定信息。" @@ -267,7 +272,7 @@ async def _(bot, ev): if len(re.findall(r"\d+", message)) == 1: floor_num = re.findall(r"\d+", message)[0] im = await draw_abyss_pic(uid[0],nickname,floor_num,image,uid[1]) - await bot.send(ev, im, at_sender=True) + await bot.send(ev, im, at_sender=True) else: im = await draw_abyss0_pic(uid[0],nickname,image,uid[1]) await bot.send(ev, im, at_sender=True) @@ -342,3 +347,68 @@ async def _(bot:HoshinoBot, ev: CQEvent): except: await bot.send(ev,'输入错误!') + + + +async def sign(uid): + sign_data = await MysSign(uid) + sign_info = await GetSignInfo(uid) + sign_info = sign_info['data'] + sign_list = await GetSignList() + status = sign_data['message'] + getitem = sign_list['data']['awards'][int(sign_info['total_sign_day'])-1]['name'] + getnum = sign_list['data']['awards'][int(sign_info['total_sign_day'])-1]['cnt'] + get_im = f"本次签到获得{getitem}x{getnum}" + if status == "OK" and sign_info['is_sign'] == True: + mes_im = "签到成功" + else: + mes_im = status + sign_missed = sign_info['sign_cnt_missed'] + im = "\n" + mes_im +"!" + "\n" + get_im + "\n" + f"本月漏签次数:{sign_missed}" + return im + +async def daily(mode = "push",uid = None): + temp_list = [] + conn = sqlite3.connect('ID_DATA.db') + c = conn.cursor() + if mode == "push": + cursor = c.execute("SELECT * FROM NewCookiesTable WHERE StatusA != ?",("off",)) + c_data = cursor.fetchall() + elif mode == "ask": + c_data = ([uid,0,0,0,0,0,0],) + + for row in c_data: + raw_data = await GetDaily(str(row[0])) + dailydata = raw_data["data"] + + resin_num = dailydata["current_resin"] + task_num = dailydata["finished_task_num"] + travel_num = dailydata["current_expedition_num"] + max_travel_num = dailydata["max_expedition_num"] + travel_data = dailydata["expeditions"] + + if resin_num >= row[6] : + + re_time = dailydata["resin_recovery_time"] + m, s = divmod(int(re_time), 60) + h, m = divmod(m, 60) + time = "%02d小时%02d分钟%02d秒" % (h, m, s) + + travel_str = '' + + for i in travel_data: + name = i["avatar_side_icon"].split('/')[-1].split('.')[0].split('_')[-1] + statu = i['status'] + if statu == "Finished": + travel_str = travel_str + f"{name} : 完成\n" + else: + remain_time = i['remained_time'] + m1, s1 = divmod(int(remain_time), 60) + h1, m1 = divmod(m1, 60) + remain_time_str = "还剩%02d小时%02d分钟%02d秒" % (h1, m1, s1) + travel_str = travel_str + f"{name} : {remain_time_str}\n" + send_mes = daily_im.format(time,resin_num,task_num,travel_num,max_travel_num,travel_str) + if row[1] != 0: + send_mes = "你的树脂快满了!" + send_mes + temp_list.append({"qid":row[2],"gid":row[3],"message":send_mes}) + return temp_list diff --git a/getDB.py b/getDB.py index 64e5180e..e2923422 100644 --- a/getDB.py +++ b/getDB.py @@ -17,14 +17,14 @@ mhyVersion = "2.11.1" FILE_PATH = os.path.abspath(os.path.join(os.getcwd(), "hoshino")) DATA_PATH = os.path.join(FILE_PATH,'config') -async def OpenPush(uid,qid,status): +async def OpenPush(uid,qid,status,mode): conn = sqlite3.connect('ID_DATA.db') c = conn.cursor() - cursor = c.execute("SELECT * from NewCookies WHERE UID = ?",(uid,)) + cursor = c.execute("SELECT * from NewCookiesTable WHERE UID = ?",(uid,)) c_data = cursor.fetchall() if len(c_data) != 0: try: - c.execute("UPDATE NewCookies SET StatusA = ?,QID = ? WHERE UID=?",(status,qid,uid)) + c.execute("UPDATE NewCookiesTable SET {s} = ?,QID = ? WHERE UID=?".format(s = mode),(status,qid,uid)) conn.commit() conn.close() return "成功!" @@ -37,21 +37,21 @@ async def CheckDB(): str = '' conn = sqlite3.connect('ID_DATA.db') c = conn.cursor() - cursor = c.execute("SELECT Cookies,UID from NewCookies") - for row in cursor: + cursor = c.execute("SELECT UID,Cookies from NewCookiesTable") + c_data = cursor.fetchall() + for row in c_data: try: - ltuid = re.search(r"ltuid=(\d*)", row[0]) - mysid_data = ltuid.group(0).split('=') + aid = re.search(r"account_id=(\d*)",row[1]) + mysid_data = aid.group(0).split('=') mysid = mysid_data[1] - - mys_data = await GetMysInfo(mysid,row[0]) + mys_data = await GetMysInfo(mysid,row[1]) mys_data = mys_data[0] uid = mys_data['data']['list'][0]['game_role_id'] - - str = str + f"uid{row[1]}/mysid{mysid}的Cookies是正常的!\n" + str = str + f"uid{row[0]}/mysid{mysid}的Cookies是正常的!\n" except: - str = str + f"uid{row[1]}/mysid{mysid}的Cookies是异常的!已删除该条Cookies!\n" - c.execute("DELETE from NewCookies where UID=?",(row[1],)) + str = str + f"uid{row[0]}的Cookies是异常的!已删除该条Cookies!\n" + c.execute("DELETE from NewCookiesTable where UID=?",(row[0],)) + c.execute("DELETE from CookiesCache where Cookies=?",(row[1],)) conn.commit() conn.close() return str @@ -66,26 +66,28 @@ async def TransDB(): conn.close() return "你没有需要迁移的数据库。" else: - c.execute('''CREATE TABLE IF NOT EXISTS NewCookies - (Cookies TEXT PRIMARY KEY NOT NULL, - UID INT, + c.execute('''CREATE TABLE IF NOT EXISTS NewCookiesTable + (UID INT PRIMARY KEY NOT NULL, + Cookies TEXT, + QID INT, StatusA TEXT, StatusB TEXT, - QID INT, + StatusC TEXT, NUM INT, Extra TEXT);''') cursor = c.execute("SELECT * from CookiesTable") c_data = cursor.fetchall() for row in c_data: try: - ltuid = re.search(r"ltuid=(\d*)", row[0]) - mysid_data = ltuid.group(0).split('=') + newcookies = ';'.join(filter(lambda x: x.split('=')[0] in ["cookie_token", "account_id"], [i.strip() for i in row[0].split(';')])) + aid = re.search(r"account_id=(\d*)", row[0]) + mysid_data = aid.group(0).split('=') mysid = mysid_data[1] mys_data = await GetMysInfo(mysid,row[0]) mys_data = mys_data[0] uid = mys_data['data']['list'][0]['game_role_id'] - c.execute("INSERT OR IGNORE INTO NewCookies (Cookies,UID,StatusA,StatusB,NUM) \ - VALUES (?, ?,?,?,?)",(row[0],uid,"off","off",140)) + c.execute("INSERT OR IGNORE INTO NewCookiesTable (Cookies,UID,StatusA,StatusB,StatusC,NUM) \ + VALUES (?, ?,?,?,?,?)",(newcookies,uid,"off","off","off",140)) str = str + f"uid{uid}/mysid{mysid}的Cookies已转移成功!\n" except: str = str + f"uid{uid}/mysid{mysid}的Cookies是异常的!已删除该条Cookies!\n" @@ -160,15 +162,15 @@ async def cacheDB(uid,mode = 1,mys = None): c_data = cursor.fetchall() if len(c_data)==0: - cookiesrow = c.execute("SELECT * FROM NewCookies ORDER BY RANDOM() limit 1") + cookiesrow = c.execute("SELECT * FROM NewCookiesTable ORDER BY RANDOM() limit 1") for row2 in cookiesrow: if mode == 1: c.execute("INSERT OR IGNORE INTO CookiesCache (Cookies,UID) \ - VALUES (?, ?)",(row2[0],uid)) + VALUES (?, ?)",(row2[1],uid)) if mode == 2: c.execute("INSERT OR IGNORE INTO CookiesCache (Cookies,MYSID) \ - VALUES (?, ?)",(row2[0],uid)) - use = row2[0] + VALUES (?, ?)",(row2[1],uid)) + use = row2[1] else: use = c_data[0][2] if mys: @@ -181,33 +183,78 @@ async def cacheDB(uid,mode = 1,mys = None): conn.close() return use -async def cookiesDB(uid,Cookies): +async def cookiesDB(uid,Cookies,qid): conn = sqlite3.connect('ID_DATA.db') c = conn.cursor() - c.execute('''CREATE TABLE IF NOT EXISTS NewCookies - (Cookies TEXT PRIMARY KEY NOT NULL, - UID INT, + c.execute('''CREATE TABLE IF NOT EXISTS NewCookiesTable + (UID INT PRIMARY KEY NOT NULL, + Cookies TEXT, + QID INT, StatusA TEXT, StatusB TEXT, - QID INT, + StatusC TEXT, NUM INT, Extra TEXT);''') - - c.execute("INSERT OR IGNORE INTO NewCookies (Cookies,UID,StatusA,StatusB,NUM) \ - VALUES (?, ?,?,?,?)",(Cookies,uid,"off","off",140)) + + cursor = c.execute("SELECT * from NewCookiesTable WHERE UID = ?",(uid,)) + c_data = cursor.fetchall() + if len(c_data) == 0 : + c.execute("INSERT OR IGNORE INTO NewCookiesTable (Cookies,UID,StatusA,StatusB,StatusC,NUM,QID) \ + VALUES (?, ?,?,?,?,?,?)",(Cookies,uid,"off","off","off",140,qid)) + else: + c.execute("UPDATE NewCookiesTable SET Cookies = ? WHERE UID=?",(Cookies,uid)) conn.commit() conn.close() +async def OpCookies(): + str = "" + conn = sqlite3.connect('ID_DATA.db') + c = conn.cursor() + test = c.execute("SELECT count(*) FROM sqlite_master WHERE type='table' AND name = 'NewCookies'") + if test == 0: + conn.commit() + conn.close() + return "你没有需要优化的数据库。" + else: + c.execute('''CREATE TABLE IF NOT EXISTS NewCookiesTable + (UID INT PRIMARY KEY NOT NULL, + Cookies TEXT, + QID INT, + StatusA TEXT, + StatusB TEXT, + StatusC TEXT, + NUM INT, + Extra TEXT);''') + cursor = c.execute("SELECT * from NewCookies") + c_data = cursor.fetchall() + for row in c_data: + try: + newcookies = ';'.join(filter(lambda x: x.split('=')[0] in ["cookie_token", "account_id"], [i.strip() for i in row[0].split(';')])) + aid = re.search(r"account_id=(\d*)", row[0]) + mysid_data = aid.group(0).split('=') + mysid = mysid_data[1] + mys_data = await GetMysInfo(mysid,row[0]) + mys_data = mys_data[0] + uid = mys_data['data']['list'][0]['game_role_id'] + c.execute("INSERT OR IGNORE INTO NewCookiesTable (Cookies,UID,StatusA,StatusB,StatusC,QID,NUM) \ + VALUES (?, ?,?,?,?,?,?)",(newcookies,row[1],row[2],row[3],"off",row[4],row[5])) + str = str + f"uid{row[1]}的Cookies已转移成功!\n" + except: + str = str + f"uid{row[1]}的Cookies是异常的!已删除该条Cookies!\n" + conn.commit() + conn.close() + return str + + async def OwnerCookies(uid): conn = sqlite3.connect('ID_DATA.db') c = conn.cursor() - try: - cursor = c.execute("SELECT * FROM NewCookies WHERE UID = ?",(uid,)) + cursor = c.execute("SELECT * FROM NewCookiesTable WHERE UID = ?",(uid,)) c_data = cursor.fetchall() - cookies = c_data[0][0] + cookies = c_data[0][1] except: return @@ -222,13 +269,24 @@ async def OwnerCookies(uid): - +def random_hex(length): + result = hex(random.randint(0,16**length)).replace('0x','').upper() + if len(result)yxwX8Ew5L2J*VcY^1y$MTXxBFhaRygKc+sxrkTR<~XZ~#v_U16q zhMFcRT=$=X=m0jO&hck$23(=mGxR8$I2M*>#$%fH8y6EjxfQnw8K2%T7`IKEsGFXB zdc2=LA3V#BJY9DAsYVn4!sr8y3Vv${WbiwP-#?=YqtA!_APOKWK?~=C7M3CXsP6pUL@vczIscI(FJS8I(>30zD*QbyhyEudH7M zK9y#WUB-oppr4uoaR0tlwH7c`(zr$yp1}6I0|JJ^{$4{o6`{*Uo5bAqO z69F$-XD;U9m$cd$5A5)>z*$jNU=GBi8z*~b&AtMKCZ;3-u7SiPi?B}n^Owt07WcEp zV~s6J6&oj49}KRA!s{%B9v9PqF0hCL#T87DOgSo~D1K{4T=E!zK0N3w-2fMigu@X* zSZ`0qw#r9ocFYa#;V**==qFY%I6HIL5L~lJ+tUUE2zSB{z0m8D1LR@ST7thB%R(-l z7SNcP72Cm=;EkUDlWgFY9E?iX(SOSZBYn$F1#iR?1ozk3FX%ti84KWhg`i;pib~J7 z#t870R%8YlHKvHzQxvh7A?qLE$6g74&y1l$zaG=v)F~A3M2EcfIq~xsC}p2UL;tyq zDDXT>I<8`4ri)1`hu^tQ#9Dq8Jr2R#W`Z^r^D9>sWTC8#IPuzTv$q}*l00rK8ilnH z1@W?6KF{Dq5>|^&F87h@9qYMWXDMCP7}M5iJJqAb?2L%}&;qTD@&8TfSUA>3>5I`T ziM8zgFas6y;^(09R`tVQ?@nF@K@gt@E7X${Se%e2aLCz;)orBWUU{ha>+v9R%7bE; z6Y>rZ{09EI!k)`f{bw9Zob*LRPAXqJ;6RbtGGF!HjI*io-3CdaLA44!#zCTIt3k_g>G6zuSS3S-8_kBtq2S|{o6*8+0D@`a>*iN{DMr_bA}`P z-OUa}_(qKZ@-02+#`QYC+0iG4f=9FVZTk9Q|C1!5v1it4E0X`AYo+0*pC1{K$KG!5 zHrHee{^IDDZI?M92Ybug>owa4swOMSyPhDIWdV4gKua?d#VLUQ&lpw}s#;mjGeExU zAdv3xvzwtyGsGT+)$xU-H99+IIo!Q#|9W3{SKiYvn(g6HmIK8Ml$HU?hkM+fSwF15 zXET6UMlO9s$M*Lk8abF{N->gsl@>}A;3yVs`tc)n`hztUaC%%Q0Mv>8k;hAUtEyXp z=oM7e1uA_zWA(P}VpYw~2LI#LiE8!CjAVGmGw*L1tkoA=zw3Zj(ywJT!sUrw_LG&5 zDC&0%2-$nCq)fsnNSFr6I8khH2|Fr6|GA7>JDgtFJ9_DRN{pv>HxIOb9DD|Xr#2|VilVzV1MAUkPQIwIeJ{HxZL&_)P^@Ooj)b{M;*A4xS&qa22K} zBe%R7AJi{y+vK6L&c`46s+ccb&4tnfn-MMr^-fPicx`{g6hZI>I~P%W-{1IE(*V_A zq~=2QpXCsiM`e}`drW>KI6OMva+K-{hsGEKq#q@cJ-v_~{+&~@|MfKcDeVmZq zccB763!{pDB0T4B2tdyRX$ubccOWKcwyzm)Hx)bMP?!Pw&uz!Wc1QdXgI_)_;(veE%huQYjMWk7}VpJK%d2R~+mgT-NxnISD??&HWuB+#jw&-?x)JpkeES!mWA6J5N7CJSzq%bR#D7W-V2NRHP z=>BuBLFyuI7o?#^le2}}FCnn{o8{8p=RA-7pq$)nlJ+GmDOJqR9^epi8sxc58cyMK zwIvS=aCugK@GER~2t@E9B-|k7teB`z$=g&?;`ZSIqXE_%MkelcWz_Rd*-^Fv3CcbD&~>SlE&8b-Vc7 zB{Vc7P%rEi;Xh}25*oddC;YcBD$);Zl*x1Dk*;wHp7UBRdZXOVEX+TMqlL9T{OfNI z%4IG*w%Vuc8@1oe$U0Xiq)8vpsp zF4hy#m zfnrFBIsbh&JcmyzLb6!8;E`d{sah~=&}mor$lN;KKh<9U&(x4A2IIyCrSs}hgMC-_ z!Uy$z=YQRR{oB17ubuFDG&dU~jsW`-exhMJB>eM~*?|xGK(csofYm3}Bd0I?P&4_z z5(}{~hDyTKaP&NeESiK6Au>XTwQW+{O@e2@_cPwZx#_&)+bt~@4G@z7@8>a;m zPOx~|I`R!6z5~xaC~`tP9znZeWW^!i5g9M6H=o4)y!ALZu^jD>eTn=xAXULPRH>h@ zNGl1ejhFj+a93hu_uJ-wY0^xD0ul;%i;mQVrO+ao8Rlc zT(zPASF_cAdy;dDXj4y9^XafKmQknG{!arc5m&A8aLjgU%a-p;Aew;tIYM=1rB40N z(aWx(^#-%)e38%;CVhcUlbij?^z`(^VsOTm{|h-WqN=4u@Z!kzEOXfV3#!BIBIdo* ze*2F(dfU@}=ELbK<|gZEIOmr44fvTlnws2q(DEY(Hw=26kDqn3$ijY?iDgkrr$lYJ zKVEKs&Go)EM(YL-#HH7$^|;xGLBip?nP3B$1@fXs$N8QQ3o-RPB2Y;Mh-9Z>dRT?g z>q@X3poP;eX>`F-rA1BGLcyW_@LK_|cQo-UsrO~y+}zw`Ca1iHl;`tN>9D>gdQdDw ztEdgAbJd(ZX4Kwhv;A((s)o4XY7kdH%GAEVjVLj}9LPQ;#(;J>2Txwzb-#wtk}FLT zdhleH<6*kh?ennZ_i^=aIF?k9M4N>I{=0RuRHbMnPPX&_xA)^E_|9I}5Cb{9IJQme@l3~q&5 zRfO0tupFmbJ%XP0j*i!9^A;Hbsg1;3_J8l!?Q$>AUmh+#4g^2Avlf~Ud zFFSI1If1i|s>*GhpzrHr5L_;ogOT?@I=9pQa0z*aaYUD5WyeML%jnl!KJY^S1S5gf z!j6L0vH{v!sK)uJ8@CKbaZohXZX$i*V`L^`ANX%%{-8Uszjfw_GeYk90q+ zLI`Me2V?U+e*JD53e0|>CxS$t25SK}>)1VI$z++TJ;RP?^@iHkUMK0l+WyZyij)ajVTnB zID$a~jIlwzzU>Tp3XdAD`pxxi&U8H`mvBnVFd{QPE9S>ZoE=elZzMVbeM%`Y!6&(F_;=X)z7ul@-I1=ZEn zh4)XMmwZ5!-C-cy)L~Sg(1=G=T7zOo2SgRdHT(VU_G>Vi1mU2GT|k(K@5w+ZWyU0V z`pG!n5d^sE`v0f|%%r-i1hQsls}S^l7kP^n2eAsCQGg?@*hX)!zf`eOnM&^8U0c~W z`PQ?5(jzw0oz*>rfHWZ;dHGne!tlsQWt6AJM6d=-=&Cz9I(m8p1q4XQv2bz4L*~HV zeKjyRJpAzR5Zb>D0)fm)LZga5!|!|!7l8-E9bdf%4%ARCjeMer%HVf_TuoZpadFHW z9a+xIaQ-0s8m+=5bM{=XXr%j9m};T2)$k*@B(LJv|?94>1FSRz{pT9c-l?6;f8XoB4hN z83;hBh}o2h^|1_Tj?IhOwKbLJO4&@h___ArROXFehac}38kTm&_shbXjPC5Tu=lzahx?7)!y&gV zRQj%$kIh`)hoPbR*4CRTE28+H%Zc)5Tk9qskDyhjM0I|ptH$7oV7K z1SqoerSiF`q5TKnTsvQ6rk{u3hi{lJK3;s~*3>VeBO@b+;Bz0MpJlaOH#0xhd)}w- z+D`!g^l!>NhtEDP7g+??m*Yo?0Do~jiKiFW?|Gn+_r&}&e=eRvRj*Y7!ZKVQ`UI5IO?F-!W?hYfR&3mk`?)HY%mK2!A*;q^hQkX|>pQ_) zIRh&Ge!CjlB%7Z~$VC)PRcs#L`PjWrKGl$_3b@|=@reKR zE8vtgy=JiNYvc3^l|bupRb<8YvP>w}+Qu=}xi9pZ2BeX4^z9v~Mwb?S4~ zq;0o6X=vt=d%;J{0|k^O&BO6*b&IunF6oE~IG%RICY`?@<)R)p)jrHl~yG6;vqrEuZ%VX?cqY$f8TXr}9u68|-rYiE^wNwoiA7f;KN5rB9rG3?C-5Rk=MDpn$f1 z6OjP2sX>*4NwA>$HC=iY9cRz!GIK4g%T&{*&HNot6G!Kttzd$Gqiv-s+iJ8PqQ0@o zcioa!)SH{`2L#_VE$b~deQc4A4x6z`UcB?7^EsZbTcuD=%6J zF^7}B`pp-Bmz4N5X;c0J|B!U#IW`pJ^L56j;bZkO2!Vtfr$e_`=?KS% z(Sw7{%l6vO`|J2mj_=T>tda=fhiHr1iv-_*4fm4+)JKq~=Zh0@hko(zM>}7$qpFQR zG`=Cw4tr@z1AUuacAd}rxaS>TEcT=1E`IgHZGBvzY~}K&wq2zp@m{o@*?e@sD-uNS z4{0mqY(CAgJV8%R$VmKnDB5hgd+@{E^1N7^w#c=+DPOeQEI2Wnmi0Y9;s6P7XOE--(GI{I;799>9E`t(!<^?_Bmdi7c^tO0N9_LwS(-z11$iq zt69km$>WO)!RzkRyGNPG=oUx)j4?9_boC?}(X4Kez}^7Odq%}4Gm6vIx8v7}HgM=W zaBTQSAS=(A^DT3Bz~aB>3Ni}Vw!)l_>uYy{g?n)6jBkIuIs0&bC)hq-wXVN!hXKc8 z++2^nZIcw;b6g9mBQ4=ft}olxEpQUk-8Iiwf_#hD6Y44SCFop!51g*=L|{*z8I_!c z0za7V%63O6b?)^F@iXF5G6G*#1;>%#*aTM;<* zzHGSL9H$B}`9036zIGlD`+Zz+qE&qiW|ZnolRUfqZ9kEO4JDiESCLkwZ9@EK&xc)_ z1+Pe*^Ie4xduu)#t=s3(^UcMwsT@ojtUh{bFdp44FZJ3*b2C}ku8Pg{pR}gbLH9i! zx0z^D5>mVS(~@mh8Q=f~gX(j+bn?-Ch4V{JjzGYKRsHIw+kNZIOW*q}uwVR>DTTA= zmiw+Y+PsX?_Z^Af5v4o9nbpL;PcQmBW|M~17}f6=!@gIS^-Ko>_jfBu_YV)8ORszD zTiV@^bY&eIOht^{{QNHhh=X4I*@F5Hbjy(_;cTB4EWZWseB8Wnqx}R0q94VGpdT1Y zIRQh3k6>kOd5T2+5NbJe5(lB>@Kpo;%Qwg3*H@UNG+^Td$E|05FR#&vnt@@okl5YT z39!E(ZMs2rd@Rl`ue%L{Q$Btf zy_mf(gWf~F-IQoU^LP~flN#bAx%Bj2|9D-H;W=ubwkVALvCmZc?%JQb;kO9`wD`W4 zQ1D;?rgLn--@ogjU!b6XnXRp!gEpT!i`Fx_H?R{d^)%-4VYGw)>8w~yzl~DPN64u3 zYIj(DAd+;R>mQ#hP_!^0V`X0W>C5B1k9*>GbGH#CUWo=5OTz2a{^Hi-46~+61ne(oRaZGdpP3s>hfLwl+lK*QC-cHb;7*N)JN)|tph4=Q~Rj z{=>Ka3Xbgvf7VvO`1bDZI)wgqvk)-=T7VxBiA z^2g`tbMG?nTJ<|W?g?H_Ars7Gm&X<2Cc?3X8V1wU@Q#;bR@-`6Tqd|oO%ta>b12@muqWB76bz#e;A_l27T zIF}@(=Z63$Cv==UP=TltZPN*vDApA(i0$GVgv=>a<{a7m%E1AHcnf)qP41coGdBmZsWZ>d;G}4 z&HD{Ujz6=9k)eX9CgKJG9*>AB> zfV7&o37BnMk*aOE&3|#*@LB(JQXNye6CfV*r0;d$)NaN3EhU;XNS6GVl!;U7!Uu1t zYj#d~!R}q@DW3vN&%)0%%~%OPn*1W&T4KLnA=PO6e^LakVGj%PaC-~cwK8c1ihP}x zN&5vDfLW`$z{XR~qX5te<_CfdYgk;j+s1-pKK4hc`?aHzw^8r!?vya1Yr9r%lk?8i2?Y-+FiVf#yAubc7B;a-vYC0CjP7KjaK7)wejKj69sAim zlJNRXL7sJj3yf4B3)Sak(noNZ2D?Y|$J3EIub!Y!IpJpvg|hB0)77r_IuAx8+MS&p zjTFio8~tiVje&3;r}mCgLh;NLb_arp2zeQ)Rte0>Acx1*(tDz3H!>~A=kr)cFpv4x z{pldd@mb?CNUPBFU=m*${`llX&_f2FjM^!8szi3pg-9?<&gS%by>Hw29nF?rw1V@%!X*4YaN$o@&4tUgBlDHYV_!Pd zHETTnCx>7_>yJ29e{iuVpgi`kD2R15A_-bJi#K8Tf3qd^KbwEk!QosQBn{TwYP)s1 z>0h~|6$Q2}4>S;x|vRP4Zdyh>|$>Z~he-$c{WX--il`GYY&we=p9D;XamKZQCZel&h$IhFMj_6K)@a^*iA05SV z7qc8GLl*dbDhy27P)p0nStjTOeld8UF|7X0e9fk<^02V*U?{p^XF*{U$~FE;KeCge zmdeGjUI_^a&~q#~Lt5c%Mr&(${-nS(l1&+0JG5$RDjFf)b)t{@{F3c4PNchirC#!w zwV#bWBuN#d5Rec6V`^SAr`TLCGv#44k7&4q`7^cw^O1;n1d&YN*a|)UE{{6Rc!;#7 zk+H4f_X!cmTk7dXzUps?o}pi1KN3|Y!cWoojm4NHgVR2|&_9NMo$gBRhWbpT>ZTPz zB#?TQG-Fmp)BrGGR$b?Q3Sv&4JEEQ_EYOBvDTA^4-E_1E_f--xb8#Vy+$AV_H6>qO z2yrZLPf7OoM!Y(;wcW^)+_RXy1fqc);oI9HgSHw&jyAKYl9d|=y(v&zV=bviN4wHo zWssl`2+OeSK(CRwHA>)-$utl(t|IYLXEbQYo{J$+m-lOK{!*AoMLUYTE2D#kj<~o= z7Cl>0(6L>dMef&FT8YC;7>=ef;o=`bTw;ZPkvi8rC)iw{(M>xid5z~-cT7T=Vq}c$ zLxi<0u=DQSTtT3D!q-B~7qW`xh4%hkHMLEQX-7?7*qbqyUY=nodQ=J15;tt<7E0-G zC=3&~ej2SLCD)c-j32U1o8y_!#jG@hD1Bbf7b>4?Y={Me2MZ*{)PF7=$ee(L#3T3= z8)#!9dQN7?YGvFEIiwN(lf9)>DxuPO5o@)}dTJ;lD&FuZOqlq--f`5Dy=s2A2onJ& z)4J;DzP^CR_@?a#)DJ>dHnul2rlyb|v88m-dDICM#vvm9$p+Lx1OAopTKmR!-*xg! zQil5si4rtMUd_lmSZe4ycrpJjLs;#oDcuSedqvbI*DR@Re``#TD+B<5h9VZ; z8x8!@+I7q|quTk(rH0{KA3}X15VL223Pem>f;5x06b!RE6Hwr~Tqr5e(G_SctgNk+ zj`9b{0kT!Xol0;=wJ{xAK27U}ggQYTOWpJmo^0VrLlbWfyGG8$LT;Q~0n*p6bo$?& z^JrPKteW0NEk(-_S+1(4YMy#CU&?``&5EMo50R~9NpiUvr$2vlZHo(0go-@+42%M+ zC_U~-L{qi3o4$)TWVr^ge)8YgH%EZ9TWnxYI3CmKOWJt;TKVTN4)464iSG6o1$hXN zIx(iJFqFN)Oy7WBhQgD%x>OGLiBZCpTh}1-*RZj3Y|t?+aj5Mraki$WuY3q->ueSh zZy*WK=gqB^Nl^fRvxu(*we;i9F4(UM8zk@cJjciDB7OZ82Z)z!>aV|CctvhZ6t8B09FCI5f>`NOl4nIaA!QBMxeW#Ci*m_k^P7*ymrOj`ozOB?_?D z9+hHJ3IGq95q8tm^I|ujEg7>>Evv&F=qBheyMz>0mwXfEFgCvR2yRY(z@o*Tz8KjT zvY>kiS~(^95{>R(5C(@9@|Iw|O+{Z6Em^dsx0|GqIC^63+|(A>{wjqO$pVB`-6yb` zeZAyk@HiE9weol(V1NQ9cFNCqidFlzus5)GG|M>1aDFrN1$7&bn zS&L+t&eF@AVoX&+amDr>LDk*Lk*io+C)DtqrTc0FbY}~0Dnn<<2n;be7J7~p?odm6 zj9kM8;gOi}6bzv)xn;!_*S_s`7#T!a*rF3OBZDvkZgt)t^M(^QRoGY3(c7Wie+vkNWwm z%|EnYAS4F6a$Rra)B34LaCMT-I^vL-zUDE)Y7*j`lbts8eQX&uT_EF;8Ua6@Cx;l<27Is#3Ruu|tbld^Q>Y<4^qS>NnZF`4!PJPbZ1iFC+R){b|IoCs zQo9zm`z)Hk;e*-8ST9F8f<(kgOSpnqRkXtSF`F@-&CFEO-IO{p)*qs+u(-RVdyrS7 zw;&MIp3pfI&%|X@zR_%PwPFSzsTV$3tBEpYJ^%sqDiv;m3d|{m^p1&?!yvuQ+VYeF<$$)1p z6hZCk8W4adH*T(OZP^<^??v^BO&(%4D{&s!pt5LMe83YqHnGl`-E?hcl(=vy#X0KY!SzRgF|6HjR_!U~DLeI`;K%lAM%J8QJa zz3U5_uyqp)8&zVgiN2MwabZW5G9na^si?!;9g2Ft$i1z`u2=P_b;tz6Ehz=|LZtX3hmeROxcCY1LpFmTy3=I_4=%Sig zI=n{25%Ya=i`nYNI-~H1`V6qAV72210n`Ge1&>6zE>w%nEW`R#(g{)1#VN;papodf zn<`&W)qcR3gRK`Bnw7beXu+@I7KhvGi;70ELS~P~3+Xefjccm=+^^2wY~sl(Wu~j? z!#h{Jx5gE_86H*ANdLAn{G&vh$TqE(1KuLqv$vir%c!lYgg+@ElRSzxhGl3GhKAAW z4M%_f*@?-T4A!fHkeqFJ*XjrvO5%*cHs`=Yc=`)SX*~%CIfU834?O*hb%RMg0EF!Y zvf?zR%b(Vc6qJ@wpw)oXn$isMVBt=5??|jiiB3OLx1?0lD=nRFsMXPED>6$s__M^A zBJ=}*VXsCX9x&_3>^^m5szm2{iboLc`0H8MY2RgUFG8q&2i=TqF{}`Lf{Ec0o?HP7 zU@wW+&eY7>A9-kfwW41of&@%An{6UKN4`6CLz%5MHs}rk=-2KL?Hs!dRV02`s1S!@ zr80_QhyZo-sq(yJ`WRc&LfYIf4&!VKk^G8TW7)~9PP_A!7gz2RVqeLYd9@B*Qs|K4 z!nY6%$N_sT2hXE*#CuaKC`Oxe&TzYSTWxZJ$18cm+ezlqb@9ca>*XQ# z`#Un89#)0ojg{zA3>F&4=nxwGe|nFiwSeA;!y9M!&H@2HA1XFHFWA@;s$-V{P3xtk zTd~mb49mqY6hHB3QitirBDu{Qc#D&=9FgSNSaNauMNjl#wGUxCC;`BKRZW{N-yxR) zRf^o7MN_EQ#>Vq$MhI2PY)O{IDZnR|Y1}D4YkyynKL^1msZ5k;Re1|TPP5P$9V&t% zG`?5pHZ$5})~3eF;*M37ms72|ICU+xD#?m)DO=>%UL~>5ucZ^&eTQONnC0jQuKF5T zNRHvKpDtO5 zFwQ(FY*B?wpm^dH0i>*C%izW#XsBsAZ4R2TBN;rSSOVfv`y*-??TSSTfb#KUCCgcX!@O*UVXG&3YiAZdg@UkCS<|X>6 zdo?XD)byUH0lqM?wLO!hAqGBW+24NduGBxGvo6~r?K3zn9PC~3wp67ZLJaMs)T59@ z;Xx-X6GNutp7O4n=;w4BzFvmgb2Y034{~5=L~7=xv0$KH4Ov$R%*^iG23a7w@%RYg zi<5krYEA3MLx*J6oK%S~6?gzWH~1kY<#S1=NxBeWVGpG>m5?pw;ksY0FXJ#);g4-n zE8+EOws-m*=9dI5PNGm=7xZegRqhu+uB0$eWG z{Ctc8|G2{&51noM#?4uUPKV9ET*{|(+G-0B?1AX0&m9zb$YrlTSwhFHL6naa14=(Z zNJfs}euqJx%c>QtyP0f7Q2IjFwKtpe7YcZu2FkCTUsdyHg788_!syIFG+bTIv@)-u zq>5yo{IhLe&@09@vMFWeJd&qr^=$~2m1VEE#>5E}(cWu0Hq( zvw-@D#gjXU^waAAgRm~#$nTF%+?we!VWu#`(@1>NC`$yQNLKLV=-L~yva>mGjf}&V zMsW%XS$0ciCmKr|opfGq<2Wq`2Fy_`F-u%%chY#Y=j6iE1~B4YFrU?i6-oRQAb|nG zi8Ahr$y3dcLVM4DPn^w|>M1l;kjOv;z43s(dF>_?%WSt{VCJx?3iD8)zJ};+BqDPs zS=0cjC`q~rQuM_A$c<-dTG&(E)jh1dnlNT;?}LBT57y=ZRyYLLD?&{@ph zBJ^m}-@k27h9vS?NZ?5w|I~F6G#z3I!V8+RQ)3-q4m2YRq9Tkafeta-A@DSg2ndyq z$DW8!eTvjzZp z&_7r%5pb9UPmZK|nP81Bf=p%w-$7qG1WivDhxzL>WdlkqOibvL=R@5P1m{L`s* zHp4vag~dL9D48sD#axezpepv7hv$~1V0fwY>$Pp^bhL&RduEs|j~{zelBLgD-G`f< zvV~7O4PXjKLv7?tm>l-nHU5>`Gvl%8affU)yA~5KvD*-&uVTLFk9XVs|qf9;oq%8z|TUfij4oswop0u=_isSh+WIaA} z!vJHVd2Edtdd)*_2mfb#X^1DCG;8EL77KOu)R5Tb3^Yb3w^JPsgnxZU@=v-T0R;l5&;^3SWZ{kl&>~;;Pq70{7N=iHSZo%LNg^1kX5aReq zk(lzTG`eyY)XWxn3`4wu;vfG&f!x%D;R(=8|No)GgzUOofP7q=nk=nWXz|l`qV~|4D>|zf8qk&}7cXE&cNjgk+adPip>+oMGe@ymBBqYZtSppW0 zoq3U*9Om!K4^N~22d5}5$Mv-h$@)(@&q~v+qc=*{ylxu7r)#hu345}^bgNbCON97s zRUpg&dv#@t*_Fi%f7a!5OXkpKto^p1iB;sJ%SkQxw47Qn(CF7*1SiGp+E+Zvwe3Zy zm8u*!3L3&;##}M|gkzogNgL5>P-wc}tSa(b^Nmkgpxmc;NLgh=-3|eP&6rY)b?Yd z?9M*)N*b4Ft(5(|!g>D3FS$KFFFbFWx%NZ@fVWoNBtb{Uk%9S{{R+P!kIg@-%wM9& zi6+9*PP&X86$Y8ALdvUN%~%-fF*Kq?wu3RL3<+2bc~sOn^?c%Hc>b)(oGU{MyJSCT z5bdKJd_+u^=U8LMzar`AMsrq<+pQ(_)94C>f4YT~h6oxQ>U^b=5)U0Xs36v3v@)(s zHzSw+O~>Gv)~wYbrOwl7IJ39!#9q^qaiW$|jjU>GH$p;F@kA(nj8?L{Ag+$Lj31|= zr((MLH1IR>4-Ih)A6)%6b$U~-al}X_f51Tt6#_tYzE0Vgpl6&pPeO*Fi$Vss+ee{_ z&!`LQ$HtydPJJV7vJn94>?X_T@E8Oca(RzTtos0+-YDJx~45w1nR9><$ ztbdzX=;@jg3npy5a#Qmc=+d2^6*U;BT{%h=wJzU$a&%zE3kX+?z>3=?Gll+VPX#;f z+r!=p6Iz50RET2rN9#r)y=3K}*J`dl=bQK{Bh|aBcde|E@4>%f-6zC}0KG{k4(R;| z6C;?Fr+Vv$X704qY*95sG_vjcg&ZA*rIJI2qpCYe=1wM5@@)AWUKULX9Tj~e5ci86 zlw$@B_UxHjO+KYqCDbYNtgB7yD@!RQd*l2oaaQwgw&r8gNVeAHTFV;~+@gl=a>|2S z8jW+agC(mn!abaa53PfYDS=b>ti!g-$qs+mS%#t(6nwX(%4uH=(z`^cr|?H1By1Sf zzy35Ke6w-&Dr7TLu9_@Z#Kl^t56~1cYU3j+al4rdP9?r86FEC zYES`FmW;yfNkr&K_H|^Ar&3aUQCdk|2-XtO3q~nZ1khPoa%ih6`W-!`X=4Cp=WL4F z={_xdt9@bfmQBvJB9OXr-SJ|`e?GzXN+}GHwQy?%G!9xCS%g3oVM7a7n4ph6eZ@;aUz#P-w0 zZppQ|^g(Qt!SCwI@nAr0e~;j`1Ywp;s`9$3X!UN9)8fU&*)+kc4k}kF;yN!iy6YB$KbI8AkXh=iMt4R(LFW?D%K{Iu z5b-vuArCtc4U^6ObLH?5%NVDe#%bx;BvrA$jaDh1HLTeL(L(tj(pw}@&$oMjp~eG3 zzmvmz5!20+wjTTnP2sLW@AW+YwCTmtMD{ht`>4G`FVN=M~aclPYonQM|w|K|2h?pWjEMg zrrZ=utJwxs)EqPDw_KL((0q~|ZJk~sn!30EU^nC7Jfp3y%+|VNTgwJrUph+S%myEq zgVuh`_s265=Vwjf0(OziYy?qE-M0lgiSdRy>AJspJ<35VMlfo83=s-C9b)E_POR;x zjukz8H8E3m)SUnB8TpqoBb|_=i$z6)Wp0`S;$ffS7FPGMv6bbTSA~|n_;u?=32m5e zT8N=J#>1Flg@CByfaxduIs=t?ox$YZGgTdO zDJjwJdZ8m@jNkYq?J0^VaOKz)tDRUy%JwGaPHd`mC4dFCD9p(0D>b-~j&dC=fvp^= zH`^fOT59HKnPIrHX!evAS1cQ+(LxGHpb$IxZLa_e4+oV{guJ{mMy`pm8Em!LXC9A0 zu0P7(R*is55IdJF*kcR>XNVj&P0R7Jp6#MLVvWJK=*m>!yp}hvxBEu}0p^TOo2AEg zeM-0S)5b^3P^tdu;jODM-f6I2p1V^p<@`^K-m@DR?8p?T-ggcR^TP1bP&N-8QO*|TLvn-=F`ITP06?^UK=JcM9Qkie=U6rcSP8=$PoKf?mzul z2oB?lutcfiX9qNA0ko()Pl(w4BM19}E zN51y+JBXu{vzAL4NrVmiONJsAN8yTT)1d|;Htq_RD1tNy2aUrl^QkX0`2V+u#hxaJ z5C+U>C>_Rd=-qH*5B|&b=MEvVsv9(5VXp7M78zNevsl0V;S@t}4A3vpPrJb4H&m4y z6jjI`CX+HXxLxDp8@dq!04t8&X3m$f!f|WEn!;Lvq>j1`nJv6yfL_% z!!NkCfF#!D>^H$N<4pnYKx7+!t7peupNB(XI7Qfq7&AKPD%KT<{f&2r917I3mMdw+ zV*w$B7&0bI!ay&~?_otA68*N$ZaT`+@|B4>V>LtJXBU(vd>Qrm>tZYIPr23NB< zj)MdE{$i@O#aRL)hNaiaBn2;*f4?(uZ1ypEGi-3|lXn-x!VK}M)W!?t)O~z1|CkrX zZPl^z*T`n-)|JspPqVW91B@%FBMSa9144MP`XN}{cv)nL)5Tgy^pMVr$vm&fNcoI4 zzYPqyV*YU*9>YWWFMz0^IAvO|T$R;Kl2zp)0E04@z`~N*Bi9Zwi!)@%5xvy;J;x?k zKzN1}a^N#ORA7kLi$N4iP+-F0&5O5QO=(rt;+|z9;9tjnvDwj;|2Y#b0>eFL(XvU4 zVYrrx7(1miApqiMjW}dqfti@g4GPy8gK&fy`7UVYQmVY1fkg&>2>N#+MRuc^k>+if8uZdVa86~x;==2j z5Sd|uWl7=HM*AM2IUJQ#21L39-^($t($d|y*w>a7O>s)JTX#(Ke1!Y9^`>7Yz7%GdSPD^@Um~9)lJ0eneGf z^U^w!v=4mnZmQMTCOJA7+g)7`qn(YHL~764#C(=(T@~%5@`{Q^!PfJ@Z(6e{ zqlS_qP9B{ll?oDa@_vanK0QUf3E|95n&RCgZFe45l&SoHeg!%-Hl=FjbxSKsEbSKO z@_T+Km zmDcL=6=scRM32Z6tkKoMWKBLu;I(_6)Kn&6oW>BVVSr}{@6R^6T3kQ~2Q8zx%Wrp| z{eiQwERgjKu?m(bYWr*NL0W74n&oMY-pOGB@?eFs$FHg}7bcr>ri!VJX1Q3vEopBt zkdkha%wEIV#(BZ(ds6;Nc_{|ujOkjvrK7HFG3DAdBqn$tBPK9!e3El63_?hGMH(GY zj^vV{HU}k>8|L9v8>}NOnWt{rt51%7kF`*CsJ*%)3 zKLjGqO)y7&Wnr)=S^X!{Ec$?ExusLeK96*2HS#x34RHd?I0N0({px$^PfJK)EY;Pu z;q-w}9ag7$R23ZBd1rHXeJ> z?jiU|rXhvEv%0Rw)5Zt4Xt%ogl6{zE&4sXGV_f%+axr~<=?LQ2uEQGtRNu)Ajm2Q| zHymH){?Q^e_LTsSdsi=CUI4HeDQm34d)<@)n{4l(Mk3}5sh>gFy3V>a8xkh+_`t7C zn@?uw?o_)Dl?)E9!B36XV=ksSB&S15xg{!0?2c?NU z1?HzpLOKmEPeU)}5=?l}2BPsBt&}|vW3A@&o0i6~UY3;uYs*yR=Bg&OFJGF$mAyHE z8&8F9L0#wAPSyI~bECO2&T6(B`cg21t%_w}utclh--%9!nXUWlIG*4&o;GGf$Ob2F zNc+AifUHy+WDaZCGp~4oJ=U^pdcs|Fs`nz)J=|EgYWj&Qhy`4lpP-S0H;Gce1v_RC zAVRy!L`z@F)_hQ>=$N49*44Mo9gb@&fm~AF8Ir2K4`Q&hKE+`RMY;Y~XNlR&3nSL+ zDFXVh15%2qgIX1_$Nf$G#7prY)zIBD2s)&$!NHQgp6X!FW^H-*$J$`JRus#5?RvIu z7WbA~R#l;R@c+@ubwJ{bYl!M%3zcr$Vl*?_ug-J-7j~oyFcu8);i~`wLk5B_H*|0@B_S9kg7jOBT_g0h)c?Bt%U8VxwJu8@&mV}OX z$d-$gSG5gYkza*1Su)@J#+>3#kSm%?&^wrE+wxd&=?v=I*H4Pve?o3M`uszhkogL$ z7IbvM;F{qIO$=pnPVWM=zOik{j}55EWU>~!FPy>~VQ}+o(r!wW!bsARoV(_xZYktR z3}=kdqYjIsOUSjPRQhF34s%kP2Rp6!QLgWiKWdZ5`j;#bWnbTk;@TCdR!O1iVqp(> zVV48jdfmI?)XiD)q4A6h^)HI)$HZ5urFuJ_SD8v!e*YhucmIVjKGcvGC;vRKQO7uH znf&^_>S&p%!FdZL<{TAg@7VN0C`odPnUyKIl>#txqRE-lPZ6a~zSIFWPlp%*JzAQA z0~rHLZu7ZgyNwSI6th1iviSi(ZBw_e`5d-0=U*(+wmLMWuAZ>R0B@(>*L{;a{qJ<$ ze@kTiAJ9l1VY~xo?+{IpW!Mtw`zVpHGEqVXAt5BAp>gw^uQ-`x*5^XfS9l_~6}gEA zh;}LK5HskVIB4cV19BW(uqKx;D?Z3!J8HH$XSBMSSY@`se*8(kCB^!gA}!d-sxfYT z>QQi=!Ps7t{7!Yk6+y{Q+~*g^WZJY>wJq?IUwlUQW2uR5mRmK$W1|K3FD#O^?v&b; zU*2-QvW`w89yhbu6#JDdZ|pCNvZ>68=8oGx9hF}qUlII*B6EqPVo0MgKnLqoRwisj2)cY*P0U6|N zaO(BTJG6=6bxdZB=%} zzH@19CXogG5o{kU5cdYTxm+*LAUyic^4S7$hfGPaMZye7s5f-7vSASj)>u(Li+@Zc z1yqDKuo%-=M*v7;v!rjK&5du(K3)guUp;Yq5zh|_whQi zTArhi>bM7?glOID2|J^Q047g+gXHmY=G?=Sy=vToCZc-&3jI z%vyJ%v30dBb%;SqvCoHLGW59Jdv?+Z3V|wRL=GJ1N~^O2Gym)Ni@`k~q|}s^FWAnH zc>cWMuPnS^nRuk=*qQO}==IZ5 z2fOM&B5e#98!Zc6->r4wB87hJR<5d$esvp&euD7yPn8nl;tc zQ>W6t{t|pei6n~+pYlp+-#J10VM;OFqJppSkW6Bqdz`nCK2qNY#A|oqS3bDy$pT5g z3E3O?qKH9fGMC|cg9$)s;l zwuUXFF=3lm5QCX@aYa|9G7)`aXnf(xwxvhju2_E?L_4Iq|Ma&JL^Pp1dCOFr{GcqVfP;}1do|8p+#n?DqqN0;;n(du+{2FKpMkyp~7vD6AnO;Vs5r?=- z!1~`vB?+5$HIc9oer3W~Llo(!kp(6w+~EkA^Yz=aRgy4YDl`bmP=Pz{;#KCTpOxHh zInaB2>mI$B|D(Gtw6qS?c$?zrEMr?;0rT)5s|z-F0);i(aKq)-HN4L-#968gp%HM2 z2lwZ9e4-+u8lG_e2+;-*xczViRyj}TkL{%CF1-81$p7guZuC6UJevnm5?1rwI7mfI zxYG;Z;gpGG+8h)w^6=teb8E*)?F6QbG~e_MZu|gV zhm9?qD=!U=A&8X}`2vRM9sf=%H~TARTz!5;i*DC*%le?#j_uWszyL@-)2fc}_~`TM z30ZRMK{=8tdfIz4c&Hyv$<8WFEeuFpF;TOjnxAvIoh^)oQJiCNpm@yIgzDm z^1(jxeY~HkOWsac9r_mYKoK{lJCBj~kUn~D6j`@WFEd4jtdJRiFReL*MCKPro|NN> z`syj2#%?saXt;{wLfz;cI~dcb;UsF}CV)6=9DIlSFzrd_g`NnC`=ND}0#CEzRyCoZ zN=Z2*<3X2&7(ML-0rc!5V|Kd)4I_J9FCzWZ?fqxeQ&rh$DSr5?w6YO3X!D&0{Cb!v z9-;$Lygq$XAtxnq8zWSMG2&z4(JL!88QnKqGgb;D6EU1C45slNk%ix);?FJ4W3f~oH$Ex?zGEs@r>P)edR8im@}Y z3OPpeDrO|C@qiYjq`ZYLtr(mC^UE)Oyt--R!^Zr;3%98o?bZn;5(&m8w&eUb|8w&= z7{}nPCNtOx5?-C72B6Jl6vV7h+C#9dT6+9AnNiH-A6)J#o1Ur}-81cRcRI&yB95YG zJL{8asJmTPM|3XhTDpmu<_Aw|APsc(?(0N zCc~f!H-&FlF&L$zL7dzfsxfTzsm#qP?F~gopU_gb7wXm^tUVgjYB0SE#?en@DS^gW zSpa~YB_~T8KEM?GE#2!bs#&nW{uVJ5cL)HWtdu*955WR6EHNDoyzF$^# z-9MCNz!b|(uiLA;?`UZ&?71=J5 zSr25%=p7E${W4yVGn9`za0&_Lr+t=<=SY;Lg&0Ocohu{m*h&nb9O?0zM3w!)*YjH| zmab7UlET31B~=`wm`c`klJO8_G#d*;{8}iri>I>~d>a~DUL0!kbrnO%lO1bM^(0y? zeVhxPjZY}uV{fOYOMolgc&sdqOr-!U?8Bu_R+}t2kFJF-aYc9B@Ax@K1)v-$fX*rl zc$dt&Dxg(YE#cFXm!iLoR8jpls@_Qu;eJr}s4<$gK&nA@dVqhq#KtEC?Lc|R5qFas zut@UmO2{jifO4@BQ|tBy>F$#Te7#-2Ta4@$1`An0TDYU;!cG!XuBR-1iYA^nrK^+k zDbyP_pkSYAO)FCmO45n+L(YW6ZuZR|`1*SM&QLT8?{XY-%0mubV65h`c^UDM#&wxD z?pOAQm218j_dra%C3Ot>xaxViUTXcW-D)`}x>z6s-3Ln!!{RA^k=zZ^jxZJ^F7D^Coh`qkGue;L>9K2VwyBfUi~5~* zq(dkzKe@-DFMd;;1hIH=yYOc~eDi1|wc{fAV>OGJR7M3a&|^?Xf&h3?U5(q^1a9r6 zSl4*X6x}<8bmZdjGEfg`Rm55rpf4+fw);RmdSAibSK~Ss|1wJOY&MGX97{2(QecCP z9}-CXIq_nCrVVNOA#U~8L+SN3#llpW8sW2P*}O;ax`wMQ-|9Zy`Mkd)N}pAOLrM`E zF|MY8^OM^M4(v-zSG?Ze4=HEjP#g_76EJwi<3jFGf5yI+A-^}-_j+60!G-tBYOQ90BH1>V}=}`g<$|gLj{Jyy}-5L2}!;S9rapJ~t$uF(!%(0ve!h zY&Mg!)D?XZv|Tur3DGJZKI^hY+qC<8b_c8_07Ux`py88rXD(gQtjRk0b=bkL0e`;< zc-@Zp?z7JLuA=*ei&?pZN4OiR_^Ix~K#o7{+xVSAgO|GvQ5BcFUv zRY@uIWEW?MW7`7rsiyQpM$X7GKMSpzF)X*P_Ah?xgr97H@UvdOrYBJ-6nQV|&(3X) zp}Ow#)8ieo