改用数据库存储,优化代码,注意看重要通知!

This commit is contained in:
CMHopeSunshine 2022-04-11 21:18:06 +08:00
parent 970573e44a
commit d9d04528c3
14 changed files with 655 additions and 576 deletions

View File

@ -14,11 +14,11 @@
## 简介 ## 简介
通过米游社接口查询uid的游戏信息并附带各种娱乐功能。 通过米游社接口查询uid的游戏信息并附带各种娱乐功能。
## 功能示例 ## 功能示例💖
<img src="https://raw.githubusercontent.com/CMHopeSunshine/LittlePaimon/master/readme/ys.jpg" alt="ys"> <img src="https://raw.githubusercontent.com/CMHopeSunshine/LittlePaimon/master/readme/ys.jpg" alt="ys">
@ -61,98 +61,36 @@
<summary>抽卡记录</summary> <summary>抽卡记录</summary>
<img src="https://raw.githubusercontent.com/CMHopeSunshine/LittlePaimon/master/readme/gachalog.jpg" alt="gachalog"> <img src="https://raw.githubusercontent.com/CMHopeSunshine/LittlePaimon/master/readme/gachalog.jpg" alt="gachalog">
</details> </details>
## 功能列表
## 指令列表 详见[WIKI](https://github.com/CMHopeSunshine/LittlePaimon/wiki/%E5%8A%9F%E8%83%BD%E5%88%97%E8%A1%A8),向派蒙发送`#帮助派蒙`可以查看指令列表
### 查询功能 ## 重要通知⚠️
以下指令会记录上一次查询的uid因此只需第一次查询时写上uid即可。 4.11对代码进行了一次较大幅度的重构cookie数据存储方式改用了`sqlite`数据库,原`json`数据会在首次启动时自动导入数据库;如果您对本项目代码有修改,请确保`git pull`时能解决冲突目前测试未有BUG如有请发起issue且注意备份用户数据!
| 指令 | 介绍 | 备注 | ## 新功能更新😙
| ----------------- | --------------------------------------- | :----------------------------------------------------------- |
| ys uid | 查询uid的个人信息卡片 | |
| ysa uid | 查询uid拥有的角色和武器 | 没绑cookie则只显示8个 |
| ysc uid 角色名 | 查询uid指定角色的信息 | 没绑cookie则只能查公开的8个且不显示天赋支持角色别名 |
| ysb cookie | 绑定私人cookie到qq号 | 建议使用私聊绑定 |
| 添加公共ck cookie | 添加cookie到公共cookie池 | 需要添加至少一个公共cookie才能使用查询功能每个cookie每日查询上限30次 |
| sy uid (层数) | 查询uid的深渊信息 | 绑定私人cookie后才能查看具体层数信息 |
| ssbq uid | 查询uid的实时便签包括树脂、派遣情况等 | uid必须绑定了对应私人cookie才能使用 |
| myzj uid (月份) | 查询uid的该月札记 | uid必须绑定了对应私人cookie才能使用不写月份时默认为本月只能看最近3个月 |
### 抽卡记录导出和分析
| 指令 | 介绍 | 备注 |
| --------------------- | -------------------------------- | -------------------------------------- |
| 查看抽卡记录 uid 池子 | 查看uid已有的抽卡记录的分析图片 | 池子有all\|角色\|武器\|常驻默认为all |
| 获取抽卡记录 uid 链接 | 从api获取抽卡记录时间较长 | |
| 导出抽卡记录 uid 格式 | 导出抽卡记录的文件,上传到群文件 | 格式有xlsx和json;只能在群里导出 |
抽卡记录链接的获取方式和其他工具是一样的,这里不多介绍了;
本派蒙导出的xlsx和json符合UIGF标准可用于其他UIGF标准的抽卡记录分析工具。
### 模拟抽卡功能
| 指令 | 介绍 | 备注 |
| -------------------------- | ---------------------------------- | ------------------------------------------------------------ |
| 抽n十连xx | 模拟抽n个xx池子的十连 | n必须为阿拉伯数字最多同时5次xx池子有角色1\|角色2\|武器\|常驻\|彩蛋可以DIY池子 |
| 选择定轨 武器名称 | 武器定轨 | 武器名必须是全称 |
| 查看定轨 | 查看当前定轨的武器和能量值 | |
| 删除定轨 | 删除定轨 | |
| 查看模拟抽卡记录 | 查看模拟抽卡的出货率、保底数等信息 | |
| 查看模拟抽卡记录 角色/武器 | 查看模拟抽卡抽到的角色/武器列表 | |
| 删除模拟抽卡记录 | 清空自己的模拟抽卡记录 | |
### 原神WIKI
| 指令 | 介绍 | 备注 |
| ---------- | ----------------------------------- | -------- |
| xx角色攻略 | 查看西风驿站出品的角色攻略一图流 | 支持别名 |
| xx角色材料 | 查看我出品的角色材料一图流 | 支持别名 |
| xx参考面板 | 查看bluemushoom出品的角色参考面板图 | 支持别名 |
| xx收益曲线 | 查看bluemushoom出品的角色收益曲线图 | 支持别名 |
### 米游币帮兑功能
私聊机器人回复```米游币兑换```,跟着派蒙的提示步骤来使用。
### 派蒙语音功能
> 发送语音功能需要额外安装FFmpeg请自行安装
群聊关键词可能会触发派蒙语音哦,尝试发送`诶嘿、大佬、羡慕`等词吧!
### 头像表情包制作
| 指令 | 介绍 | 备注 | 例子 |
| ------------------------------------------------------------ | --------------------------- | :-------- | -------------- |
| #亲亲/贴贴/拍拍/给爷爬/吃掉/扔掉/撕掉/精神支柱/要我一直 @人/qq号/图片 | 好玩的头像图片gif表情包生成 | 要以#开头 | #精神支柱@群主 |
## 新功能更新
- 3.20 新增Windows一键部署脚本 - 3.20 新增Windows一键部署脚本
- 3.22 新增蓝佬授权提供的收益曲线和参考面板攻略图 - 3.22 新增蓝佬授权提供的收益曲线和参考面板攻略图
- 3.24 新增抽卡记录导出和分析功能,原模拟抽卡的指令更改 - 3.24 新增抽卡记录导出和分析功能,原模拟抽卡的指令更改
- 3.30 个人信息卡片新增层岩巨渊和神里绫人信息 - 3.30 个人信息卡片新增层岩巨渊和神里绫人信息
- 3.31 实时便签加入参量质变仪信息 - 3.31 实时便签加入参量质变仪信息
- 4.11 改用数据库进行数据存储,优化代码
## 已知问题\待优化 ## ToDo🕛
- [ ] 公共cookie达到每日30次上限时不会更换
- [ ] 公共cookie没有复用
- [ ] 指令参数判别不够清晰
## ToDo
- [ ] 实时便签树脂提醒 - [ ] 实时便签树脂提醒
- [x] 抽卡记录导出和分析 - [x] 抽卡记录导出和分析
- [ ] ocr圣遗物评分和角色面板记录 - [ ] ocr圣遗物评分和角色面板记录
- [ ] 角色、武器和圣遗物wiki进度30% - [ ] 角色、武器和圣遗物wiki
- [ ] 派蒙AI闲聊 - [ ] 派蒙AI闲聊
- [ ] 米游社自动签到进度70% - [ ] 米游社自动签到
- [ ] 今日可刷材料 - [ ] 今日可刷材料
- [ ] 角色练度统计 - [ ] 角色练度统计
- [ ] 派蒙戳一戳集卡
## 部署方法 ## 部署方法🖥️
> 本项目和HoshinoBot的部署方式一样因此Linux可以参考 > 本项目和HoshinoBot的部署方式一样因此Linux可以参考
> >
@ -160,6 +98,8 @@
### 一键安装脚本 ### 一键安装脚本
一键脚本会因计算机环境不一样而可能产生各种各样的问题出现问题的话请尝试手动部署部署方法参考HoshinoBot
#### Windows #### Windows
在你想安装的位置打开`powershell`,输入执行: 在你想安装的位置打开`powershell`,输入执行:
@ -179,13 +119,13 @@ javascript:(function(){prompt(document.domain,document.cookie)})();
#### Linux #### Linux
代补充... 待补充...懒
## 额外说明 ## 额外说明🗝️
本项目也可作为HoshinoBot的插件来使用移植`hoshino/modules`内模块即可不过对HoshinoBot有所魔改报错时查看修改一下代码即可 本项目也可作为HoshinoBot的插件来使用移植`hoshino\modules`内模块即可,另外还需在`hoshino\util\__init__.py`中添加`PriFreqLimiter`方法用于模拟抽卡和派蒙聊天的冷却限制
## 感谢 ## 感谢❤️
代码水平很烂站在巨人的肩膀上努力学习ing...... 代码水平很烂站在巨人的肩膀上努力学习ing......

View File

@ -1,56 +1,40 @@
import json,os,re import json,os,re
from hoshino import R,MessageSegment,logger, Service from hoshino import R,MessageSegment,logger, Service
from hoshino.typing import CQEvent, Message from hoshino.typing import CQEvent, Message
from ..util import get_uid_by_qq, get_cookie, update_last_query_to_qq from ..util import get_uid_in_msg
from ..get_data import get_abyss_data from ..get_data import get_abyss_data
from .get_img import draw_abyss_card from .get_img import draw_abyss_card
sv = Service('原神深渊查询') help_msg='''
[sy/深渊查询/深境螺旋查询 (uid) (层数)]查询深渊战绩信息
*绑定私人cookie之后才能查看层数具体阵容哦
'''
sv = Service('派蒙深渊查询', bundle='派蒙', help_=help_msg)
@sv.on_prefix(('sy','深渊查询','深境螺旋查询')) @sv.on_prefix(('sy','深渊查询','深境螺旋查询'))
async def main(bot,ev): async def main(bot,ev):
msg = ev.message.extract_plain_text().strip().split(' ') uid, msg, user_id, use_cache = await get_uid_in_msg(ev)
uid = ''
if len(msg[0]) == 9 and msg[0].isdigit():
uid = msg[0]
del msg[0]
if not msg:
abyss_floor = []
else:
abyss_floor = msg
abyss_floor_true = []
for floor in abyss_floor:
if floor.isdigit() and (int(floor) <= 12 and int(floor) >= 9):
abyss_floor_true.append(int(floor))
abyss_floor_true.sort()
if len(abyss_floor_true)>2:
abyss_floor_true = [abyss_floor_true[0],abyss_floor_true[1]]
qq = str(ev.user_id)
# nickname = ev['sender']['nickname']
if ev.message_type == 'guild':
rm = str(ev.message)
else:
rm = str(ev.raw_message)
match = re.search(r"\[CQ:at,qq=(.*)\]", rm)
if match:
uid = ''
qq = str(match.group(1))
if not uid: if not uid:
uid = get_uid_by_qq(qq) await bot.send(ev,'请把正确的uid给派蒙哦,例如sy100123456!',at_sender=True)
if not uid: return
await bot.send(ev,'请把uid给派蒙哦比如sy100000001',at_sender=True) if not msg:
return floor = []
cookie = await get_cookie(qq, uid)
update_last_query_to_qq(qq, uid)
if not cookie:
await bot.send(ev,'当前cookie池中没有可用的cookie请联系开发者',at_sender=True)
else: else:
try: floor = msg.split(' ')
data = await get_abyss_data(uid, cookie) true_floor = []
abyss_card = await draw_abyss_card(data, uid, abyss_floor_true) for f in floor:
await bot.send(ev,abyss_card,at_sender=True) if f.isdigit() and (9 <= int(f) <=12) and len(true_floor) < 2:
except Exception as e: true_floor.append(int(f))
await bot.send(ev, f'派蒙出现了问题:{e}',at_sender=True) true_floor.sort()
# try:
data = await get_abyss_data(user_id, uid, use_cache=use_cache)
if isinstance(data, str):
await bot.send(ev, data, at_sender=True)
else:
abyss_card = await draw_abyss_card(data, uid, true_floor)
await bot.send(ev, abyss_card, at_sender=True)
# except Exception as e:
# await bot.send(ev, f'派蒙出现了问题:{e}',at_sender=True)

View File

@ -2,43 +2,25 @@ import json,os,re
from hoshino import R,MessageSegment,logger, Service from hoshino import R,MessageSegment,logger, Service
from hoshino.typing import CQEvent, Message from hoshino.typing import CQEvent, Message
from hoshino.util import filt_message from hoshino.util import filt_message
from ..util import get_uid_by_qq, get_cookie, check_uid_by_qq, update_last_query_to_qq from ..util import get_uid_in_msg
from ..get_data import get_daily_note_data from ..get_data import get_daily_note_data
from .get_img import draw_daily_note_card from .get_img import draw_daily_note_card
sv = Service('原神实时便签') help_msg='''
[ssbq/实时便签 (uid)]查询当前树脂洞天宝钱派遣状况等
*绑定私人cookie之后才能使用
'''
sv = Service('派蒙实时便签', bundle='派蒙', help_=help_msg)
@sv.on_prefix(('ssbq','实时便笺','实时便签')) @sv.on_prefix(('ssbq','实时便笺','实时便签'))
async def main(bot,ev): async def main(bot,ev):
uid = ev.message.extract_plain_text().strip() uid, msg, user_id, use_cache = await get_uid_in_msg(ev)
qq = str(ev.user_id) # try:
if ev.message_type == 'guild': data = await get_daily_note_data(uid)
rm = str(ev.message) if isinstance(data, str):
await bot.send(ev, data, at_sender=True)
else: else:
rm = str(ev.raw_message) daily_note_card = await draw_daily_note_card(data, uid)
match = re.search(r"\[CQ:at,qq=(.*)\]", rm) await bot.send(ev, daily_note_card, at_sender=True)
if match: # except Exception as e:
uid = '' # await bot.send(ev, f'派蒙出现了问题:{e}',at_sender=True)
qq = str(match.group(1))
if uid and not check_uid_by_qq(qq, uid):
await bot.send(ev,'派蒙没有这个uid的绑定信息哦',at_sender=True)
return
if not uid:
uid = get_uid_by_qq(qq)
if not uid:
await bot.send(ev,'你还没把信息绑定给派蒙哦',at_sender=True)
return
if len(uid) != 9 or not uid.isdigit():
await bot.send(ev,f'uid {filt_message(uid)} 不合规,是不是打错了呀',at_sender=True)
return
cookie = await get_cookie(qq, uid, only_private = True, only_match_uid = True)
update_last_query_to_qq(qq, uid)
if not cookie:
await bot.send(ev,'你没有绑定cookie或者cookie失效了噢',at_sender=True)
else:
try:
data = await get_daily_note_data(uid, cookie)
daily_note_card = await draw_daily_note_card(data, uid)
await bot.send(ev, daily_note_card, at_sender=True)
except Exception as e:
await bot.send(ev, f'派蒙出现了问题:{e}',at_sender=True)

View File

@ -0,0 +1,244 @@
import sqlite3
import json
import os
import re
from hoshino import logger
from datetime import datetime
db_path = os.path.join(os.path.dirname(__file__), 'user_data', 'user_data.db')
# 重载公共cookie
def reload_public_cookie(is_drop=True):
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
if is_drop:
cursor.execute('DROP TABLE IF EXISTS public_cookies;')
cursor.execute('''CREATE TABLE IF NOT EXISTS public_cookies
(
no int PRIMARY KEY
cookie TEXT,
status TEXT,
);''')
try:
with open(os.path.join(os.path.dirname(__file__), 'user_data', 'user_cookies.json'), 'r', encoding='utf-8') as f:
data = json.load(f)
for d in data['通用']:
cursor.execute('INSERT IGNORE INTO public_cookies VALUES (?, ?, "OK");', (d['no'], d['cookie']))
conn.commit()
conn.close()
logger.info('---公共cookie池载入成功!---')
return f'公共cookie池载入成功,共载入{len(data)}条cookie'
except Exception as e:
logger.error(f'---公共cookie池载入失败错误{e}---')
return f'公共cookie池载入失败错误{e}'
# 初始化数据库将原json数据导入数据库
def init_db():
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute('SELECT NAME FROM sqlite_master WHERE TYPE="table" and NAME="private_cookies"')
if not cursor.fetchone():
cursor.execute('''CREATE TABLE private_cookies
(
user_id TEXT NOT NULL,
uid TEXT NOT NULL,
mys_id TEXT,
cookie TEXT,
stoken TEXT,
PRIMARY KEY (user_id, uid)
);''')
cursor.execute('DROP TABLE IF EXISTS last_query;')
cursor.execute('''CREATE TABLE last_query
(
user_id TEXT PRIMARY KEY NOT NULL,
uid TEXT,
mys_id TEXT,
last_time datetime
);''')
try:
with open(os.path.join(os.path.dirname(__file__), 'user_data', 'user_cookies.json'), 'r', encoding='utf-8') as f:
data = json.load(f)
for d in data['私人'].items():
for c in d[1]['cookies']:
match = re.search(r'account_id=(\d{6,12})', c['cookie'])
mys_id = match.group(1) if match else ''
cursor.execute('INSERT INTO private_cookies (user_id, uid, mys_id, cookie) VALUES (?, ?, ?, ?);', (d[0], c['uid'], mys_id, c['cookie']))
cursor.execute('INSERT INTO last_query (user_id, uid, last_time) VALUES (?, ?, ?);', (d[0], d[1]['last_query'], datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
cursor.execute('''CREATE TABLE IF NOT EXISTS public_cookies (
no int IDENTITY(1,1) PRIMARY KEY,
cookie TEXT,
status TEXT);''')
for d in data['通用']:
if d['cookie']:
try:
cursor.execute('INSERT INTO public_cookies VALUES (?, ?, "OK");', (d['no'], d['cookie']))
except:
pass
logger.info('---派蒙初始化数据库成功已导入原json数据---')
except:
logger.error('---派蒙初始化数据库失败请检查user_cookies.json文件是否存在---')
conn.commit()
conn.close()
# 获取公共cookie
async def get_public_cookie():
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS public_cookies(
no int IDENTITY(1,1) PRIMARY KEY,
cookie TEXT,
status TEXT);''')
cursor.execute('SELECT no, cookie FROM public_cookies WHERE status="OK";')
cookie = cursor.fetchone()
conn.commit()
conn.close()
return cookie
# 插入公共cookie
async def insert_public_cookie(cookie):
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS public_cookies
(
no int IDENTITY(1,1) PRIMARY KEY,
cookie TEXT,
status TEXT,
);''')
cursor.execute('INSERT IGNORE INTO public_cookies (cookie, status) VALUES (?,"ok");', (cookie,))
conn.commit()
conn.close()
# 设置公共cookie到上限
async def limit_public_cookie(cookie):
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS public_cookies(
no int PRIMARY KEY
cookie TEXT,
status TEXT);''')
cursor.execute('UPDATE public_cookies SET status="limited30" WHERE cookie=?;', (cookie,))
conn.commit()
conn.close()
# 通过key(如user_id, uid)获取私人cookie
async def get_private_cookie(value, key='user_id'):
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute(f'SELECT user_id, cookie, uid, mys_id FROM private_cookies WHERE {key}="{value}";')
cookie = cursor.fetchall()
conn.close()
return cookie
# 更新cookie
async def update_private_cookie(user_id, uid='', mys_id='', cookie='', stoken=''):
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute('REPLACE INTO private_cookies VALUES (?, ?, ?, ?, ?);', (user_id, uid, mys_id, cookie, stoken))
conn.commit()
conn.close()
# 删除私人cookie
async def delete_private_cookie(user_id):
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute('DELETE FROM private_cookies WHERE user_id=?',(user_id,))
conn.commit()
conn.close()
# 删除cookie
async def delete_cookie(cookie, type='public'):
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute('DELETE FROM cookie_cache WHERE cookie=?;', (cookie,))
cursor.execute(f'DELETE FROM {type}_cookies WHERE cookie="{cookie}";')
conn.commit()
conn.close()
# 获取cookie缓存
async def get_cookie_cache(value, key='uid'):
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS cookie_cache(
uid TEXT PRIMARY KEY NOT NULL,
mys_id TEXT,
cookie TEXT);''')
cursor.execute(f'SELECT cookie FROM cookie_cache WHERE {key}="{value}"')
res = cursor.fetchone()
if res:
try:
cursor.execute('SELECT user_id, uid, mys_id FROM private_cookies WHERE cookie=?;', (res[0],))
is_in_private = cursor.fetchone()
if is_in_private:
return {'type':'private', 'user_id': is_in_private[0], 'cookie': res[0], 'uid': is_in_private[1], 'mys_id': is_in_private[2]}
except:
pass
try:
cursor.execute('SELECT no FROM public_cookies WHERE cookie=?;', (res[0],))
is_in_public = cursor.fetchone()
if is_in_public:
return {'type':'public', 'cookie': res[0], 'no': is_in_public[0]}
except:
pass
conn.close()
return None
# 更新cookie缓存
async def update_cookie_cache(cookie, value, key='uid'):
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS cookie_cache(
uid TEXT PRIMARY KEY NOT NULL,
mys_id TEXT,
cookie TEXT);''')
cursor.execute(f'REPLACE INTO cookie_cache ({key}, cookie) VALUES ("{value}", "{cookie}");')
conn.commit()
conn.close()
# 删除cookie缓存
async def delete_cookie_cache(value='', key='cookie', all=False):
try:
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
if all:
cursor.execute('DROP TABLE cookie_cache;')
else:
cursor.execute(f'DELETE FROM cookie_cache WHERE {key}="{value}";')
conn.commit()
conn.close()
except:
pass
# 获取user_id最后查询的uid
async def get_last_query(user_id):
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS last_query(
user_id TEXT PRIMARY KEY NOT NULL,
uid TEXT,
last_time datetime);''')
cursor.execute('SELECT uid FROM last_query WHERE user_id=?;', (user_id,))
uid = cursor.fetchone()
conn.close()
return uid[0] if uid else None
# 更新user_id最后查询的uid
async def update_last_query(user_id, value, key='uid'):
t = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS last_query(
user_id TEXT PRIMARY KEY NOT NULL,
uid TEXT,
mys_id TEXT,
last_time datetime);''')
cursor.execute(f'REPLACE INTO last_query (user_id, {key}, last_time) VALUES ("{user_id}", "{value}", "{t}");')
conn.commit()
conn.close()
init_db()

View File

@ -1,15 +1,23 @@
import requests, json,re import requests, json,re
from hoshino import R,MessageSegment from hoshino import MessageSegment, Service, aiorequests
from hoshino.typing import CQEvent, Message from hoshino.typing import CQEvent, Message
from hoshino.util import PriFreqLimiter from hoshino.util import PriFreqLimiter
import hoshino
from ..util import Dict from ..util import Dict
from hoshino import aiorequests
from .gacha_role import * from .gacha_role import *
from .gacha_wish import more_ten from .gacha_wish import more_ten
lmt = PriFreqLimiter(60) lmt = PriFreqLimiter(30)
sv=hoshino.Service('原神模拟抽卡') help_msg='''
1.[抽n十连xx池]抽n次xx池的十连最多同时5次
*池子和官方同步有角色1|角色2|武器|常驻默认为角色1
2.[模拟抽卡记录]查看模拟抽卡记录总结
3.[模拟抽卡记录 角色/武器]查看模拟抽卡抽到的五星角色/武器
4.[删除模拟抽卡记录]顾名思义
5.[选择定轨 武器全名]选择武器定轨
6.[查看定轨]查看当前定轨的武器
7.[删除定轨]删除当前定轨的武器
'''
sv = Service('派蒙模拟抽卡', bundle='派蒙', help_=help_msg)
#activity = 301 限定卡池 #activity = 301 限定卡池
#activity2 = 400 限定卡池2 #activity2 = 400 限定卡池2
#weapon = 302 武器卡池 #weapon = 302 武器卡池
@ -44,7 +52,7 @@ async def gacha(bot, ev):
if not lmt.check(gid,uid): if not lmt.check(gid,uid):
await bot.finish(ev, f'模拟抽卡冷却中(剩余{int(lmt.left_time(gid,uid)) + 1}秒)', at_sender=True) await bot.finish(ev, f'模拟抽卡冷却中(剩余{int(lmt.left_time(gid,uid)) + 1}秒)', at_sender=True)
return return
lmt.start_cd(gid,uid,60) lmt.start_cd(gid, uid, 30)
if num >= 3: if num >= 3:
await bot.send(ev, '抽卡图正在生成中,请稍候') await bot.send(ev, '抽卡图正在生成中,请稍候')
if isinstance(gacha_type,int): if isinstance(gacha_type,int):

View File

@ -1,12 +1,17 @@
import json,os,re import json,os,re
from hoshino import R,MessageSegment,logger, Service from hoshino import R,MessageSegment,logger, Service
from hoshino.typing import CQEvent, Message from hoshino.typing import CQEvent, Message
from ..util import get_uid_by_qq, update_last_query_to_qq from ..util import get_uid_in_msg
from .gacha_logs import get_data from .gacha_logs import get_data
from .get_img import get_gacha_log_img from .get_img import get_gacha_log_img
from .api import toApi, checkApi from .api import toApi, checkApi
sv = Service('原神抽卡记录导出') help_msg='''
1.[获取抽卡记录 (uid) (url)]提供url获取原神抽卡记录需要一定时间
2.[查看抽卡记录 (uid)]查看抽卡记录分析
3.[导出抽卡记录 (uid) (xlsx/json)]导出抽卡记录文件上传到群文件中
'''
sv = Service('派蒙抽卡记录导出', bundle='派蒙', help_=help_msg)
data_path = os.path.join(os.path.dirname(os.path.dirname(__file__)),'user_data', 'gacha_log_data') data_path = os.path.join(os.path.dirname(os.path.dirname(__file__)),'user_data', 'gacha_log_data')
if not os.path.exists(data_path): if not os.path.exists(data_path):
@ -20,33 +25,13 @@ async def ckjl(bot,ev):
if ev.message_type != 'group': if ev.message_type != 'group':
await bot.send(ev,'在群聊中才能导出抽卡记录文件哦!') await bot.send(ev,'在群聊中才能导出抽卡记录文件哦!')
return return
msg = ev.message.extract_plain_text().strip().split(' ') uid, msg, user_id, use_cache = await get_uid_in_msg(ev)
uid = ''
if len(msg[0]) == 9 and msg[0].isdigit():
uid = msg[0]
if len(msg) >= 2:
filetype = msg[1]
else:
filetype = 'xlsx'
else:
filetype = msg[0]
if not filetype or filetype not in ['xlsx', 'json']:
filetype = 'xlsx'
qq = str(ev.user_id)
if ev.message_type == 'guild':
rm = str(ev.message)
else:
rm = str(ev.raw_message)
match = re.search(r"\[CQ:at,qq=(.*)\]", rm)
if match:
uid = ''
qq = str(match.group(1))
if not uid: if not uid:
uid = get_uid_by_qq(qq) await bot.send(ev,'请把uid给派蒙哦比如获取抽卡记录100000001 链接',at_sender=True)
if not uid: return
await bot.send(ev,'请把uid给派蒙哦比如抽卡记录导出100000001 xlsx',at_sender=True) find_filetype = r'(?P<filetype>xlsx|json)'
return match = re.search(find_filetype, msg)
update_last_query_to_qq(qq, uid) filetype = match.group('filetype') if match else 'xlsx'
if filetype == 'xlsx': if filetype == 'xlsx':
filetype = f'gachaExport-{uid}.xlsx' filetype = f'gachaExport-{uid}.xlsx'
else: else:
@ -59,24 +44,12 @@ async def ckjl(bot,ev):
@sv.on_prefix(('更新抽卡记录', '获取抽卡记录', 'updategachalog', 'gxckjl')) @sv.on_prefix(('更新抽卡记录', '获取抽卡记录', 'updategachalog', 'gxckjl'))
async def update_ckjl(bot,ev): async def update_ckjl(bot,ev):
msg = ev.message.extract_plain_text().strip().split(' ') uid, msg, user_id, use_cache = await get_uid_in_msg(ev)
uid = ''
if len(msg[0]) == 9 and msg[0].isdigit():
uid = msg[0]
if len(msg) >= 2:
url = msg[1]
else:
url = ''
else:
url = msg[0]
qq = str(ev.user_id)
if not uid: if not uid:
uid = get_uid_by_qq(qq) await bot.send(ev,'请把uid给派蒙哦比如获取抽卡记录100000001 链接',at_sender=True)
if not uid: return
await bot.send(ev,'请把uid给派蒙哦比如获取抽卡记录100000001 链接',at_sender=True) if msg:
return match = re.search(r'(https://webstatic.mihoyo.com/.*#/log)', msg)
if url:
match = re.search(r'(https://webstatic.mihoyo.com/.*#/log)', url)
if match: if match:
url = str(match.group(1)) url = str(match.group(1))
else: else:
@ -85,17 +58,17 @@ async def update_ckjl(bot,ev):
else: else:
with open(os.path.join(data_path, 'user_gacha_log.json'), 'r', encoding="utf-8") as f: with open(os.path.join(data_path, 'user_gacha_log.json'), 'r', encoding="utf-8") as f:
user_data = json.load(f) user_data = json.load(f)
if qq in user_data and uid in user_data[qq]: if user_id in user_data and uid in user_data[user_id]:
url = user_data[qq][uid] url = user_data[user_id][uid]
await bot.send(ev,'发现历史抽卡记录链接,尝试使用...') await bot.send(ev,'发现历史抽卡记录链接,尝试使用...')
else: else:
await bot.send(ev, '拿到游戏抽卡记录链接后,对派蒙说[获取抽卡记录 uid 链接]就可以啦\n获取抽卡记录链接的方式和vx小程序的是一样的还请旅行者自己搜方法', at_sender=True) await bot.send(ev, '拿到游戏抽卡记录链接后,对派蒙说[获取抽卡记录 uid 链接]就可以啦\n获取抽卡记录链接的方式和vx小程序的是一样的还请旅行者自己搜方法', at_sender=True)
return return
with open(os.path.join(data_path, 'user_gacha_log.json'), 'r', encoding="utf-8") as f: with open(os.path.join(data_path, 'user_gacha_log.json'), 'r', encoding="utf-8") as f:
user_data = json.load(f) user_data = json.load(f)
if qq not in user_data: if user_id not in user_data:
user_data[qq] = {} user_data[user_id] = {}
user_data[qq][uid] = url user_data[user_id][uid] = url
with open(os.path.join(data_path, 'user_gacha_log.json'), 'w', encoding="utf-8") as f: with open(os.path.join(data_path, 'user_gacha_log.json'), 'w', encoding="utf-8") as f:
json.dump(user_data, f, ensure_ascii=False, sort_keys=False, indent=4) json.dump(user_data, f, ensure_ascii=False, sort_keys=False, indent=4)
@ -115,34 +88,12 @@ async def update_ckjl(bot,ev):
@sv.on_prefix('查看抽卡记录', 'ckjl', 'gachalog') @sv.on_prefix('查看抽卡记录', 'ckjl', 'gachalog')
async def get_ckjl(bot,ev): async def get_ckjl(bot,ev):
msg = ev.message.extract_plain_text().strip().split(' ') uid, msg, user_id, use_cache = get_uid_in_msg(ev)
uid = ''
if len(msg[0]) == 9 and msg[0].isdigit():
uid = msg[0]
if len(msg) >= 2:
pool = msg[1]
else:
pool = 'all'
else:
pool = msg[0]
if not pool or pool not in ['all', '角色', '武器', '常驻', '新手']:
pool = 'all'
qq = str(ev.user_id)
if ev.message_type == 'guild':
rm = str(ev.message)
else:
rm = str(ev.raw_message)
match = re.search(r"\[CQ:at,qq=(.*)\]", rm)
if match:
uid = ''
qq = str(match.group(1))
if not uid: if not uid:
uid = get_uid_by_qq(qq) await bot.send(ev,'请把uid给派蒙哦比如获取抽卡记录100000001 链接',at_sender=True)
if not uid: return
await bot.send(ev,'请把uid给派蒙哦比如抽卡记录100000001 all',at_sender=True) match = re.search(r'(all|角色|武器|常驻|新手)',msg)
return pool = match.group(1) if match else 'all'
update_last_query_to_qq(qq, uid)
local_data = os.path.join(data_path, f'gachaData-{uid}.json') local_data = os.path.join(data_path, f'gachaData-{uid}.json')
if not os.path.exists(local_data): if not os.path.exists(local_data):
await bot.send(ev, '你在派蒙这里还没有抽卡记录哦,对派蒙说 获取抽卡记录 吧!', at_sender=True) await bot.send(ev, '你在派蒙这里还没有抽卡记录哦,对派蒙说 获取抽卡记录 吧!', at_sender=True)

View File

@ -7,7 +7,16 @@ from .blue import get_blue_pic
from ..util import pil2b64 from ..util import pil2b64
from hoshino.util import filt_message from hoshino.util import filt_message
sv=hoshino.Service('原神角色wiki') help_msg='''
1.[xx角色攻略]查看西风驿站出品的角色一图流攻略
2.[xx角色材料]查看惜月出品的角色材料统计
3.[xx参考面板]查看blue菌hehe出品的参考面板攻略
4.[xx收益曲线]查看blue菌hehe出品的收益曲线攻略
*感谢来自大佬们的授权角色支持别名查询
'''
sv = Service('派蒙WIKI', bundle='派蒙', help_=help_msg)
res_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'res') res_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'res')
@sv.on_prefix('角色攻略') @sv.on_prefix('角色攻略')

View File

@ -1,31 +1,38 @@
from hoshino import aiorequests from hoshino import aiorequests
from .util import get_headers, cache from .util import get_headers, cache, get_use_cookie, get_own_cookie, check_retcode
from .db_util import update_cookie_cache
import datetime import datetime
import re import re
import random
@cache(ttl=datetime.timedelta(minutes=30)) # TODO注意每处参数顺序的更改
async def get_abyss_data(uid, cookie, schedule_type = "1", use_cache=True): @cache(ttl=datetime.timedelta(hours=1))
if uid[0] == '5': async def get_abyss_data(user_id, uid, schedule_type = "1", use_cache=True):
server_id = "cn_qd01" server_id = "cn_qd01" if uid[0] == '5' else "cn_gf01"
else:
server_id = "cn_gf01"
url ="https://api-takumi.mihoyo.com/game_record/app/genshin/api/spiralAbyss" url ="https://api-takumi.mihoyo.com/game_record/app/genshin/api/spiralAbyss"
headers = get_headers(q="role_id=" + uid + "&schedule_type=" + schedule_type + "&server=" + server_id, cookie=cookie)
params ={ params ={
"schedule_type": schedule_type, "schedule_type": schedule_type,
"role_id": uid, "role_id": uid,
"server": server_id "server": server_id}
} while True:
res = await aiorequests.get(url=url, headers=headers, params=params) cookie = await get_use_cookie(user_id, uid=uid, action='查询深渊')
return await res.json() if not cookie:
return '现在派蒙没有可以用的cookie哦,请让主人 添加公共ck 吧!'
headers = get_headers(q=f'role_id={uid}&schedule_type={schedule_type}&server={server_id}', cookie=cookie['cookie'])
res = await aiorequests.get(url=url, headers=headers, params=params)
data = await res.json()
if await check_retcode(data, cookie, uid):
return data
async def get_daily_note_data(uid, cookie): async def get_daily_note_data(uid):
if uid[0] == '5': server_id = "cn_qd01" if uid[0] == '5' else "cn_gf01"
server_id = "cn_qd01"
else:
server_id = "cn_gf01"
url ="https://api-takumi.mihoyo.com/game_record/app/genshin/api/dailyNote" url ="https://api-takumi.mihoyo.com/game_record/app/genshin/api/dailyNote"
headers = get_headers(q="role_id=" + uid + "&server=" + server_id, cookie=cookie) cookie = await get_own_cookie(uid, action='查询实时便签')
if not cookie:
return f'你的uid{uid}没有绑定对应的cookie哦,先用ysb给派蒙绑定吧!'
await update_cookie_cache(cookie['cookie'], uid, 'uid')
headers = get_headers(q=f'role_id={uid}&server={server_id}', cookie=cookie['cookie'])
params = { params = {
"server": server_id, "server": server_id,
"role_id": uid "role_id": uid
@ -34,67 +41,79 @@ async def get_daily_note_data(uid, cookie):
return await res.json() return await res.json()
@cache(ttl=datetime.timedelta(hours=1)) @cache(ttl=datetime.timedelta(hours=1))
async def get_player_card_data(uid, cookie, use_cache=True): async def get_player_card_data(user_id, uid, use_cache=True):
if uid[0] == '5': server_id = "cn_qd01" if uid[0] == '5' else "cn_gf01"
server_id = "cn_qd01"
else:
server_id = "cn_gf01"
url ="https://api-takumi.mihoyo.com/game_record/app/genshin/api/index" url ="https://api-takumi.mihoyo.com/game_record/app/genshin/api/index"
headers = get_headers(q="role_id=" + uid + "&server=" + server_id, cookie=cookie)
params = { params = {
"server": server_id, "server": server_id,
"role_id": uid "role_id": uid
} }
res = await aiorequests.get(url=url, headers=headers, params=params) while True:
return await res.json() cookie = await get_use_cookie(user_id, uid=uid, action='查询原神卡片')
if not cookie:
return '现在派蒙没有可以用的cookie哦,请让主人 添加公共ck 吧!'
headers = get_headers(q=f'role_id={uid}&server={server_id}', cookie=cookie['cookie'])
res = await aiorequests.get(url=url, headers=headers, params=params)
data = await res.json()
if await check_retcode(data, cookie, uid):
return data
@cache(ttl=datetime.timedelta(hours=1)) @cache(ttl=datetime.timedelta(hours=1))
async def get_chara_detail_data(uid, cookie, use_cache=True): async def get_chara_detail_data(user_id, uid, use_cache=True):
if uid[0] == '5': server_id = "cn_qd01" if uid[0] == '5' else "cn_gf01"
server_id = "cn_qd01"
else:
server_id = "cn_gf01"
json_data = { json_data = {
"server": server_id, "server": server_id,
"role_id": uid, "role_id": uid,
"character_ids": [] "character_ids": []
} }
url = 'https://api-takumi.mihoyo.com/game_record/app/genshin/api/character' url = 'https://api-takumi.mihoyo.com/game_record/app/genshin/api/character'
headers = get_headers(b=json_data, cookie=cookie) while True:
res = await aiorequests.post(url=url, headers=headers, json=json_data) cookie = await get_use_cookie(user_id, uid=uid, action='查询角色详情')
return await res.json() if not cookie:
return '现在派蒙没有可以用的cookie哦,请让主人 添加公共ck 吧!'
headers = get_headers(b=json_data, cookie=cookie['cookie'])
res = await aiorequests.post(url=url, headers=headers, json=json_data)
data = await res.json()
if await check_retcode(data, cookie, uid):
return data
@cache(ttl=datetime.timedelta(hours=1)) @cache(ttl=datetime.timedelta(hours=1))
async def get_chara_skill_data(uid, chara_id, cookie, use_cache=True): async def get_chara_skill_data(uid, chara_id, use_cache=True):
if uid[0] == '5': server_id = "cn_qd01" if uid[0] == '5' else "cn_gf01"
server_id = "cn_qd01"
else:
server_id = "cn_gf01"
url = 'https://api-takumi.mihoyo.com/event/e20200928calculate/v1/sync/avatar/detail' url = 'https://api-takumi.mihoyo.com/event/e20200928calculate/v1/sync/avatar/detail'
headers = get_headers(q="uid=" + uid + "&region=" + server_id + "&avatar_id=" + str(chara_id), cookie=cookie) cookie = await get_own_cookie(uid, action='查询角色天赋')
if not cookie:
return None
await update_cookie_cache(cookie['cookie'], uid, 'uid')
headers = get_headers(q=f'uid={uid}&region={server_id}&avatar_id={chara_id}', cookie=cookie['cookie'])
params = { params = {
"region": server_id, "region": server_id,
"uid": uid, "uid": uid,
"avatar_id": chara_id "avatar_id": chara_id
} }
res = await aiorequests.get(url=url, headers=headers, params=params) res = await aiorequests.get(url=url, headers=headers, params=params)
return await res.json() data = await res.json()
# TODO:待定未知cookie对技能的影响
return data
@cache(ttl=datetime.timedelta(hours=1)) @cache(ttl=datetime.timedelta(hours=1))
async def get_monthinfo_data(uid, month, cookie, use_cache=True): async def get_monthinfo_data(uid, month, use_cache=True):
if uid[0] == '5': server_id = "cn_qd01" if uid[0] == '5' else "cn_gf01"
server_id = "cn_qd01"
else:
server_id = "cn_gf01"
url = 'https://hk4e-api.mihoyo.com/event/ys_ledger/monthInfo' url = 'https://hk4e-api.mihoyo.com/event/ys_ledger/monthInfo'
headers = get_headers(q='month='+ str(month) + '&bind_uid=' + uid + '&bind_region=' + server_id, cookie=cookie) cookie = await get_own_cookie(uid, action='查询每月札记')
if not cookie:
return f'你的uid{uid}没有绑定对应的cookie哦,先用ysb给派蒙绑定吧!'
await update_cookie_cache(cookie['cookie'], uid, 'uid')
headers = get_headers(q=f'month={month}&bind_uid={uid}&bind_region={server_id}', cookie=cookie['cookie'])
params = { params = {
"month": int(month), "month": int(month),
"bind_uid": uid, "bind_uid": uid,
"bind_region": server_id "bind_region": server_id
} }
res = await aiorequests.get(url=url, headers=headers, params=params) res = await aiorequests.get(url=url, headers=headers, params=params)
return await res.json() data = await res.json()
if await check_retcode(data, cookie, uid):
return data
async def get_bind_game(cookie): async def get_bind_game(cookie):
finduid = re.search(r'account_id=(\d{6,12})', cookie) finduid = re.search(r'account_id=(\d{6,12})', cookie)
@ -102,11 +121,13 @@ async def get_bind_game(cookie):
return None return None
uid = finduid.group(1) uid = finduid.group(1)
url = 'https://api-takumi.mihoyo.com/game_record/card/wapi/getGameRecordCard' url = 'https://api-takumi.mihoyo.com/game_record/card/wapi/getGameRecordCard'
headers = get_headers(q='uid=' + uid, cookie = cookie) headers = get_headers(q=f'uid={uid}', cookie = cookie)
params = { params = {
"uid": uid "uid": uid
} }
res = await aiorequests.get(url=url, headers=headers, params=params) res = await aiorequests.get(url=url, headers=headers, params=params)
return await res.json() return (await res.json()), uid

View File

@ -2,55 +2,36 @@ import json,os,re,datetime
from hoshino import R,MessageSegment,logger, Service from hoshino import R,MessageSegment,logger, Service
from hoshino.typing import CQEvent, Message from hoshino.typing import CQEvent, Message
from hoshino.util import filt_message from hoshino.util import filt_message
from ..util import get_uid_by_qq, get_cookie, check_uid_by_qq, update_last_query_to_qq from ..util import get_uid_in_msg
from ..get_data import get_monthinfo_data from ..get_data import get_monthinfo_data
from .get_img import draw_monthinfo_card from .get_img import draw_monthinfo_card
sv = Service('原神每月札记') help_msg='''
[myzj/每月札记/zj (uid) (月份)]查看该月份获得的原石摩拉数
*绑定私人cookie之后才能使用,只能查看最近3个月的记录,默认为本月
'''
sv = Service('派蒙每月札记', bundle='派蒙', help_=help_msg)
@sv.on_prefix(('myzj','每月札记')) @sv.on_prefix(('myzj', '每月札记', 'zj'))
async def main(bot,ev): async def main(bot,ev):
msg = ev.message.extract_plain_text().strip().split(' ') uid, msg, user_id, use_cache = await get_uid_in_msg(ev)
uid = '' # 札记只能查看最近3个月的构造正则来获取月份
if len(msg[0]) == 9 and msg[0].isdigit(): month_now = datetime.datetime.now().month
uid = msg[0] if month_now == 1:
if len(msg) >= 2: month_list = ['11','12','1']
month = msg[1] elif month_now == 2:
else: month_list = ['12', '1', '2']
month = datetime.datetime.now().month
else: else:
month = msg[0] month_list = [str(month_now - 2), str(month_now - 1)]
if month and not month.isdigit(): find_month = '(?P<month>' + '|'.join(month_list) + ')'
await bot.send(ev,'月份是不是写错了呀,要阿拉伯数字哦',at_sender=True) match = re.search(find_month, msg)
return month = match.group('month') if match else month_now
qq = str(ev.user_id) # try:
if ev.message_type == 'guild': data = await get_monthinfo_data(uid, month, use_cache=use_cache)
rm = str(ev.message) if isinstance(data, str):
await bot.send(ev, data, at_sender=True)
else: else:
rm = str(ev.raw_message) monthinfo_card = await draw_monthinfo_card(data)
match = re.search(r"\[CQ:at,qq=(.*)\]", rm) await bot.send(ev, monthinfo_card, at_sender=True)
if match: # except Exception as e:
uid = '' #  await bot.send(ev, f'派蒙出现了问题:{e}',at_sender=True)
qq = str(match.group(1))
if uid and not check_uid_by_qq(qq, uid):
await bot.send(ev,'派蒙没有这个uid的绑定信息哦',at_sender=True)
return
if not uid:
uid = get_uid_by_qq(qq)
if not uid:
await bot.send(ev,'你还没把信息绑定给派蒙哦',at_sender=True)
return
if len(uid) != 9 or not uid.isdigit():
await bot.send(ev,f'uid {filt_message(uid)} 不合规,是不是打错了呀',at_sender=True)
return
cookie = await get_cookie(qq, uid, only_private = True, only_match_uid = True)
update_last_query_to_qq(qq, uid)
if not cookie:
await bot.send(ev,'你没有绑定cookie或者cookie失效了噢',at_sender=True)
else:
try:
data = await get_monthinfo_data(uid, month, cookie)
monthinfo_card = await draw_monthinfo_card(data)
await bot.send(ev, monthinfo_card, at_sender=True)
except Exception as e:
await bot.send(ev, f'派蒙出现了问题:{e}',at_sender=True)

View File

@ -2,127 +2,80 @@ import json,os,re
from hoshino import R,MessageSegment,logger, Service from hoshino import R,MessageSegment,logger, Service
from hoshino.typing import CQEvent, Message from hoshino.typing import CQEvent, Message
from hoshino.util import filt_message from hoshino.util import filt_message
from ..util import get_uid_by_qq, get_cookie, check_uid_by_qq, update_last_query_to_qq from ..util import get_uid_in_msg, get_at_target
from ..get_data import get_player_card_data, get_chara_detail_data, get_chara_skill_data from ..get_data import get_player_card_data, get_chara_detail_data, get_chara_skill_data
from .get_img import draw_player_card, draw_all_chara_card, draw_chara_card from .get_img import draw_player_card, draw_all_chara_card, draw_chara_card
from ..character_alias import get_id_by_alias from ..character_alias import get_id_by_alias
sv = Service('原神信息查询') help_msg='''
1.[ys (uid)]查看原神个人卡片(包含宝箱探索度等数据)
2.[ysa (uid)]查看所有公开的8角色的简略信息
3.[ysc (uid) 角色名]查看公开的8角色的详细信息
*绑定私人cookie之后就可以查看所有角色啦
'''
sv = Service('派蒙原神信息查询', bundle='派蒙', help_=help_msg)
@sv.on_prefix('ys') @sv.on_prefix('ys')
async def player_card(bot,ev): async def player_card(bot,ev):
uid = ev.message.extract_plain_text().strip() uid, msg, user_id, use_cache = await get_uid_in_msg(ev)
qq = str(ev.user_id)
if ev.message_type == 'guild':
rm = str(ev.message)
else:
rm = str(ev.raw_message)
match = re.search(r"\[CQ:at,qq=(.*)\]", rm)
if match:
uid = ''
qq = str(match.group(1))
if not uid: if not uid:
uid = get_uid_by_qq(qq) await bot.send(ev,'请把正确的uid给派蒙哦,例如sy100123456!',at_sender=True)
if not uid: return
await bot.send(ev,'请把uid给派蒙哦比如ys100000001',at_sender=True) # try:
return data = await get_player_card_data(user_id, uid, use_cache=use_cache)
if len(uid) != 9 or not uid.isdigit(): if isinstance(data, str):
await bot.send(ev,f'uid {filt_message(uid)} 不合规,是不是打错了呀',at_sender=True) await bot.send(ev, data, at_sender=True)
return
cookie = await get_cookie(qq, uid)
update_last_query_to_qq(qq, uid)
if not cookie:
await bot.send(ev,'这个uid的cookie信息好像失效了请给派蒙重新绑定',at_sender=True)
else: else:
try: if ev.message_type == 'group':
if ev.message_type == 'group': user_info = await bot.get_group_member_info(group_id=ev.group_id,user_id=int(user_id))
user_info = await bot.get_group_member_info(group_id=ev.group_id,user_id=int(qq)) nickname = user_info['card'] or user_info['nickname']
nickname = user_info['card'] or user_info['nickname'] else:
else: nickname = ev.sender['nickname']
nickname = ev.sender['nickname'] chara_data = await get_chara_detail_data(user_id, uid, use_cache=use_cache)
data = await get_player_card_data(uid, cookie) chara_data = None if isinstance(chara_data, str) else chara_data
chara_data = await get_chara_detail_data(uid, cookie) or [] player_card = await draw_player_card(data, chara_data, uid, nickname)
player_card = await draw_player_card(data, chara_data, uid, nickname) await bot.send(ev, player_card, at_sender=True)
await bot.send(ev, player_card, at_sender=True) # except Exception as e:
except Exception as e: # await bot.send(ev, f'派蒙出现了问题:{e}',at_sender=True)
await bot.send(ev, f'派蒙出现了问题:{e}',at_sender=True)
@sv.on_prefix('ysa') @sv.on_prefix('ysa')
async def all_characters(bot,ev): async def all_characters(bot,ev):
uid = ev.message.extract_plain_text().strip() uid, msg, user_id, use_cache = await get_uid_in_msg(ev)
qq = str(ev.user_id)
if ev.message_type == 'guild':
rm = str(ev.message)
else:
rm = str(ev.raw_message)
match = re.search(r"\[CQ:at,qq=(.*)\]", rm)
if match:
uid = ''
qq = str(match.group(1))
if not uid: if not uid:
uid = get_uid_by_qq(qq) await bot.send(ev,'请把正确的uid给派蒙哦,例如sy100123456!',at_sender=True)
if not uid:
await bot.send(ev,'请把uid给派蒙哦比如ysa100000001',at_sender=True)
return
if len(uid) != 9 or not uid.isdigit():
await bot.send(ev,f'uid {filt_message(uid)} 不合规,是不是打错了呀',at_sender=True)
return return
cookie = await get_cookie(qq, uid) # try:
update_last_query_to_qq(qq, uid) chara_data = await get_chara_detail_data(user_id, uid, use_cache=use_cache)
if not cookie: if isinstance(chara_data, str):
await bot.send(ev,'这个uid的cookie信息好像失效了请给派蒙重新绑定',at_sender=True) await bot.send(ev, chara_data, at_sender=True)
else: else:
try: player_card = await draw_all_chara_card(chara_data, uid)
chara_data = await get_chara_detail_data(uid, cookie) or [] await bot.send(ev, player_card, at_sender=True)
player_card = await draw_all_chara_card(chara_data, uid) # except Exception as e:
await bot.send(ev, player_card, at_sender=True) # await bot.send(ev, f'派蒙出现了问题:{e}',at_sender=True)
except Exception as e:
await bot.send(ev, f'派蒙出现了问题:{e}',at_sender=True)
@sv.on_prefix('ysc') @sv.on_prefix('ysc')
async def my_characters(bot,ev): async def my_characters(bot,ev):
msg = ev.message.extract_plain_text().strip().split(' ') uid, msg, user_id, use_cache = await get_uid_in_msg(ev)
qq = str(ev.user_id) if not uid:
uid = '' await bot.send(ev,'请把正确的uid给派蒙哦,例如sy100123456!',at_sender=True)
if len(msg[0]) == 9 and msg[0].isdigit(): return
uid = msg[0] if not msg:
if len(msg) >= 2: await bot.send(ev,f'要把角色名给派蒙呀!例如ysc100123456钟离',at_sender=True)
chara = msg[1] return
else: chara = msg.split(' ')[0]
await bot.send(ev,'要把想查询的角色名告诉我哦!',at_sender=True)
return
else:
chara = msg[0]
chara_name = get_id_by_alias(chara) chara_name = get_id_by_alias(chara)
if not chara_name: if not chara_name:
await bot.send(ev,f'没有角色名叫{filt_message(chara)}哦!',at_sender=True) await bot.send(ev,f'没有角色名叫{filt_message(chara)}哦!',at_sender=True)
return return
if ev.message_type == 'guild': # try:
rm = str(ev.message) chara_data = await get_chara_detail_data(user_id, uid, use_cache=use_cache)
if isinstance(chara_data, str):
await bot.send(ev, chara_data, at_sender=True)
else: else:
rm = str(ev.raw_message) skill_data = await get_chara_skill_data(uid, chara_name[0], use_cache=use_cache)
match = re.search(r"\[CQ:at,qq=(.*)\]", rm) chara_card = await draw_chara_card(chara_data, skill_data, chara_name, uid)
if match: await bot.send(ev, chara_card, at_sender=True)
qq = str(match.group(1)) # except Exception as e:
if not uid: # await bot.send(ev, f'派蒙出现了问题:{e}',at_sender=True)
uid = get_uid_by_qq(qq)
if not uid:
await bot.send(ev,'请把uid给派蒙哦比如ysc100000001 钟离',at_sender=True)
return
if len(uid) != 9 or not uid.isdigit():
await bot.send(ev,f'uid {filt_message(uid)} 不合规,是不是打错了呀',at_sender=True)
return
cookie = await get_cookie(qq, uid)
update_last_query_to_qq(qq, uid)
if not cookie:
await bot.send(ev,'你没有绑定cookie或者cookie失效了噢',at_sender=True)
else:
try:
chara_data = await get_chara_detail_data(uid, cookie)
skill_data = await get_chara_skill_data(uid, chara_name[0], cookie)
chara_card = await draw_chara_card(chara_data, skill_data, chara_name, uid)
await bot.send(ev, chara_card, at_sender=True)
except Exception as e:
await bot.send(ev, f'派蒙出现了问题:{e}',at_sender=True)

View File

@ -218,7 +218,7 @@ async def draw_player_card(data, chara_data, uid, nickname="旅行者"):
# 世界探索 # 世界探索
await draw_world_data(bg_draw,data) await draw_world_data(bg_draw,data)
# 角色 # 角色
if chara_data['data']: if chara_data:
chara_data = chara_data['data']['avatars'] chara_data = chara_data['data']['avatars']
w = 1045 w = 1045
i = 0 i = 0
@ -429,6 +429,9 @@ async def draw_chara_card(data, skill_data, chara_name, uid):
bg_img.alpha_composite(reli_icon, reli_p[i]) bg_img.alpha_composite(reli_icon, reli_p[i])
i += 1 i += 1
if not skill_data:
skill_data = {'retcode' : 'error'}
# 补上三命和五命的技能等级提升 # 补上三命和五命的技能等级提升
if skill_data['retcode'] == 0 and character['constellations'][2]['is_actived']: if skill_data['retcode'] == 0 and character['constellations'][2]['is_actived']:
skill_name = re.search(r'>(.*)</color>', character['constellations'][2]['effect']) skill_name = re.search(r'>(.*)</color>', character['constellations'][2]['effect'])

View File

@ -1,42 +1,64 @@
from hoshino import MessageSegment, Service, trigger, priv, CanceledException from hoshino import MessageSegment, Service, trigger, priv, CanceledException,logger
from hoshino.typing import CQEvent, Message from hoshino.typing import CQEvent, Message
from ..util import update_last_query_to_qq, bind_cookie, bind_public_cookie
from nonebot import message_preprocessor from nonebot import message_preprocessor
from ..get_data import get_bind_game from ..get_data import get_bind_game
from ..db_util import insert_public_cookie, update_private_cookie, delete_cookie_cache, delete_cookie
sv = Service('原神绑定',visible=False,enable_on_default=True) help_msg='''
1.[ysb cookie]绑定你的私人cookie以开启高级功能
2.[删除ck]删除你的私人cookie
3.[添加公共ck cookie]添加公共cookie以供大众查询*仅管理员
'''
sv = Service('派蒙绑定', visible=False, enable_on_default=True, bundle='派蒙', help_=help_msg)
cookie_error_msg = '这个cookie无效哦请旅行者确认是否正确\n1.ck要登录mys帐号后获取\n2.获取ck后不能退出登录\n3.ck至少要包含cookie_token和account_id两个参数\n4.建议在无痕模式下取'
@sv.on_prefix(('原神绑定','ysb')) @sv.on_prefix(('原神绑定','ysb'))
async def bind(bot,ev): async def bind(bot,ev):
cookie = ev.message.extract_plain_text().strip() cookie = ev.message.extract_plain_text().strip()
qq=str(ev.user_id)
if cookie == '': if cookie == '':
res = '''旅行者好呀你可以直接用ys/ysa等指令附上uid来使用派蒙\n如果想看全部角色信息和实时便笺等功能要把cookie给派蒙哦\ncookie获取方法登录网页版米游社在地址栏粘贴代码\njavascript:(function(){prompt(document.domain,document.cookie)})();\n复制弹窗出来的字符串手机要via或chrome浏览器才行\n然后添加派蒙私聊发送ysb接刚刚复制的字符串例如:ysb UM_distinctid=17d131d...\ncookie是账号重要安全信息请确保机器人持有者可信赖''' res = '''旅行者好呀你可以直接用ys/ysa等指令附上uid来使用派蒙\n如果想看全部角色信息和实时便笺等功能要把cookie给派蒙哦\ncookie获取方法登录网页版米游社在地址栏粘贴代码\njavascript:(function(){prompt(document.domain,document.cookie)})();\n复制弹窗出来的字符串手机要via或chrome浏览器才行\n然后添加派蒙私聊发送ysb接刚刚复制的字符串例如:ysb UM_distinctid=17d131d...\ncookie是账号重要安全信息请确保机器人持有者可信赖'''
await bot.send(ev,res,at_sender=True) await bot.send(ev,res,at_sender=True)
else: else:
cookie_info = await get_bind_game(cookie) cookie_info, mys_id = await get_bind_game(cookie)
if not cookie_info or cookie_info['retcode'] != 0: if not cookie_info or cookie_info['retcode'] != 0:
msg = '这cookie没有用哦检查一下是不是复制错了或者过期了(试试重新登录米游社再获取)' msg = cookie_error_msg
if ev.detail_type != 'private': if ev.detail_type != 'private':
msg += '\n当前是在群聊里绑定,建议旅行者添加派蒙好友私聊绑定' msg += '\n当前是在群聊里绑定,建议旅行者添加派蒙好友私聊绑定!'
await bot.send(ev,msg,at_sender=True) await bot.send(ev,msg,at_sender=True)
else: else:
for data in cookie_info['data']['list']: for data in cookie_info['data']['list']:
if data['game_id'] == 2: if data['game_id'] == 2:
uid = data['game_role_id'] uid = data['game_role_id']
nickname = data['nickname'] nickname = data['nickname']
# level = data['level']
break break
if uid: if uid:
await bind_cookie(qq,uid,cookie) await update_private_cookie(user_id=str(ev.user_id), uid=uid, mys_id=mys_id, cookie=cookie)
msg = f'{nickname}绑定成功啦使用ys/ysa等指令和派蒙互动吧' await delete_cookie_cache(uid, key='uid', all=False)
msg = f'{nickname}绑定成功啦!使用ys/ysa等指令和派蒙互动吧!'
if ev.detail_type != 'private': if ev.detail_type != 'private':
msg += '\n当前是在群聊里绑定建议旅行者把cookie撤回哦' msg += '\n当前是在群聊里绑定建议旅行者把cookie撤回哦!'
await bot.send(ev,msg,at_sender=True) await bot.send(ev,msg,at_sender=True)
@sv.on_prefix('删除ck')
async def delete(bot,ev):
user_id = str(ev.user_id)
await delete_private_cookie(str(ev.user_id))
await bot.send(ev, '派蒙把你的私人cookie都删除啦!', at_sender=True)
@sv.on_prefix('添加公共ck') @sv.on_prefix('添加公共ck')
async def bing_public(bot,ev): async def bing_public(bot, ev):
if not priv.check_priv(ev, hoshino.priv.ADMIN):
await bot.send(ev, '只有管理员或主人才能添加公共cookie哦!')
return
cookie = ev.message.extract_plain_text().strip() cookie = ev.message.extract_plain_text().strip()
res = await bind_public_cookie(cookie) if await check_cookie(cookie):
await bot.send(ev,res,at_sender=True) await insert_public_cookie(cookie)
await bot.send(ev, '公共cookie添加成功啦,派蒙开始工作!')
else:
await bot.send(ev, cookie_error_msg)
@sv.scheduled_job('cron', hour='0')
async def delete_cache():
logger.info('---清空今日cookie缓存---')
await delete_cookie_cache(all=True)

View File

@ -1,54 +1,78 @@
import os import os
import json import json
import traceback
import hashlib import hashlib
import re
import random import random
import time import time
import uuid
import requests
from hoshino import logger, aiorequests from hoshino import logger, aiorequests
from io import BytesIO from io import BytesIO
import base64 import base64
import datetime import datetime
import functools import functools
import inspect import inspect
from nonebot import get_bot
from .db_util import get_private_cookie, get_cookie_cache, get_public_cookie, limit_public_cookie, update_cookie_cache,get_last_query,update_last_query,delete_cookie
# user_cookies.json数据文件模版如没有.json文件就会按这个模版生成文件 async def get_use_cookie(user_id, uid='', mys_id='', action=''):
user_cookies_example = { cache_cookie = await get_cookie_cache(uid, 'uid')
"通用": [ if cache_cookie:
{ if cache_cookie['type'] == 'public':
"cookie": "", logger.info(f'---派蒙调用{uid}的缓存公共cookie执行{action}操作---')
"no": 1 else:
}, logger.info(f'---派蒙调用{uid}的缓存私人cookie执行{action}操作---')
{ return cache_cookie
"cookie": "", cookies = await get_private_cookie(user_id, 'user_id')
"no": 2 if not cookies:
} public_cookie = await get_public_cookie()
], if not public_cookie:
"私人":{} return None
else:
} logger.info(f'---派蒙调用{public_cookie[0]}号公共cookie执行{action}操作---')
user_cookies = {} return {'type':'public', 'cookie': public_cookie[1], 'no': public_cookie[0]}
def load_data(): else:
path = os.path.join(os.path.dirname(__file__), 'user_data','user_cookies.json') for user_id_, cookie, uid_, mys_id_ in cookies:
if not os.path.exists(path): if (uid and uid_ == uid) or (mys_id and mys_id_ == mys_id):
with open(path,'w',encoding='UTF-8') as f: logger.info(f'---派蒙调用用户{user_id_}的uid{uid_}私人cookie执行{action}操作---')
json.dump(user_cookies_example,f,ensure_ascii=False) return {'type':'private', 'user_id': user_id_, 'cookie': cookie, 'uid': uid_, 'mys_id': mys_id_}
try: use_cookie = random.choice(cookies)
with open(path, encoding='utf8') as f: logger.info(f'---派蒙调用用户{use_cookie[0]}的uid{use_cookie[2]}私人cookie执行{action}操作---')
data = json.load(f) return {'type':'private', 'user_id': use_cookie[0], 'cookie': use_cookie[1], 'uid': use_cookie[2], 'mys_id': use_cookie[3]}
for k, v in data.items():
user_cookies[k] = v async def get_own_cookie(uid='', mys_id='', action=''):
except: if uid:
traceback.print_exc() cookie = (await get_private_cookie(uid, 'uid'))
elif mys_id:
cookie = (await get_private_cookie(mys_id, 'mys_id'))
else:
cookie = None
if not cookie:
return None
else:
cookie = cookie[0]
logger.info(f'---派蒙调用用户{cookie[0]}的uid{cookie[2]}私人cookie执行{action}操作---')
return {'type':'private', 'user_id': cookie[0], 'cookie': cookie[1], 'uid': cookie[2], 'mys_id': cookie[3]}
# 检查数据返回状态10001为ck过期了10101为达到每日30次上线了
async def check_retcode(data, cookie, uid):
if data['retcode'] == 10001:
# TODO此处为删除cookie的操作
await delete_cookie(cookie['cookie'], cookie['type'])
# TODO: 此处为发送cookie删除信息提醒的操作
await send_cookie_delete_msg(cookie)
return False
elif data['retcode'] == 10101:
# TODO: 此处为设置cookie到30次上限的操作
if cookie['type'] == 'public':
logger.info(f'{cookie["no"]}号公共cookie达到了每日30次查询上限')
elif cookie['type'] == 'private':
logger.info(f'用户{cookie["user_id"]}的uid{cookie["uid"]}私人cookie达到了每日30次查询上限')
await limit_public_cookie(cookie['cookie'])
return False
else:
# TODO: 此处为更新最后查询的操作
await update_cookie_cache(cookie['cookie'], uid, 'uid')
return True
def save_data():
path = os.path.join(os.path.dirname(__file__), 'user_data','user_cookies.json')
try:
with open(path, 'w', encoding='utf8') as f:
json.dump(user_cookies, f, ensure_ascii=False, indent=2)
except:
traceback.print_exc()
# 缓存装饰器 ttl为过期时间 参数use_cache决定是否使用缓存默认为True # 缓存装饰器 ttl为过期时间 参数use_cache决定是否使用缓存默认为True
def cache(ttl=datetime.timedelta(hours=1), **kwargs): def cache(ttl=datetime.timedelta(hours=1), **kwargs):
@ -81,6 +105,34 @@ def cache(ttl=datetime.timedelta(hours=1), **kwargs):
return wrap return wrap
# 获取message中的艾特对象
async def get_at_target(msg):
for msg_seg in msg:
if msg_seg.type == "at":
return msg_seg.data['qq']
return None
# message预处理获取uid、干净的msg、user_id、是否缓存
async def get_uid_in_msg(ev):
msg = ev.message
msgt = msg.extract_plain_text().strip()
if not msg:
uid = await get_last_query(str(ev.user_id))
return uid, '', str(ev.user_id), True
user_id = await get_at_target(msg) or str(ev.user_id)
use_cache = False if '-r' in msgt else True
msgt = msgt.replace('-r', '').strip()
find_uid = r'(?P<uid>(1|2|5)\d{8})'
for msg_seg in msg:
if msg_seg.type == 'text':
match = re.search(find_uid, msg_seg.data['text'])
if match:
await update_last_query(user_id, match.group('uid'), 'uid')
return match.group('uid'), msgt.replace(match.group('uid'), '').strip(), user_id, use_cache
uid = await get_last_query(user_id)
return uid, msgt.strip(), user_id, use_cache
class Dict(dict): class Dict(dict):
__setattr__ = dict.__setitem__ __setattr__ = dict.__setitem__
__getattr__ = dict.__getitem__ __getattr__ = dict.__getitem__
@ -123,10 +175,9 @@ def get_headers(cookie, q='',b=None):
'x-rpc-client_type': '5', 'x-rpc-client_type': '5',
'Referer': 'https://webstatic.mihoyo.com/' 'Referer': 'https://webstatic.mihoyo.com/'
} }
#print(headers)
return headers return headers
# 检查cookie是否有效通过查看个人主页是否返回ok来判断 # 检查cookie是否有效通过查看个人主页来判断
async def check_cookie(cookie): async def check_cookie(cookie):
url = 'https://bbs-api.mihoyo.com/user/wapi/getUserFullInfo?gids=2' url = 'https://bbs-api.mihoyo.com/user/wapi/getUserFullInfo?gids=2'
headers ={ headers ={
@ -144,91 +195,21 @@ async def check_cookie(cookie):
else: else:
return True return True
# 通过qq号获取最后查询的uid # 向超级用户私聊发送cookie删除信息
def get_uid_by_qq(qq): async def send_cookie_delete_msg(cookie_info):
if qq not in user_cookies['私人']: msg = ''
return None if cookie_info['type'] == 'public':
return user_cookies['私人'][qq]['last_query'] msg = f'公共池的{cookie_info["no"]}号cookie已失效'
elif cookie_info['type'] == 'private':
if cookie_info['uid']:
msg = f'用户{cookie_info["user_id"]}的uid{cookie_info["uid"]}的cookie已失效'
elif cookie_info['mys_id']:
msg = f'用户{cookie_info["user_id"]}的mys_id{cookie_info["mys_id"]}的cookie已失效'
if msg:
logger.info(f'---{msg}---')
for superuser in get_bot().config.SUPERUSERS:
try:
await get_bot().send_private_msg(user_id=superuser,message=msg + ',派蒙帮你删除啦!')
except Exception as e:
logger.error(f'发送cookie删除消息失败: {e}')
# 检查qq号是否绑定uid
def check_uid_by_qq(qq, uid):
if qq not in user_cookies['私人']:
return False
for cookie in user_cookies['私人'][qq]['cookies']:
if cookie['uid'] == uid:
return True
return False
# 更新qq最后查询的uid
def update_last_query_to_qq(qq, uid):
if qq not in user_cookies['私人']:
user_cookies['私人'][qq] = {}
user_cookies['私人'][qq]['cookies'] = []
user_cookies['私人'][qq]['last_query'] = uid
save_data()
# 绑定uid、cookie到qq号
async def bind_cookie(qq, uid, cookie):
if qq not in user_cookies['私人']:
user_cookies['私人'][qq] = {}
user_cookies['私人'][qq]['cookies'] = []
f = False
for c in user_cookies['私人'][qq]['cookies']:
if c['uid'] == uid:
c['cookie'] = cookie
f = True
break
if not f:
c = {'cookie':cookie,'uid':uid}
user_cookies['私人'][qq]['cookies'].append(c)
user_cookies['私人'][qq]['last_query'] = uid
save_data()
# 绑定cookie到公共cookie池
async def bind_public_cookie(cookie):
if not await check_cookie(cookie):
return '这cookie没有用哦检查一下是不是复制错了或者过期了(试试重新登录米游社再获取)'
else:
user_cookies['通用'].append({"cookie": cookie, "no": len(user_cookies['通用']) + 1})
save_data()
return '添加公共cookie成功'
# 获取公共池可用的cookie
async def get_public_cookie():
for cookie in user_cookies['通用']:
if await check_cookie(cookie['cookie']):
logger.info(f'--CMgenshin调用公共cookie池-{cookie["no"]}号执行操作==')
return cookie['cookie']
else:
logger.info(f'--CMgenshin公共cookie池-{cookie["no"]}号已失效--')
logger.error('--CMgenshin原神查询公共cookie池已全部失效--')
return None
# 获取可用的cookie优先获取私人cookie没有则获取公共池cookie
async def get_cookie(qq, uid, only_private = False, only_match_uid = False):
if qq not in user_cookies['私人']:
if only_private:
return None
else:
return await get_public_cookie()
else:
valid_cookie = []
for cookie in user_cookies['私人'][qq]['cookies']:
if not await check_cookie(cookie['cookie']):
logger.error(f'--CMgenshinqq{qq}下的cookie-{cookie["uid"]}已失效--')
else:
valid_cookie.append(cookie)
if cookie['uid'] == uid:
logger.info(f'--CMgenshin调用qq{qq}的cookie-{cookie["uid"]}执行操作--')
return cookie['cookie']
if valid_cookie and only_match_uid:
logger.info(f'--CMgenshin调用qq{qq}的cookie-{cookie["uid"]}执行操作--')
return random.choice(valid_cookie)['cookie']
else:
if only_private:
return None
else:
return await get_public_cookie()
# 初始化读取cookie数据
load_data()

View File

@ -14,7 +14,7 @@ async def handle_group_invite(session: RequestSession):
async def handle_unknown_group_invite(session): async def handle_unknown_group_invite(session):
if session.ctx['user_id'] == session.ctx['self_id']: if session.ctx['user_id'] == session.ctx['self_id']:
try: try:
await nonebot.get_bot().send_private_msg(user_id=nonebot.get_bot().config.SUPERUSERS,message=f'{session.ctx["group_id"]}未经允许拉了派蒙进群') await nonebot.get_bot().send_private_msg(user_id=nonebot.get_bot().config.SUPERUSERS[0],message=f'{session.ctx["group_id"]}未经允许拉了派蒙进群')
except Exception as e: except Exception as e:
print('处理群聊邀请错误:',e) print('处理群聊邀请错误:',e)
else: else: