mirror of
https://github.com/PaiGramTeam/PaiGram.git
synced 2024-11-25 09:37:30 +00:00
✨ 支持抽卡记录导入/导出
This commit is contained in:
parent
9b10e382b0
commit
7f2bb53c7f
12
metadata/pool/pool.py
Normal file
12
metadata/pool/pool.py
Normal file
@ -0,0 +1,12 @@
|
||||
from metadata.pool.pool_200 import POOL_200
|
||||
from metadata.pool.pool_301 import POOL_301
|
||||
from metadata.pool.pool_302 import POOL_302
|
||||
|
||||
|
||||
def get_pool_by_id(pool_type):
|
||||
if pool_type == 200:
|
||||
return POOL_200
|
||||
elif pool_type == 301:
|
||||
return POOL_301
|
||||
elif pool_type == 302:
|
||||
return POOL_302
|
11
metadata/pool/pool_200.py
Normal file
11
metadata/pool/pool_200.py
Normal file
@ -0,0 +1,11 @@
|
||||
POOL_200 = [
|
||||
{
|
||||
"five": [
|
||||
"常驻池"
|
||||
],
|
||||
"four": [],
|
||||
"from": "2020-09-15 06:00:00",
|
||||
"name": "常驻池",
|
||||
"to": "2050-09-15 17:59:59"
|
||||
}
|
||||
]
|
480
metadata/pool/pool_301.py
Normal file
480
metadata/pool/pool_301.py
Normal file
@ -0,0 +1,480 @@
|
||||
POOL_301 = [
|
||||
{
|
||||
"five": [
|
||||
"赛诺",
|
||||
"温迪"
|
||||
],
|
||||
"four": [
|
||||
"久岐忍",
|
||||
"早柚",
|
||||
"坎蒂丝"
|
||||
],
|
||||
"from": "2022-09-28 06:00:00",
|
||||
"name": "劈裁冥昭|杯装之诗",
|
||||
"to": "2022-10-14 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"甘雨",
|
||||
"心海"
|
||||
],
|
||||
"four": [
|
||||
"行秋",
|
||||
"砂糖",
|
||||
"多莉"
|
||||
],
|
||||
"from": "2022-09-09 18:00:00",
|
||||
"name": "浮生孰来|浮岳虹珠",
|
||||
"to": "2022-09-27 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"提纳里",
|
||||
"钟离"
|
||||
],
|
||||
"four": [
|
||||
"云堇",
|
||||
"辛焱",
|
||||
"班尼特"
|
||||
],
|
||||
"from": "2022-08-24 06:00:00",
|
||||
"name": "巡御蘙荟|陵薮市朝",
|
||||
"to": "2022-09-09 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"宵宫"
|
||||
],
|
||||
"four": [
|
||||
"云堇",
|
||||
"辛焱",
|
||||
"班尼特"
|
||||
],
|
||||
"from": "2022-08-02 18:00:00",
|
||||
"name": "焰色天河",
|
||||
"to": "2022-08-23 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"枫原万叶",
|
||||
"可莉"
|
||||
],
|
||||
"four": [
|
||||
"凝光",
|
||||
"鹿野院平藏",
|
||||
"托马"
|
||||
],
|
||||
"from": "2022-07-13 06:00:00",
|
||||
"name": "红叶逐荒波",
|
||||
"to": "2022-08-02 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"荒泷一斗"
|
||||
],
|
||||
"four": [
|
||||
"烟绯",
|
||||
"芭芭拉",
|
||||
"诺艾尔"
|
||||
],
|
||||
"from": "2022-06-21 18:00:00",
|
||||
"name": "鬼门斗宴",
|
||||
"to": "2022-07-12 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"夜兰",
|
||||
"魈"
|
||||
],
|
||||
"four": [
|
||||
"烟绯",
|
||||
"芭芭拉",
|
||||
"诺艾尔"
|
||||
],
|
||||
"from": "2022-05-31 06:00:00",
|
||||
"name": "素霓伣天|烟火之邀",
|
||||
"to": "2022-06-21 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"神里绫华"
|
||||
],
|
||||
"four": [
|
||||
"罗莎莉亚",
|
||||
"早柚",
|
||||
"雷泽"
|
||||
],
|
||||
"from": "2022-04-19 17:59:59",
|
||||
"name": "白鹭之庭",
|
||||
"to": "2022-05-31 05:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"神里绫人",
|
||||
"温迪"
|
||||
],
|
||||
"four": [
|
||||
"香菱",
|
||||
"砂糖",
|
||||
"云堇"
|
||||
],
|
||||
"from": "2022-03-30 06:00:00",
|
||||
"name": "苍流踏花|杯装之诗",
|
||||
"to": "2022-04-19 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"雷电将军",
|
||||
"珊瑚宫心海"
|
||||
],
|
||||
"four": [
|
||||
"辛焱",
|
||||
"九条裟罗",
|
||||
"班尼特"
|
||||
],
|
||||
"from": "2022-03-08 18:00:00",
|
||||
"name": "影寂天下人|浮岳虹珠",
|
||||
"to": "2022-03-29 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"八重神子"
|
||||
],
|
||||
"four": [
|
||||
"菲谢尔",
|
||||
"迪奥娜",
|
||||
"托马"
|
||||
],
|
||||
"from": "2022-02-16 06:00:00",
|
||||
"name": "华紫樱绯",
|
||||
"to": "2022-03-08 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"甘雨",
|
||||
"钟离"
|
||||
],
|
||||
"four": [
|
||||
"行秋",
|
||||
"北斗",
|
||||
"烟绯"
|
||||
],
|
||||
"from": "2022-01-25 18:00:00",
|
||||
"name": "浮生孰来|陵薮市朝",
|
||||
"to": "2022-02-15 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"申鹤",
|
||||
"魈"
|
||||
],
|
||||
"four": [
|
||||
"云堇",
|
||||
"凝光",
|
||||
"重云"
|
||||
],
|
||||
"from": "2022-01-05 06:00:00",
|
||||
"name": "出尘入世|烟火之邀",
|
||||
"to": "2022-01-25 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"荒泷一斗"
|
||||
],
|
||||
"four": [
|
||||
"五郎",
|
||||
"芭芭拉",
|
||||
"香菱"
|
||||
],
|
||||
"from": "2021-12-14 18:00:00",
|
||||
"name": "鬼门斗宴",
|
||||
"to": "2022-01-04 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"阿贝多",
|
||||
"优菈"
|
||||
],
|
||||
"four": [
|
||||
"班尼特",
|
||||
"诺艾尔",
|
||||
"罗莎莉亚"
|
||||
],
|
||||
"from": "2021-11-24 06:00:00",
|
||||
"name": "深秘之息|浪涌之瞬",
|
||||
"to": "2021-12-14 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"胡桃"
|
||||
],
|
||||
"four": [
|
||||
"托马",
|
||||
"迪奥娜",
|
||||
"早柚"
|
||||
],
|
||||
"from": "2021-11-02 18:00:00",
|
||||
"name": "赤团开时",
|
||||
"to": "2021-11-23 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"达达利亚"
|
||||
],
|
||||
"four": [
|
||||
"凝光",
|
||||
"重云",
|
||||
"烟绯"
|
||||
],
|
||||
"from": "2021-10-13 06:00:00",
|
||||
"name": "暂别冬都",
|
||||
"to": "2021-11-02 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"珊瑚宫心海"
|
||||
],
|
||||
"four": [
|
||||
"罗莎莉亚",
|
||||
"北斗",
|
||||
"行秋"
|
||||
],
|
||||
"from": "2021-09-21 18:00:00",
|
||||
"name": "浮岳虹珠",
|
||||
"to": "2021-10-12 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"雷电将军"
|
||||
],
|
||||
"four": [
|
||||
"九条裟罗",
|
||||
"香菱",
|
||||
"砂糖"
|
||||
],
|
||||
"from": "2021-09-01 06:00:00",
|
||||
"name": "影寂天下人",
|
||||
"to": "2021-09-21 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"宵宫"
|
||||
],
|
||||
"four": [
|
||||
"早柚",
|
||||
"迪奥娜",
|
||||
"辛焱"
|
||||
],
|
||||
"from": "2021-08-10 18:00:00",
|
||||
"name": "焰色天河",
|
||||
"to": "2021-08-31 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"神里绫华"
|
||||
],
|
||||
"four": [
|
||||
"凝光",
|
||||
"重云",
|
||||
"烟绯"
|
||||
],
|
||||
"from": "2021-07-21 06:00:00",
|
||||
"name": "白鹭之庭",
|
||||
"to": "2021-08-10 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"枫原万叶"
|
||||
],
|
||||
"four": [
|
||||
"罗莎莉亚",
|
||||
"班尼特",
|
||||
"雷泽"
|
||||
],
|
||||
"from": "2021-06-29 18:00:00",
|
||||
"name": "红叶逐荒波",
|
||||
"to": "2021-07-20 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"可莉"
|
||||
],
|
||||
"four": [
|
||||
"芭芭拉",
|
||||
"砂糖",
|
||||
"菲谢尔"
|
||||
],
|
||||
"from": "2021-06-09 06:00:00",
|
||||
"name": "逃跑的太阳",
|
||||
"to": "2021-06-29 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"优菈"
|
||||
],
|
||||
"four": [
|
||||
"辛焱",
|
||||
"行秋",
|
||||
"北斗"
|
||||
],
|
||||
"from": "2021-05-18 18:00:00",
|
||||
"name": "浪沫的旋舞",
|
||||
"to": "2021-06-08 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"钟离"
|
||||
],
|
||||
"four": [
|
||||
"烟绯",
|
||||
"诺艾尔",
|
||||
"迪奥娜"
|
||||
],
|
||||
"from": "2021-04-28 06:00:00",
|
||||
"name": "陵薮市朝",
|
||||
"to": "2021-05-18 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"达达利亚"
|
||||
],
|
||||
"four": [
|
||||
"罗莎莉亚",
|
||||
"芭芭拉",
|
||||
"菲谢尔"
|
||||
],
|
||||
"from": "2021-04-06 18:00:00",
|
||||
"name": "暂别冬都",
|
||||
"to": "2021-04-27 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"温迪"
|
||||
],
|
||||
"four": [
|
||||
"砂糖",
|
||||
"雷泽",
|
||||
"诺艾尔"
|
||||
],
|
||||
"from": "2021-03-17 06:00:00",
|
||||
"name": "杯装之诗",
|
||||
"to": "2021-04-06 15:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"胡桃"
|
||||
],
|
||||
"four": [
|
||||
"行秋",
|
||||
"香菱",
|
||||
"重云"
|
||||
],
|
||||
"from": "2021-03-02 18:00:00",
|
||||
"name": "赤团开时",
|
||||
"to": "2021-03-16 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"刻晴"
|
||||
],
|
||||
"four": [
|
||||
"凝光",
|
||||
"班尼特",
|
||||
"芭芭拉"
|
||||
],
|
||||
"from": "2021-02-17 18:00:00",
|
||||
"name": "鱼龙灯昼",
|
||||
"to": "2021-03-02 15:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"魈"
|
||||
],
|
||||
"four": [
|
||||
"迪奥娜",
|
||||
"北斗",
|
||||
"辛焱"
|
||||
],
|
||||
"from": "2021-02-03 06:00:00",
|
||||
"name": "烟火之邀",
|
||||
"to": "2021-02-17 15:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"甘雨"
|
||||
],
|
||||
"four": [
|
||||
"香菱",
|
||||
"行秋",
|
||||
"诺艾尔"
|
||||
],
|
||||
"from": "2021-01-12 18:00:00",
|
||||
"name": "浮生孰来",
|
||||
"to": "2021-02-02 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"阿贝多"
|
||||
],
|
||||
"four": [
|
||||
"菲谢尔",
|
||||
"砂糖",
|
||||
"班尼特"
|
||||
],
|
||||
"from": "2020-12-23 06:00:00",
|
||||
"name": "深秘之息",
|
||||
"to": "2021-01-12 15:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"钟离"
|
||||
],
|
||||
"four": [
|
||||
"辛焱",
|
||||
"雷泽",
|
||||
"重云"
|
||||
],
|
||||
"from": "2020-12-01 18:00:00",
|
||||
"name": "陵薮市朝",
|
||||
"to": "2020-12-22 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"达达利亚"
|
||||
],
|
||||
"four": [
|
||||
"迪奥娜",
|
||||
"北斗",
|
||||
"凝光"
|
||||
],
|
||||
"from": "2020-11-11 06:00:00",
|
||||
"name": "暂别冬都",
|
||||
"to": "2020-12-01 15:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"可莉"
|
||||
],
|
||||
"four": [
|
||||
"行秋",
|
||||
"诺艾尔",
|
||||
"砂糖"
|
||||
],
|
||||
"from": "2020-10-20 18:00:00",
|
||||
"name": "闪焰的驻足",
|
||||
"to": "2020-11-10 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"温迪"
|
||||
],
|
||||
"four": [
|
||||
"芭芭拉",
|
||||
"菲谢尔",
|
||||
"香菱"
|
||||
],
|
||||
"from": "2020-9-28 06:00:00",
|
||||
"name": "杯装之诗",
|
||||
"to": "2020-10-18 17:59:59"
|
||||
}
|
||||
]
|
562
metadata/pool/pool_302.py
Normal file
562
metadata/pool/pool_302.py
Normal file
@ -0,0 +1,562 @@
|
||||
POOL_302 = [
|
||||
{
|
||||
"five": [
|
||||
"赤沙之杖",
|
||||
"终末嗟叹之诗"
|
||||
],
|
||||
"four": [
|
||||
"匣里龙吟",
|
||||
"玛海菈的水色",
|
||||
"西风长枪",
|
||||
"祭礼残章",
|
||||
"西风猎弓"
|
||||
],
|
||||
"from": "2022-09-28 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2022-10-14 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"阿莫斯之弓",
|
||||
"不灭月华"
|
||||
],
|
||||
"four": [
|
||||
"祭礼剑",
|
||||
"西风大剑",
|
||||
"匣里灭辰",
|
||||
"昭心",
|
||||
"弓藏"
|
||||
],
|
||||
"from": "2022-09-09 18:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2022-09-27 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"猎人之径",
|
||||
"贯虹之槊"
|
||||
],
|
||||
"four": [
|
||||
"西风剑",
|
||||
"钟剑",
|
||||
"西风长枪",
|
||||
"西风秘典",
|
||||
"绝弦"
|
||||
],
|
||||
"from": "2022-08-24 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2022-09-09 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"飞雷之弦振",
|
||||
"斫峰之刃"
|
||||
],
|
||||
"four": [
|
||||
"暗巷的酒与诗",
|
||||
"暗巷猎手",
|
||||
"笛剑",
|
||||
"祭礼大剑",
|
||||
"匣里灭辰"
|
||||
],
|
||||
"from": "2022-08-02 18:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2022-08-23 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"苍古自由之誓",
|
||||
"四风原典"
|
||||
],
|
||||
"four": [
|
||||
"千岩古剑",
|
||||
"匣里龙吟",
|
||||
"匣里灭辰",
|
||||
"祭礼残章",
|
||||
"绝弦"
|
||||
],
|
||||
"from": "2022-07-13 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2022-08-02 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"赤角石溃杵",
|
||||
"尘世之锁"
|
||||
],
|
||||
"four": [
|
||||
"千岩古剑",
|
||||
"匣里龙吟",
|
||||
"匣里灭辰",
|
||||
"祭礼残章",
|
||||
"绝弦"
|
||||
],
|
||||
"from": "2022-06-21 18:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2022-07-12 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"若水",
|
||||
"和璞鸢"
|
||||
],
|
||||
"four": [
|
||||
"千岩长枪",
|
||||
"祭礼剑",
|
||||
"西风大剑",
|
||||
"昭心",
|
||||
"祭礼弓"
|
||||
],
|
||||
"from": "2022-05-31 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2022-06-21 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"雾切之回光",
|
||||
"无工之剑"
|
||||
],
|
||||
"four": [
|
||||
"西风剑",
|
||||
"钟剑",
|
||||
"西风长枪",
|
||||
"西风秘典",
|
||||
"西风猎弓"
|
||||
],
|
||||
"from": "2022-04-19 17:59:59",
|
||||
"name": "神铸赋形",
|
||||
"to": "2022-05-31 05:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"波乱月白经津",
|
||||
"终末嗟叹之诗"
|
||||
],
|
||||
"four": [
|
||||
"弓藏",
|
||||
"笛剑",
|
||||
"流浪乐章",
|
||||
"匣里灭辰",
|
||||
"祭礼大剑"
|
||||
],
|
||||
"from": "2022-03-30 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2022-04-19 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"薙草之稻光",
|
||||
"不灭月华"
|
||||
],
|
||||
"four": [
|
||||
"恶王丸",
|
||||
"曚云之月",
|
||||
"匣里龙吟",
|
||||
"西风长枪",
|
||||
"祭礼残章"
|
||||
],
|
||||
"from": "2022-03-08 18:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2022-03-29 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"神乐之真意",
|
||||
"磐岩结绿"
|
||||
],
|
||||
"four": [
|
||||
"祭礼剑",
|
||||
"雨裁",
|
||||
"断浪长鳍",
|
||||
"昭心",
|
||||
"绝弦"
|
||||
],
|
||||
"from": "2022-02-16 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2022-03-08 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"贯虹之槊",
|
||||
"阿莫斯之弓"
|
||||
],
|
||||
"four": [
|
||||
"西风剑",
|
||||
"千岩古剑",
|
||||
"匣里灭辰",
|
||||
"西风秘典",
|
||||
"祭礼弓"
|
||||
],
|
||||
"from": "2022-01-25 18:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2022-02-15 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"息灾",
|
||||
"和璞鸢"
|
||||
],
|
||||
"four": [
|
||||
"笛剑",
|
||||
"西风大剑",
|
||||
"千岩长枪",
|
||||
"流浪乐章",
|
||||
"西风猎弓"
|
||||
],
|
||||
"from": "2022-01-05 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2022-01-25 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"赤角石溃杵",
|
||||
"天空之翼"
|
||||
],
|
||||
"four": [
|
||||
"暗巷闪光",
|
||||
"钟剑",
|
||||
"西风长枪",
|
||||
"祭礼残章",
|
||||
"幽夜华尔兹"
|
||||
],
|
||||
"from": "2021-12-14 18:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2022-01-04 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"苍古自由之誓",
|
||||
"松籁响起之时"
|
||||
],
|
||||
"four": [
|
||||
"匣里龙吟",
|
||||
"祭礼大剑",
|
||||
"匣里灭辰",
|
||||
"暗巷的酒与诗",
|
||||
"暗巷猎手"
|
||||
],
|
||||
"from": "2021-11-24 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-12-14 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"护摩之杖",
|
||||
"终末嗟叹之诗"
|
||||
],
|
||||
"four": [
|
||||
"祭礼剑",
|
||||
"雨裁",
|
||||
"断浪长鳍",
|
||||
"流浪乐章",
|
||||
"曚云之月"
|
||||
],
|
||||
"from": "2021-11-02 18:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-11-23 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"冬极白星",
|
||||
"尘世之锁"
|
||||
],
|
||||
"four": [
|
||||
"西风剑",
|
||||
"恶王丸",
|
||||
"西风长枪",
|
||||
"昭心",
|
||||
"弓藏"
|
||||
],
|
||||
"from": "2021-10-13 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-11-02 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"不灭月华",
|
||||
"磐岩结绿"
|
||||
],
|
||||
"four": [
|
||||
"笛剑",
|
||||
"西风大剑",
|
||||
"匣里灭辰",
|
||||
"西风秘典",
|
||||
"绝弦"
|
||||
],
|
||||
"from": "2021-09-21 18:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-10-12 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"薙草之稻光",
|
||||
"无工之剑"
|
||||
],
|
||||
"four": [
|
||||
"匣里龙吟",
|
||||
"钟剑",
|
||||
"西风长枪",
|
||||
"流浪乐章",
|
||||
"祭礼弓"
|
||||
],
|
||||
"from": "2021-09-01 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-09-21 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"飞雷之弦振",
|
||||
"天空之刃"
|
||||
],
|
||||
"four": [
|
||||
"祭礼剑",
|
||||
"雨裁",
|
||||
"匣里灭辰",
|
||||
"祭礼残章",
|
||||
"西风猎弓"
|
||||
],
|
||||
"from": "2021-08-10 18:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-08-31 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"雾切之回光",
|
||||
"天空之脊"
|
||||
],
|
||||
"four": [
|
||||
"西风剑",
|
||||
"祭礼大剑",
|
||||
"西风长枪",
|
||||
"西风秘典",
|
||||
"绝弦"
|
||||
],
|
||||
"from": "2021-07-21 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-08-10 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"苍古自由之誓",
|
||||
"天空之卷"
|
||||
],
|
||||
"four": [
|
||||
"暗巷闪光",
|
||||
"西风大剑",
|
||||
"匣里灭辰",
|
||||
"暗巷的酒与诗",
|
||||
"暗巷猎手"
|
||||
],
|
||||
"from": "2021-06-29 18:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-07-20 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"天空之傲",
|
||||
"四风原典"
|
||||
],
|
||||
"four": [
|
||||
"匣里龙吟",
|
||||
"钟剑",
|
||||
"西风长枪",
|
||||
"流浪乐章",
|
||||
"幽夜华尔兹"
|
||||
],
|
||||
"from": "2021-06-09 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-06-29 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"松籁响起之时",
|
||||
"风鹰剑"
|
||||
],
|
||||
"four": [
|
||||
"祭礼剑",
|
||||
"雨裁",
|
||||
"匣里灭辰",
|
||||
"祭礼残章",
|
||||
"弓藏"
|
||||
],
|
||||
"from": "2021-05-18 18:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-06-08 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"斫峰之刃",
|
||||
"尘世之锁"
|
||||
],
|
||||
"four": [
|
||||
"笛剑",
|
||||
"千岩古剑",
|
||||
"祭礼弓",
|
||||
"昭心",
|
||||
"千岩长枪"
|
||||
],
|
||||
"from": "2021-04-28 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-05-18 17:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"天空之翼",
|
||||
"四风原典"
|
||||
],
|
||||
"four": [
|
||||
"西风剑",
|
||||
"祭礼大剑",
|
||||
"暗巷猎手",
|
||||
"西风秘典",
|
||||
"西风长枪"
|
||||
],
|
||||
"from": "2021-04-06 18:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-04-27 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"终末嗟叹之诗",
|
||||
"天空之刃"
|
||||
],
|
||||
"four": [
|
||||
"暗巷闪光",
|
||||
"西风大剑",
|
||||
"西风猎弓",
|
||||
"暗巷的酒与诗",
|
||||
"匣里灭辰"
|
||||
],
|
||||
"from": "2021-03-17 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-04-06 15:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"护摩之杖",
|
||||
"狼的末路"
|
||||
],
|
||||
"four": [
|
||||
"匣里龙吟",
|
||||
"千岩古剑",
|
||||
"祭礼弓",
|
||||
"流浪乐章",
|
||||
"千岩长枪"
|
||||
],
|
||||
"from": "2021-02-23 18:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-03-16 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"磐岩结绿",
|
||||
"和璞鸢"
|
||||
],
|
||||
"four": [
|
||||
"笛剑",
|
||||
"祭礼大剑",
|
||||
"弓藏",
|
||||
"昭心",
|
||||
"西风长枪"
|
||||
],
|
||||
"from": "2021-02-03 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-02-23 15:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"阿莫斯之弓",
|
||||
"天空之傲"
|
||||
],
|
||||
"four": [
|
||||
"祭礼剑",
|
||||
"钟剑",
|
||||
"匣里灭辰",
|
||||
"昭心",
|
||||
"西风猎弓"
|
||||
],
|
||||
"from": "2021-01-12 18:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-02-02 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"斫峰之刃",
|
||||
"天空之卷"
|
||||
],
|
||||
"four": [
|
||||
"西风剑",
|
||||
"西风大剑",
|
||||
"西风长枪",
|
||||
"祭礼残章",
|
||||
"绝弦"
|
||||
],
|
||||
"from": "2020-12-23 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2021-01-12 15:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"贯虹之槊",
|
||||
"无工之剑"
|
||||
],
|
||||
"four": [
|
||||
"匣里龙吟",
|
||||
"钟剑",
|
||||
"西风秘典",
|
||||
"西风猎弓",
|
||||
"匣里灭辰"
|
||||
],
|
||||
"from": "2020-12-01 18:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2020-12-22 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"天空之翼",
|
||||
"尘世之锁"
|
||||
],
|
||||
"four": [
|
||||
"笛剑",
|
||||
"雨裁",
|
||||
"昭心",
|
||||
"弓藏",
|
||||
"西风长枪"
|
||||
],
|
||||
"from": "2020-11-11 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2020-12-01 15:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"四风原典",
|
||||
"狼的末路"
|
||||
],
|
||||
"four": [
|
||||
"祭礼剑",
|
||||
"祭礼大剑",
|
||||
"祭礼残章",
|
||||
"祭礼弓",
|
||||
"匣里灭辰"
|
||||
],
|
||||
"from": "2020-10-20 18:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2020-11-10 14:59:59"
|
||||
},
|
||||
{
|
||||
"five": [
|
||||
"风鹰剑",
|
||||
"阿莫斯之弓"
|
||||
],
|
||||
"four": [
|
||||
"祭礼剑",
|
||||
"祭礼大剑",
|
||||
"祭礼残章",
|
||||
"祭礼弓",
|
||||
"匣里灭辰"
|
||||
],
|
||||
"from": "2020-09-28 06:00:00",
|
||||
"name": "神铸赋形",
|
||||
"to": "2020-10-18 17:59:59"
|
||||
}
|
||||
]
|
531
modules/apihelper/gacha_log.py
Normal file
531
modules/apihelper/gacha_log.py
Normal file
@ -0,0 +1,531 @@
|
||||
import contextlib
|
||||
import datetime
|
||||
import json
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import List, Dict, Tuple, Optional, Union
|
||||
|
||||
import aiofiles
|
||||
from genshin import Client, InvalidAuthkey
|
||||
from genshin.models import BannerType
|
||||
from pydantic import BaseModel
|
||||
|
||||
from core.base.assets import AssetsService
|
||||
from metadata.pool.pool import get_pool_by_id
|
||||
from metadata.shortname import roleToId, weaponToId
|
||||
from utils.const import PROJECT_ROOT
|
||||
|
||||
GACHA_LOG_PATH = PROJECT_ROOT.joinpath("data", "apihelper", "gacha_log")
|
||||
GACHA_LOG_PATH.mkdir(parents=True, exist_ok=True)
|
||||
GACHA_TYPE_LIST = {
|
||||
BannerType.NOVICE: '新手祈愿',
|
||||
BannerType.PERMANENT: '常驻祈愿',
|
||||
BannerType.WEAPON: '武器祈愿',
|
||||
BannerType.CHARACTER1: '角色祈愿',
|
||||
BannerType.CHARACTER2: '角色祈愿'
|
||||
}
|
||||
|
||||
|
||||
class FiveStarItem(BaseModel):
|
||||
name: str
|
||||
icon: str
|
||||
count: int
|
||||
type: str
|
||||
isUp: bool
|
||||
isBig: bool
|
||||
time: datetime.datetime
|
||||
|
||||
|
||||
class FourStarItem(BaseModel):
|
||||
name: str
|
||||
icon: str
|
||||
count: int
|
||||
type: str
|
||||
time: datetime.datetime
|
||||
|
||||
|
||||
class GachaItem(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
gacha_type: str
|
||||
item_type: str
|
||||
rank_type: str
|
||||
time: datetime.datetime
|
||||
|
||||
|
||||
class GachaLogInfo(BaseModel):
|
||||
user_id: str
|
||||
uid: str
|
||||
update_time: datetime.datetime
|
||||
item_list: Dict[str, List[GachaItem]] = {
|
||||
'角色祈愿': [],
|
||||
'武器祈愿': [],
|
||||
'常驻祈愿': [],
|
||||
'新手祈愿': [],
|
||||
}
|
||||
|
||||
|
||||
class Pool:
|
||||
def __init__(self, five: List[str], four: List[str], name: str, to: str, **kwargs):
|
||||
self.five = five
|
||||
self.real_name = name
|
||||
self.name = "、".join(self.five)
|
||||
self.four = four
|
||||
self.from_ = kwargs.get("from")
|
||||
self.to = to
|
||||
self.from_time = datetime.datetime.strptime(self.from_, "%Y-%m-%d %H:%M:%S")
|
||||
self.to_time = datetime.datetime.strptime(self.to, "%Y-%m-%d %H:%M:%S")
|
||||
self.start = self.from_time
|
||||
self.start_init = False
|
||||
self.end = self.to_time
|
||||
self.dict = {}
|
||||
self.count = 0
|
||||
|
||||
def parse(self, item: Union[FiveStarItem, FourStarItem]):
|
||||
if self.from_time <= item.time <= self.to_time:
|
||||
if self.dict.get(item.name):
|
||||
self.dict[item.name]["count"] += 1
|
||||
else:
|
||||
self.dict[item.name] = {
|
||||
"name": item.name,
|
||||
"icon": item.icon,
|
||||
"count": 1,
|
||||
"rank_type": 5 if isinstance(item, FiveStarItem) else 4,
|
||||
}
|
||||
|
||||
def count_item(self, item: List[GachaItem]):
|
||||
for i in item:
|
||||
if self.from_time <= i.time <= self.to_time:
|
||||
self.count += 1
|
||||
if not self.start_init:
|
||||
self.start = i.time
|
||||
self.end = i.time
|
||||
|
||||
def to_list(self):
|
||||
return list(self.dict.values())
|
||||
|
||||
|
||||
class GachaLog:
|
||||
@staticmethod
|
||||
async def load_json(path):
|
||||
async with aiofiles.open(path, 'r', encoding='utf-8') as f:
|
||||
return json.loads(await f.read())
|
||||
|
||||
@staticmethod
|
||||
async def save_json(path, data):
|
||||
async with aiofiles.open(path, 'w', encoding='utf-8') as f:
|
||||
if isinstance(data, dict):
|
||||
return await f.write(json.dumps(data, ensure_ascii=False, indent=4))
|
||||
await f.write(data)
|
||||
|
||||
@staticmethod
|
||||
async def load_history_info(user_id: str, uid: str) -> Tuple[GachaLogInfo, bool]:
|
||||
"""读取历史抽卡记录数据
|
||||
:param user_id: 用户id
|
||||
:param uid: 原神uid
|
||||
:return: 抽卡记录数据
|
||||
"""
|
||||
file_path = GACHA_LOG_PATH / f'{user_id}-{uid}.json'
|
||||
if file_path.exists():
|
||||
return GachaLogInfo.parse_obj(await GachaLog.load_json(file_path)), True
|
||||
else:
|
||||
return GachaLogInfo(user_id=user_id,
|
||||
uid=uid,
|
||||
update_time=datetime.datetime.now()), False
|
||||
|
||||
@staticmethod
|
||||
async def save_gacha_log_info(user_id: str, uid: str, info: GachaLogInfo):
|
||||
"""保存抽卡记录数据
|
||||
:param user_id: 用户id
|
||||
:param uid: 原神uid
|
||||
:param info: 抽卡记录数据
|
||||
"""
|
||||
save_path = GACHA_LOG_PATH / f'{user_id}-{uid}.json'
|
||||
save_path_bak = GACHA_LOG_PATH / f'{user_id}-{uid}.json.bak'
|
||||
# 将旧数据备份一次
|
||||
with contextlib.suppress(PermissionError):
|
||||
if save_path.exists():
|
||||
if save_path_bak.exists():
|
||||
save_path_bak.unlink()
|
||||
save_path.rename(save_path.parent / f'{save_path.name}.bak')
|
||||
# 写入数据
|
||||
await GachaLog.save_json(save_path, info.json())
|
||||
|
||||
@staticmethod
|
||||
async def gacha_log_to_uigf(user_id: str, uid: str) -> Tuple[bool, str, Optional[Path]]:
|
||||
"""抽卡日记转换为 UIGF 格式
|
||||
:param user_id: 用户ID
|
||||
:param uid: 游戏UID
|
||||
:return: 转换是否成功、转换信息、UIGF文件目录
|
||||
"""
|
||||
data, state = await GachaLog.load_history_info(user_id, uid)
|
||||
if not state:
|
||||
return False, f'UID{uid} 还没有导入任何抽卡记录数据。', None
|
||||
save_path = GACHA_LOG_PATH / f'{user_id}-{uid}-uigf.json'
|
||||
uigf_dict = {
|
||||
'info': {
|
||||
'uid': uid,
|
||||
'lang': 'zh-cn',
|
||||
'export_time': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'export_timestamp': int(time.time()),
|
||||
'export_app': 'TGPaimonBot',
|
||||
'export_app_version': "v3",
|
||||
'uigf_version': 'v2.2'
|
||||
},
|
||||
'list': []
|
||||
}
|
||||
for items in data.item_list.values():
|
||||
for item in items:
|
||||
uigf_dict['list'].append({
|
||||
'gacha_type': item.gacha_type,
|
||||
'item_id': '',
|
||||
'count': '1',
|
||||
'time': item.time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'name': item.name,
|
||||
'item_type': item.item_type,
|
||||
'rank_type': item.rank_type,
|
||||
'id': item.id,
|
||||
'uigf_gacha_type': item.gacha_type
|
||||
})
|
||||
await GachaLog.save_json(save_path, uigf_dict)
|
||||
return True, '', save_path
|
||||
|
||||
@staticmethod
|
||||
async def import_gacha_log_data(user_id: int, data: dict):
|
||||
new_num = 0
|
||||
try:
|
||||
uid = data['info']['uid']
|
||||
gacha_log, _ = await GachaLog.load_history_info(str(user_id), uid)
|
||||
for item in data['list']:
|
||||
pool_name = GACHA_TYPE_LIST[BannerType(int(item['gacha_type']))]
|
||||
item_info = GachaItem.parse_obj(item)
|
||||
if item_info not in gacha_log.item_list[pool_name]:
|
||||
gacha_log.item_list[pool_name].append(item_info)
|
||||
new_num += 1
|
||||
for i in gacha_log.item_list.values():
|
||||
i.sort(key=lambda x: (x.time, x.id))
|
||||
gacha_log.update_time = datetime.datetime.now()
|
||||
await GachaLog.save_gacha_log_info(str(user_id), uid, gacha_log)
|
||||
return "导入完成,本次没有新增数据" if new_num == 0 else f"导入完成,本次共新增{new_num}条抽卡记录"
|
||||
except Exception:
|
||||
return "导入失败,数据格式错误"
|
||||
|
||||
@staticmethod
|
||||
async def get_gacha_log_data(user_id: int, client: Client, authkey: str) -> str:
|
||||
"""
|
||||
使用authkey获取抽卡记录数据,并合并旧数据
|
||||
:param user_id: 用户id
|
||||
:param client: genshin client
|
||||
:param authkey: authkey
|
||||
:return: 更新结果
|
||||
"""
|
||||
new_num = 0
|
||||
gacha_log, _ = await GachaLog.load_history_info(str(user_id), str(client.uid))
|
||||
try:
|
||||
for pool_id, pool_name in GACHA_TYPE_LIST.items():
|
||||
async for data in client.wish_history(pool_id, authkey=authkey):
|
||||
item = GachaItem(
|
||||
id=str(data.id),
|
||||
name=data.name,
|
||||
gacha_type=str(data.banner_type.value),
|
||||
item_type=data.type,
|
||||
rank_type=str(data.rarity),
|
||||
time=datetime.datetime(data.time.year,
|
||||
data.time.month,
|
||||
data.time.day,
|
||||
data.time.hour,
|
||||
data.time.minute,
|
||||
data.time.second)
|
||||
)
|
||||
|
||||
if item not in gacha_log.item_list[pool_name]:
|
||||
gacha_log.item_list[pool_name].append(item)
|
||||
new_num += 1
|
||||
except InvalidAuthkey:
|
||||
return "更新数据失败,authkey 无效"
|
||||
for i in gacha_log.item_list.values():
|
||||
i.sort(key=lambda x: (x.time, x.id))
|
||||
gacha_log.update_time = datetime.datetime.now()
|
||||
await GachaLog.save_gacha_log_info(str(user_id), str(client.uid), gacha_log)
|
||||
return '更新完成,本次没有新增数据' if new_num == 0 else f'更新完成,本次共新增{new_num}条抽卡记录'
|
||||
|
||||
@staticmethod
|
||||
def check_avatar_up(name: str, gacha_time: datetime.datetime) -> bool:
|
||||
if name in {'莫娜', '七七', '迪卢克', '琴'}:
|
||||
return False
|
||||
elif name == "刻晴":
|
||||
start_time = datetime.datetime.strptime("2021-02-17 18:00:00", "%Y-%m-%d %H:%M:%S")
|
||||
end_time = datetime.datetime.strptime("2021-03-02 15:59:59", "%Y-%m-%d %H:%M:%S")
|
||||
if not (start_time < gacha_time < end_time):
|
||||
return False
|
||||
elif name == "提纳里":
|
||||
start_time = datetime.datetime.strptime("2022-08-24 06:00:00", "%Y-%m-%d %H:%M:%S")
|
||||
end_time = datetime.datetime.strptime("2022-09-09 17:59:59", "%Y-%m-%d %H:%M:%S")
|
||||
if not (start_time < gacha_time < end_time):
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
async def get_all_5_star_items(data: List[GachaItem], assets: AssetsService, pool_name: str = "角色祈愿"):
|
||||
"""
|
||||
获取所有5星角色
|
||||
:param data: 抽卡记录
|
||||
:param assets: 资源服务
|
||||
:param pool_name: 池子名称
|
||||
:return: 5星角色列表
|
||||
"""
|
||||
count = 0
|
||||
result = []
|
||||
for item in data:
|
||||
count += 1
|
||||
if item.rank_type == '5':
|
||||
if item.item_type == "角色" and pool_name in {"角色祈愿", "常驻祈愿"}:
|
||||
result.append(
|
||||
FiveStarItem(
|
||||
name=item.name,
|
||||
icon=(await assets.avatar(roleToId(item.name)).icon()).as_uri(),
|
||||
count=count,
|
||||
type="角色",
|
||||
isUp=GachaLog.check_avatar_up(item.name, item.time) if pool_name == "角色祈愿" else False,
|
||||
isBig=(not result[-1].isUp) if result and pool_name == "角色祈愿" else False,
|
||||
time=item.time,
|
||||
)
|
||||
)
|
||||
elif item.item_type == "武器" and pool_name in {"武器祈愿", "常驻祈愿"}:
|
||||
result.append(
|
||||
FiveStarItem(
|
||||
name=item.name,
|
||||
icon=(await assets.weapon(weaponToId(item.name)).icon()).as_uri(),
|
||||
count=count,
|
||||
type="武器",
|
||||
isUp=False,
|
||||
isBig=False,
|
||||
time=item.time,
|
||||
)
|
||||
)
|
||||
count = 0
|
||||
result.reverse()
|
||||
return result, count
|
||||
|
||||
@staticmethod
|
||||
async def get_all_4_star_items(data: List[GachaItem], assets: AssetsService):
|
||||
"""
|
||||
获取 no_fout_star
|
||||
:param data: 抽卡记录
|
||||
:param assets: 资源服务
|
||||
:return: no_fout_star
|
||||
"""
|
||||
count = 0
|
||||
result = []
|
||||
for item in data:
|
||||
count += 1
|
||||
if item.rank_type == '4':
|
||||
if item.item_type == "角色":
|
||||
result.append(
|
||||
FourStarItem(
|
||||
name=item.name,
|
||||
icon=(await assets.avatar(roleToId(item.name)).icon()).as_uri(),
|
||||
count=count,
|
||||
type="角色",
|
||||
time=item.time,
|
||||
)
|
||||
)
|
||||
elif item.item_type == "武器":
|
||||
result.append(
|
||||
FourStarItem(
|
||||
name=item.name,
|
||||
icon=(await assets.weapon(weaponToId(item.name)).icon()).as_uri(),
|
||||
count=count,
|
||||
type="武器",
|
||||
time=item.time,
|
||||
)
|
||||
)
|
||||
count = 0
|
||||
result.reverse()
|
||||
return result, count
|
||||
|
||||
@staticmethod
|
||||
def get_301_pool_data(total: int,
|
||||
all_five: List[FiveStarItem],
|
||||
no_five_star: int,
|
||||
no_four_star: int):
|
||||
# 总共五星
|
||||
five_star = len(all_five)
|
||||
five_star_up = len([i for i in all_five if i.isUp])
|
||||
five_star_big = len([i for i in all_five if i.isBig])
|
||||
# 五星平均
|
||||
five_star_avg = round(total / five_star, 2) if five_star != 0 else 0
|
||||
# 小保底不歪
|
||||
small_protect = round((five_star_up - five_star_big) / (five_star - five_star_big) * 100.0, 1) if \
|
||||
five_star - five_star_big != 0 else "0.0"
|
||||
# 五星常驻
|
||||
five_star_const = five_star - five_star_up
|
||||
# UP 平均
|
||||
up_avg = round(total / five_star_up, 2) if five_star_up != 0 else 0
|
||||
# UP 花费原石
|
||||
up_cost = sum(i.count * 160 for i in all_five if i.isUp)
|
||||
up_cost = f"{round(up_cost / 10000, 2)}w" if up_cost >= 10000 else up_cost
|
||||
return [
|
||||
[
|
||||
{"num": no_five_star, "unit": "抽", "lable": "未出五星"},
|
||||
{"num": five_star, "unit": "个", "lable": "五星"},
|
||||
{"num": five_star_avg, "unit": "抽", "lable": "五星平均"},
|
||||
{"num": small_protect, "unit": "%", "lable": "小保底不歪"},
|
||||
],
|
||||
[
|
||||
{"num": no_four_star, "unit": "抽", "lable": "未出四星"},
|
||||
{"num": five_star_const, "unit": "个", "lable": "五星常驻"},
|
||||
{"num": up_avg, "unit": "抽", "lable": "UP平均"},
|
||||
{"num": up_cost, "unit": "", "lable": "UP花费原石"},
|
||||
]
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def get_200_pool_data(total: int, all_five: List[FiveStarItem], all_four: List[FourStarItem],
|
||||
no_five_star: int, no_four_star: int):
|
||||
# 总共五星
|
||||
five_star = len(all_five)
|
||||
# 五星平均
|
||||
five_star_avg = round(total / five_star, 2) if five_star != 0 else 0
|
||||
# 五星武器
|
||||
five_star_weapon = len([i for i in all_five if i.type == "武器"])
|
||||
# 总共四星
|
||||
four_star = len(all_four)
|
||||
# 四星平均
|
||||
four_star_avg = round(total / four_star, 2) if four_star != 0 else 0
|
||||
# 四星最多
|
||||
four_star_name_list = [i.name for i in all_four]
|
||||
four_star_max = max(four_star_name_list, key=four_star_name_list.count)
|
||||
four_star_max_count = four_star_name_list.count(four_star_max)
|
||||
return [
|
||||
[
|
||||
{"num": no_five_star, "unit": "抽", "lable": "未出五星"},
|
||||
{"num": five_star, "unit": "个", "lable": "五星"},
|
||||
{"num": five_star_avg, "unit": "抽", "lable": "五星平均"},
|
||||
{"num": five_star_weapon, "unit": "个", "lable": "五星武器"},
|
||||
],
|
||||
[
|
||||
{"num": no_four_star, "unit": "抽", "lable": "未出四星"},
|
||||
{"num": four_star, "unit": "个", "lable": "四星"},
|
||||
{"num": four_star_avg, "unit": "抽", "lable": "四星平均"},
|
||||
{"num": four_star_max_count, "unit": four_star_max, "lable": "四星最多"},
|
||||
]
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def get_302_pool_data(total: int, all_five: List[FiveStarItem], all_four: List[FourStarItem],
|
||||
no_five_star: int, no_four_star: int):
|
||||
# 总共五星
|
||||
five_star = len(all_five)
|
||||
# 五星平均
|
||||
five_star_avg = round(total / five_star, 2) if five_star != 0 else 0
|
||||
# 四星武器
|
||||
four_star_weapon = len([i for i in all_four if i.type == "武器"])
|
||||
# 总共四星
|
||||
four_star = len(all_four)
|
||||
# 四星平均
|
||||
four_star_avg = round(total / four_star, 2) if four_star != 0 else 0
|
||||
# 四星最多
|
||||
four_star_name_list = [i.name for i in all_four]
|
||||
four_star_max = max(four_star_name_list, key=four_star_name_list.count)
|
||||
four_star_max_count = four_star_name_list.count(four_star_max)
|
||||
return [
|
||||
[
|
||||
{"num": no_five_star, "unit": "抽", "lable": "未出五星"},
|
||||
{"num": five_star, "unit": "个", "lable": "五星"},
|
||||
{"num": five_star_avg, "unit": "抽", "lable": "五星平均"},
|
||||
{"num": four_star_weapon, "unit": "个", "lable": "四星武器"},
|
||||
],
|
||||
[
|
||||
{"num": no_four_star, "unit": "抽", "lable": "未出四星"},
|
||||
{"num": four_star, "unit": "个", "lable": "四星"},
|
||||
{"num": four_star_avg, "unit": "抽", "lable": "四星平均"},
|
||||
{"num": four_star_max_count, "unit": four_star_max, "lable": "四星最多"},
|
||||
]
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
async def get_analysis(user_id: int, client: Client, pool: BannerType, assets: AssetsService):
|
||||
"""
|
||||
获取抽卡记录分析数据
|
||||
:param user_id: 用户id
|
||||
:param client: genshin client
|
||||
:param pool: 池子类型
|
||||
:param assets: 资源服务
|
||||
:return: 分析数据
|
||||
"""
|
||||
gacha_log, status = await GachaLog.load_history_info(str(user_id), str(client.uid))
|
||||
if not status:
|
||||
return "获取数据失败,未找到抽卡记录"
|
||||
pool_name = GACHA_TYPE_LIST[pool]
|
||||
data = gacha_log.item_list[pool_name]
|
||||
total = len(data)
|
||||
if total == 0:
|
||||
return "获取数据失败,未找到抽卡记录"
|
||||
all_five, no_five_star = await GachaLog.get_all_5_star_items(data, assets, pool_name)
|
||||
all_four, no_four_star = await GachaLog.get_all_4_star_items(data, assets)
|
||||
summon_data = None
|
||||
if pool == BannerType.CHARACTER1:
|
||||
summon_data = GachaLog.get_301_pool_data(total, all_five, no_five_star, no_four_star)
|
||||
elif pool == BannerType.WEAPON:
|
||||
summon_data = GachaLog.get_302_pool_data(total, all_five, all_four, no_five_star, no_four_star)
|
||||
elif pool == BannerType.PERMANENT:
|
||||
summon_data = GachaLog.get_200_pool_data(total, all_five, all_four, no_five_star, no_four_star)
|
||||
last_time = data[0].time.strftime("%Y-%m-%d %H:%M")
|
||||
first_time = data[-1].time.strftime("%Y-%m-%d %H:%M")
|
||||
return {
|
||||
"uid": client.uid,
|
||||
"allNum": total,
|
||||
"type": pool.value,
|
||||
"typeName": pool_name,
|
||||
"line": summon_data,
|
||||
"firstTime": first_time,
|
||||
"lastTime": last_time,
|
||||
"fiveLog": all_five,
|
||||
"fourLog": all_four[:18],
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
async def get_pool_analysis(user_id: int, client: Client, pool: BannerType, assets: AssetsService, group: bool):
|
||||
"""
|
||||
获取抽卡记录分析数据
|
||||
:param user_id: 用户id
|
||||
:param client: genshin client
|
||||
:param pool: 池子类型
|
||||
:param assets: 资源服务
|
||||
:param group: 是否群组
|
||||
:return: 分析数据
|
||||
"""
|
||||
gacha_log, status = await GachaLog.load_history_info(str(user_id), str(client.uid))
|
||||
if not status:
|
||||
return "获取数据失败,未找到抽卡记录"
|
||||
pool_name = GACHA_TYPE_LIST[pool]
|
||||
data = gacha_log.item_list[pool_name]
|
||||
total = len(data)
|
||||
if total == 0:
|
||||
return "获取数据失败,未找到抽卡记录"
|
||||
all_five, _ = await GachaLog.get_all_5_star_items(data, assets, pool_name)
|
||||
all_four, _ = await GachaLog.get_all_4_star_items(data, assets)
|
||||
pool_data = []
|
||||
up_pool_data = [Pool(**i) for i in get_pool_by_id(pool.value)]
|
||||
for up_pool in up_pool_data:
|
||||
for item in all_five:
|
||||
up_pool.parse(item)
|
||||
for item in all_four:
|
||||
up_pool.parse(item)
|
||||
up_pool.count_item(data)
|
||||
for up_pool in up_pool_data:
|
||||
pool_data.append({
|
||||
"count": up_pool.count,
|
||||
"list": up_pool.to_list(),
|
||||
"name": up_pool.name,
|
||||
"start": up_pool.start.strftime("%Y-%m-%d"),
|
||||
"end": up_pool.end.strftime("%Y-%m-%d"),
|
||||
})
|
||||
pool_data = [i for i in pool_data if i["count"] > 0]
|
||||
return {
|
||||
"uid": client.uid,
|
||||
"typeName": pool_name,
|
||||
"pool": pool_data[:6] if group else pool_data,
|
||||
"hasMore": len(pool_data) > 6,
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
from .gacha import Gacha
|
||||
|
||||
|
||||
class GachaPlugins(Gacha):
|
||||
pass
|
229
plugins/genshin/gacha/gacha_log.py
Normal file
229
plugins/genshin/gacha/gacha_log.py
Normal file
@ -0,0 +1,229 @@
|
||||
import json
|
||||
import os
|
||||
from io import BytesIO
|
||||
|
||||
from genshin.models import BannerType
|
||||
from pyppeteer import launch
|
||||
from telegram import Update, User
|
||||
from telegram.constants import ChatAction
|
||||
from telegram.ext import CallbackContext, CommandHandler, MessageHandler, filters, ConversationHandler
|
||||
|
||||
from core.base.assets import AssetsService
|
||||
from core.baseplugin import BasePlugin
|
||||
from core.cookies.error import CookiesNotFoundError
|
||||
from core.plugin import Plugin, handler, conversation
|
||||
from core.template import TemplateService
|
||||
from core.user.error import UserNotFoundError
|
||||
from modules.apihelper.gacha_log import GachaLog as GachaLogService
|
||||
from utils.bot import get_all_args
|
||||
from utils.decorators.error import error_callable
|
||||
from utils.decorators.restricts import restricts
|
||||
from utils.helpers import get_genshin_client
|
||||
from utils.log import logger
|
||||
|
||||
INPUT_URL, INPUT_FILE = 10100, 10101
|
||||
|
||||
|
||||
class GachaLog(Plugin.Conversation, BasePlugin.Conversation):
|
||||
""" 抽卡记录导入/导出/分析"""
|
||||
|
||||
def __init__(self, template_service: TemplateService = None, assets: AssetsService = None):
|
||||
self.template_service = template_service
|
||||
self.browser: launch = None
|
||||
self.current_dir = os.getcwd()
|
||||
self.resources_dir = os.path.join(self.current_dir, "resources")
|
||||
self.character_gacha_card = {}
|
||||
self.user_time = {}
|
||||
self.assets_service = assets
|
||||
|
||||
@staticmethod
|
||||
def from_url_get_authkey(url: str) -> str:
|
||||
"""从 UEL 解析 authkey
|
||||
:param url: URL
|
||||
:return: authkey
|
||||
"""
|
||||
try:
|
||||
return url.split("authkey=")[1].split("&")[0]
|
||||
except IndexError:
|
||||
return url
|
||||
|
||||
@staticmethod
|
||||
async def _refresh_user_data(user: User, data: dict = None, authkey: str = None) -> str:
|
||||
"""刷新用户数据
|
||||
:param user: 用户
|
||||
:param data: 数据
|
||||
:param authkey: 认证密钥
|
||||
:return: 返回信息
|
||||
"""
|
||||
try:
|
||||
logger.debug("尝试获取已绑定的原神账号")
|
||||
client = await get_genshin_client(user.id)
|
||||
if authkey:
|
||||
return await GachaLogService.get_gacha_log_data(user.id, client, authkey)
|
||||
if data:
|
||||
return await GachaLogService.import_gacha_log_data(user.id, data)
|
||||
except (UserNotFoundError, CookiesNotFoundError):
|
||||
logger.info(f"未查询到用户({user.full_name} {user.id}) 所绑定的账号信息")
|
||||
return "未查询到您所绑定的账号信息,请先私聊派蒙绑定账号"
|
||||
|
||||
@conversation.entry_point
|
||||
@handler(CommandHandler, command="gacha_log_refresh", filters=filters.ChatType.PRIVATE, block=True)
|
||||
@handler(MessageHandler, filters=filters.Regex("^更新抽卡记录(.*)") & filters.ChatType.PRIVATE, block=True)
|
||||
@restricts()
|
||||
@error_callable
|
||||
async def command_start(self, update: Update, context: CallbackContext) -> int:
|
||||
message = update.effective_message
|
||||
user = update.effective_user
|
||||
args = get_all_args(context)
|
||||
if not args:
|
||||
await message.reply_text("请发送从游戏中获取到的抽卡记录链接\n\n"
|
||||
"获取抽卡记录链接教程:https://paimon.moe/wish/import")
|
||||
return INPUT_URL
|
||||
authkey = self.from_url_get_authkey(args[0])
|
||||
data = await self._refresh_user_data(user, authkey=authkey)
|
||||
await message.reply_text(data)
|
||||
|
||||
@conversation.state(state=INPUT_URL)
|
||||
@handler.message(filters=filters.TEXT & ~filters.COMMAND,
|
||||
block=True)
|
||||
@restricts()
|
||||
@error_callable
|
||||
async def import_data_from_url(self, update: Update, _: CallbackContext) -> int:
|
||||
message = update.effective_message
|
||||
user = update.effective_user
|
||||
authkey = self.from_url_get_authkey(message.text)
|
||||
reply = await message.reply_text("正在从米哈游服务器获取数据,请稍后")
|
||||
text = await self._refresh_user_data(user, authkey=authkey)
|
||||
await reply.edit_text(text)
|
||||
return ConversationHandler.END
|
||||
|
||||
@handler(CommandHandler, command="gacha_log_import", filters=filters.ChatType.PRIVATE, block=True)
|
||||
@handler(MessageHandler, filters=filters.Regex("^导入抽卡记录(.*)") & filters.ChatType.PRIVATE, block=True)
|
||||
@restricts()
|
||||
@error_callable
|
||||
async def command_start_import(self, update: Update, _: CallbackContext) -> None:
|
||||
message = update.effective_message
|
||||
user = update.effective_user
|
||||
if message.reply_to_message:
|
||||
document = message.reply_to_message.document
|
||||
else:
|
||||
document = message.document
|
||||
if not document:
|
||||
await message.reply_text("请回复符合 UIGF 标准的抽卡记录文件")
|
||||
return
|
||||
if not document.file_name.endswith(".json"):
|
||||
await message.reply_text("文件格式错误,请发送符合 UIGF 标准的抽卡记录文件")
|
||||
return
|
||||
if document.file_size > 50 * 1024 * 1024:
|
||||
await message.reply_text("文件过大,请发送小于 50MB 的文件")
|
||||
return
|
||||
try:
|
||||
data = BytesIO()
|
||||
await (await document.get_file()).download(out=data)
|
||||
# bytesio to json
|
||||
data = data.getvalue().decode("utf-8")
|
||||
data = json.loads(data)
|
||||
except Exception as exc:
|
||||
logger.error(f"文件解析失败:{repr(exc)}")
|
||||
await message.reply_text("文件解析失败,请检查文件是否符合 UIGF 标准")
|
||||
return
|
||||
reply = await message.reply_text("文件解析成功,正在导入数据")
|
||||
try:
|
||||
text = await self._refresh_user_data(user, data=data)
|
||||
except Exception as exc:
|
||||
logger.error(f"文件解析失败:{repr(exc)}")
|
||||
await reply.edit_text("文件解析失败,请检查文件是否符合 UIGF 标准")
|
||||
return
|
||||
await reply.edit_text(text)
|
||||
return
|
||||
|
||||
@handler(CommandHandler, command="gacha_log_export", filters=filters.ChatType.PRIVATE, block=True)
|
||||
@handler(MessageHandler, filters=filters.Regex("^导出抽卡记录(.*)") & filters.ChatType.PRIVATE, block=True)
|
||||
@restricts()
|
||||
@error_callable
|
||||
async def command_start_export(self, update: Update, _: CallbackContext) -> None:
|
||||
message = update.effective_message
|
||||
user = update.effective_user
|
||||
try:
|
||||
client = await get_genshin_client(user.id)
|
||||
state, text, path = await GachaLogService.gacha_log_to_uigf(str(user.id), str(client.uid))
|
||||
if state:
|
||||
await message.reply_document(document=open(path, "rb+"), caption="抽卡记录导出文件")
|
||||
else:
|
||||
await message.reply_text(text)
|
||||
except (UserNotFoundError, CookiesNotFoundError):
|
||||
logger.info(f"未查询到用户({user.full_name} {user.id}) 所绑定的账号信息")
|
||||
await message.reply_text("未查询到您所绑定的账号信息,请先私聊派蒙绑定账号")
|
||||
return
|
||||
|
||||
@handler(CommandHandler, command="gacha_log", block=True)
|
||||
@handler(MessageHandler, filters=filters.Regex("^抽卡记录(.*)"), block=True)
|
||||
@restricts()
|
||||
@error_callable
|
||||
async def command_start_analysis(self, update: Update, context: CallbackContext) -> None:
|
||||
message = update.effective_message
|
||||
user = update.effective_user
|
||||
pool_type = BannerType.CHARACTER1
|
||||
if args := get_all_args(context):
|
||||
if "武器" in args:
|
||||
pool_type = BannerType.WEAPON
|
||||
elif "常驻" in args:
|
||||
pool_type = BannerType.STANDARD
|
||||
logger.info(f"用户 {user.full_name}[{user.id}] 抽卡记录命令请求 || 参数 {pool_type.name}")
|
||||
try:
|
||||
client = await get_genshin_client(user.id)
|
||||
data = await GachaLogService.get_analysis(user.id, client, pool_type, self.assets_service)
|
||||
if isinstance(data, str):
|
||||
reply_message = await message.reply_text(data)
|
||||
else:
|
||||
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
|
||||
png_data = await self.template_service.render('genshin/gacha_log', "gacha_log.html", data,
|
||||
full_page=True, query_selector=".body_box")
|
||||
reply_message = await message.reply_photo(png_data)
|
||||
if filters.ChatType.GROUPS.filter(message):
|
||||
self._add_delete_message_job(context, reply_message.chat_id, reply_message.message_id, 300)
|
||||
self._add_delete_message_job(context, message.chat_id, message.message_id, 300)
|
||||
except (UserNotFoundError, CookiesNotFoundError):
|
||||
logger.info(f"未查询到用户({user.full_name} {user.id}) 所绑定的账号信息")
|
||||
await message.reply_text("未查询到您所绑定的账号信息,请先私聊派蒙绑定账号")
|
||||
return
|
||||
|
||||
@handler(CommandHandler, command="gacha_count", block=True)
|
||||
@handler(MessageHandler, filters=filters.Regex("^抽卡统计(.*)"), block=True)
|
||||
@restricts()
|
||||
@error_callable
|
||||
async def command_start_count(self, update: Update, context: CallbackContext) -> None:
|
||||
message = update.effective_message
|
||||
user = update.effective_user
|
||||
pool_type = BannerType.CHARACTER1
|
||||
if args := get_all_args(context):
|
||||
if "武器" in args:
|
||||
pool_type = BannerType.WEAPON
|
||||
elif "常驻" in args:
|
||||
pool_type = BannerType.STANDARD
|
||||
logger.info(f"用户 {user.full_name}[{user.id}] 抽卡统计命令请求 || 参数 {pool_type.name}")
|
||||
try:
|
||||
client = await get_genshin_client(user.id)
|
||||
group = filters.ChatType.GROUPS.filter(message)
|
||||
data = await GachaLogService.get_pool_analysis(user.id, client, pool_type, self.assets_service, group)
|
||||
if isinstance(data, str):
|
||||
reply_message = await message.reply_text(data)
|
||||
else:
|
||||
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
|
||||
document = False
|
||||
if data["hasMore"] and not group:
|
||||
document = True
|
||||
data["hasMore"] = False
|
||||
png_data = await self.template_service.render('genshin/gacha_count', "gacha_count.html", data,
|
||||
full_page=True, query_selector=".body_box")
|
||||
if document:
|
||||
reply_message = await message.reply_document(png_data, filename="抽卡统计.png")
|
||||
else:
|
||||
reply_message = await message.reply_photo(png_data)
|
||||
if filters.ChatType.GROUPS.filter(message):
|
||||
self._add_delete_message_job(context, reply_message.chat_id, reply_message.message_id, 300)
|
||||
self._add_delete_message_job(context, message.chat_id, message.message_id, 300)
|
||||
except (UserNotFoundError, CookiesNotFoundError):
|
||||
logger.info(f"未查询到用户({user.full_name} {user.id}) 所绑定的账号信息")
|
||||
await message.reply_text("未查询到您所绑定的账号信息,请先私聊派蒙绑定账号")
|
||||
return
|
47
resources/genshin/gacha_count/example.html
Normal file
47
resources/genshin/gacha_count/example.html
Normal file
@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
|
||||
<link rel="shortcut icon" href="#"/>
|
||||
<link rel="stylesheet" type="text/css" href="gacha_count.css"/>
|
||||
<link rel="preload" href="./../../fonts/汉仪文黑-85W.ttf" as="font">
|
||||
<link rel="preload" href="./../../fonts/tttgbnumber.ttf" as="font">
|
||||
<link rel="preload" href="./../abyss/background/roleStarBg5.png" as="image">
|
||||
<link rel="preload" href="./../abyss/background/roleStarBg4.png" as="image">
|
||||
<style>
|
||||
.head_box {
|
||||
background-position-x: 42px;
|
||||
background: #fff url(../gacha_log/img/提纳里.png) no-repeat;
|
||||
background-size: auto 101%;
|
||||
}
|
||||
</style>
|
||||
<title></title>
|
||||
</head>
|
||||
<body id="container" class="body_box">
|
||||
<div class="container">
|
||||
<div class="head_box">
|
||||
<div class="id_text">ID: 10001</div>
|
||||
<h2 class="day_text">抽卡统计-角色祈愿</h2>
|
||||
<img class="genshin_logo" src="./../../bot/help/background/genshin.png"/>
|
||||
</div>
|
||||
<div class="pool_box">
|
||||
<div class="title_box">
|
||||
<div class="name_box">
|
||||
<div class="title"><h2>「枫原万叶、可莉」</h2></div>
|
||||
<span class="label label_301">98抽</span>
|
||||
</div>
|
||||
<span class="date">2022-08-02 - 2022-08-02</span>
|
||||
</div>
|
||||
<div class="list_box">
|
||||
<div class="item">
|
||||
<div class="bg5"></div>
|
||||
<span class="num life5">20</span>
|
||||
<img class="role_img" src=""/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hasMore">*完整数据请私聊查看</div>
|
||||
<div class="logo">Template By Yunzai-Bot</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
214
resources/genshin/gacha_count/gacha_count.css
Normal file
214
resources/genshin/gacha_count/gacha_count.css
Normal file
@ -0,0 +1,214 @@
|
||||
@font-face {
|
||||
font-family: "tttgbnumber";
|
||||
src: url("./../../fonts/tttgbnumber.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "HYWenHei-55W";
|
||||
src: url("./../../fonts/汉仪文黑-85W.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 16px;
|
||||
width: 530px;
|
||||
color: #1e1f20;
|
||||
transform: scale(1.5);
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 530px;
|
||||
padding: 20px 15px 10px 15px;
|
||||
background-color: #f5f6fb;
|
||||
}
|
||||
|
||||
.head_box {
|
||||
border-radius: 15px;
|
||||
font-family: tttgbnumber, serif;
|
||||
padding: 10px 20px;
|
||||
position: relative;
|
||||
box-shadow: 0 5px 10px 0 rgb(0 0 0 / 15%);
|
||||
|
||||
}
|
||||
|
||||
.head_box .id_text {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.head_box .day_text {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.head_box .genshin_logo {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 15px;
|
||||
width: 97px;
|
||||
}
|
||||
|
||||
.base_info {
|
||||
position: relative;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.uid {
|
||||
font-family: tttgbnumber, serif;
|
||||
}
|
||||
|
||||
.pool_box {
|
||||
font-family: HYWenHei-55W, serif;
|
||||
border-radius: 12px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
padding: 10px 5px 5px 5px;
|
||||
background: #fff;
|
||||
box-shadow: 0 5px 10px 0 rgb(0 0 0 / 15%);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.title_box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.title {
|
||||
white-space: nowrap;
|
||||
max-width: 210px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.name_box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.title_box .date {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.list_box {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.item {
|
||||
margin: 0 0 10px 10px;
|
||||
border-radius: 7px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 6px 0 rgb(132 93 90 / 30%);
|
||||
height: 70px;
|
||||
width: 70px;
|
||||
background: #e9e5dc;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.item .role_img {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
background-size: 100%;
|
||||
background-repeat: no-repeat;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
/* filter: contrast(95%); */
|
||||
}
|
||||
|
||||
.item .num {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 9;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
border-radius: 3px;
|
||||
padding: 1px 5px;
|
||||
background: rgb(0 0 0 / 50%);
|
||||
font-family: "tttgbnumber", serif;
|
||||
}
|
||||
|
||||
.label_301 {
|
||||
background-color: rgb(235 106 75);
|
||||
}
|
||||
|
||||
.label_302 {
|
||||
background-color: #e69449;
|
||||
}
|
||||
|
||||
.label_200 {
|
||||
background-color: #757cc8;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #fff;
|
||||
border-radius: 10px;
|
||||
font-size: 16px;
|
||||
padding: 2px 7px;
|
||||
vertical-align: 2px;
|
||||
}
|
||||
|
||||
.bg5 {
|
||||
background-image: url(./../abyss/background/roleStarBg5.png);
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
/* filter: brightness(1.1); */
|
||||
background-size: 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.bg4 {
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
background-image: url(./../abyss/background/roleStarBg4.png);
|
||||
background-size: 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.list_box .item .life1 {
|
||||
background-color: #62a8ea;
|
||||
}
|
||||
|
||||
.list_box .item .life2 {
|
||||
background-color: #62a8ea;
|
||||
}
|
||||
|
||||
.list_box .item .life3 {
|
||||
background-color: #45b97c;
|
||||
}
|
||||
|
||||
.list_box .item .life4 {
|
||||
background-color: #45b97c;
|
||||
}
|
||||
|
||||
.list_box .item .life5 {
|
||||
background-color: #ff5722;
|
||||
}
|
||||
|
||||
.list_box .item .life6 {
|
||||
background-color: #ff5722;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: 14px;
|
||||
font-family: "tttgbnumber", serif;
|
||||
text-align: center;
|
||||
color: #7994a7;
|
||||
}
|
||||
|
||||
.hasMore {
|
||||
font-size: 12px;
|
||||
margin: -6px 0 10px 6px;
|
||||
color: #7f858a;
|
||||
}
|
55
resources/genshin/gacha_count/gacha_count.html
Normal file
55
resources/genshin/gacha_count/gacha_count.html
Normal file
@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
|
||||
<link rel="shortcut icon" href="#"/>
|
||||
<link rel="stylesheet" type="text/css" href="gacha_count.css"/>
|
||||
<link rel="preload" href="./../../fonts/汉仪文黑-85W.ttf" as="font">
|
||||
<link rel="preload" href="./../../fonts/tttgbnumber.ttf" as="font">
|
||||
<link rel="preload" href="./../abyss/background/roleStarBg5.png" as="image">
|
||||
<link rel="preload" href="./../abyss/background/roleStarBg4.png" as="image">
|
||||
<style>
|
||||
.head_box {
|
||||
background-position-x: 42px;
|
||||
background: #fff url(../gacha_log/img/提纳里.png) no-repeat;
|
||||
background-size: auto 101%;
|
||||
}
|
||||
</style>
|
||||
<title></title>
|
||||
</head>
|
||||
<body id="container" class="body_box">
|
||||
<div class="container">
|
||||
<div class="head_box">
|
||||
<div class="id_text">ID: {{uid}}</div>
|
||||
<h2 class="day_text">抽卡统计-{{typeName}}</h2>
|
||||
<img class="genshin_logo" src="./../../bot/help/background/genshin.png" alt=""/>
|
||||
</div>
|
||||
{% for val in pool %}
|
||||
<div class="pool_box">
|
||||
<div class="title_box">
|
||||
<div class="name_box">
|
||||
<div class="title"><h2>「{{val.name}}」</h2></div>
|
||||
<span class="label label_301">{{val.count}}抽</span>
|
||||
</div>
|
||||
{% if typeName != "常驻祈愿" %}
|
||||
<span class="date">{{val.start}} - {{val.end}}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="list_box">
|
||||
{% for v in val.list %}
|
||||
<div class="item">
|
||||
<div class="bg{{v.rank_type}}"></div>
|
||||
<span class="num {% if v.count>=5 and v.rank_type == 5 %}life5{% endif %}">{{v.count}}</span>
|
||||
<img class="role_img" src="{{ v.icon }}" alt=""/>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% if hasMore %}
|
||||
<div class="hasMore">*完整数据请私聊查看</div>
|
||||
{% endif %}
|
||||
<div class="logo">Template By Yunzai-Bot</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
77
resources/genshin/gacha_log/example.html
Normal file
77
resources/genshin/gacha_log/example.html
Normal file
@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
|
||||
<link rel="shortcut icon" href="#"/>
|
||||
<link rel="stylesheet" type="text/css" href="gacha_log.css"/>
|
||||
<link rel="preload" href="./../../fonts/tttgbnumber.ttf" as="font">
|
||||
<link rel="preload" href="./img/提纳里.png" as="image">
|
||||
<link rel="preload" href="./../abyss/background/roleStarBg5.png" as="image">
|
||||
<style>
|
||||
.head_box {
|
||||
background-position-x: 42px;
|
||||
background: #fff url(./img/提纳里.png) no-repeat;
|
||||
background-size: auto 101%;
|
||||
}
|
||||
</style>
|
||||
<title></title>
|
||||
</head>
|
||||
<body id="container" class="body_box">
|
||||
<div class="container">
|
||||
<div class="info_box">
|
||||
|
||||
<div class="head_box">
|
||||
<div class="id_text">
|
||||
ID: 10001
|
||||
</div>
|
||||
<h2 class="day_text">
|
||||
81抽
|
||||
<span class="label label_301">角色祈愿池</span>
|
||||
</h2>
|
||||
<img class="genshin_logo" src="./../../bot/help/background/genshin.png" alt=""/>
|
||||
</div>
|
||||
|
||||
<div class="data_box">
|
||||
<div class="tab_lable">数据总览</div>
|
||||
<div class="data_line">
|
||||
<div class="data_line_item">
|
||||
<div class="num">1<span class="unit">抽</span></div>
|
||||
<div class="lable">未出五星</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="line_box">
|
||||
<span class="line"></span>
|
||||
<span class="text">五星历史 2022-10-07 01:10 ~ 2022-10-07 23:10</span>
|
||||
<span class="line"></span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card_list">
|
||||
<div class="item star5">
|
||||
<span class="minimum">UP</span>
|
||||
<img class="role" src="" alt=""/>
|
||||
<!-- <div class="num">{{val.num}}</div>-->
|
||||
<div class="num_name">80</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="line_box">
|
||||
<span class="line"></span>
|
||||
<span class="text">四星最近历史</span>
|
||||
<span class="line"></span>
|
||||
</div>
|
||||
|
||||
<div class="card_list">
|
||||
<div class="item star4">
|
||||
<img class="role" src="" alt=""/>
|
||||
<!-- <div class="num">{{val.num}}</div>-->
|
||||
<div class="num_name">10</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="logo"> Template By Yunzai-Bot</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
341
resources/genshin/gacha_log/gacha_log.css
Normal file
341
resources/genshin/gacha_log/gacha_log.css
Normal file
@ -0,0 +1,341 @@
|
||||
@font-face {
|
||||
font-family: "tttgbnumber";
|
||||
src: url("./../../fonts/tttgbnumber.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 18px;
|
||||
color: #1e1f20;
|
||||
font-family: PingFangSC-Medium, PingFang SC, sans-serif;
|
||||
transform: scale(1.5);
|
||||
transform-origin: 0 0;
|
||||
width: 510px;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 510px;
|
||||
padding: 20px 15px 10px 15px;
|
||||
background-color: #f5f6fb;
|
||||
}
|
||||
|
||||
.head_box {
|
||||
border-radius: 15px;
|
||||
font-family: tttgbnumber, sans-serif;
|
||||
padding: 10px 20px;
|
||||
position: relative;
|
||||
box-shadow: 0 5px 10px 0 rgb(0 0 0 / 15%);
|
||||
}
|
||||
|
||||
.head_box .id_text {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.head_box .day_text {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.head_box .genshin_logo {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 15px;
|
||||
width: 97px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: 12px;
|
||||
font-family: "tttgbnumber", serif;
|
||||
text-align: center;
|
||||
color: #7994a7;
|
||||
position: relative;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.data_box {
|
||||
border-radius: 15px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 10px;
|
||||
padding: 20px 0 5px 10px;
|
||||
background: #fff;
|
||||
box-shadow: 0 5px 10px 0 rgb(0 0 0 / 15%);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab_lable {
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
left: -8px;
|
||||
background: #d4b98c;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
padding: 3px 10px;
|
||||
border-radius: 15px 0 15px 15px;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.data_line {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-bottom: 14px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.data_line_item {
|
||||
width: 100px;
|
||||
text-align: center;
|
||||
|
||||
/* margin: 0 20px; */
|
||||
}
|
||||
|
||||
.num {
|
||||
font-family: tttgbnumber, serif;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.num .unit {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.data_box .lable {
|
||||
font-size: 14px;
|
||||
color: #7f858a;
|
||||
line-height: 1;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.info_box_border {
|
||||
border-radius: 15px;
|
||||
|
||||
/* margin-top: 20px; */
|
||||
margin-bottom: 20px;
|
||||
padding: 6px 0 5px 10px;
|
||||
background: #fff;
|
||||
box-shadow: 0 5px 10px 0 rgb(0 0 0 / 15%);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.card_list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.card_list .item {
|
||||
margin: 0 8px 10px 0;
|
||||
border-radius: 7px;
|
||||
box-shadow: 0 2px 6px 0 rgb(132 93 90 / 30%);
|
||||
height: 90px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: #e7e5d9;
|
||||
}
|
||||
|
||||
.card_list .item img {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
border-radius: 7px 7px 20px 0;
|
||||
}
|
||||
|
||||
.card_list .item.star5 img {
|
||||
background-image: url(./../abyss/background/roleStarBg5.png);
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
/* filter: brightness(1.1); */
|
||||
background-size: 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.card_list .item.star4 img {
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
background-image: url(./../abyss/background/roleStarBg4.png);
|
||||
background-size: 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.card_list .item .num {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 9;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
border-radius: 3px;
|
||||
padding: 1px 5px;
|
||||
background: rgb(0 0 0 / 50%);
|
||||
font-family: "tttgbnumber", serif;
|
||||
}
|
||||
|
||||
.card_list .item .name,
|
||||
.card_list .item .num_name {
|
||||
position: absolute;
|
||||
top: 71px;
|
||||
left: 0;
|
||||
z-index: 9;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
height: 16px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.card_list .item .num_name {
|
||||
font-family: "tttgbnumber", serif;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.base_info {
|
||||
position: relative;
|
||||
padding-left: 10px;
|
||||
margin: 5px 10px;
|
||||
}
|
||||
|
||||
.uid::before {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
width: 5px;
|
||||
height: 24px;
|
||||
border-radius: 1px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background: #d3bc8d;
|
||||
}
|
||||
|
||||
.label_301 {
|
||||
background-color: rgb(235 106 75);
|
||||
}
|
||||
|
||||
.label_302 {
|
||||
background-color: #e69449;
|
||||
}
|
||||
|
||||
.label_200 {
|
||||
background-color: #757cc8;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #fff;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
padding: 2px 7px;
|
||||
vertical-align: 2px;
|
||||
}
|
||||
|
||||
.ritem {
|
||||
display: flex;
|
||||
font-size: 12px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.info_role {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 0 0 5px 9px;
|
||||
}
|
||||
|
||||
.ritem .role {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #ffb285;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.ritem .weapon_box {
|
||||
overflow: hidden;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.ritem .weapon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #ffb285;
|
||||
border-radius: 100%;
|
||||
transform: scale(1.5);
|
||||
-webkit-transform: scale(1.5);
|
||||
|
||||
}
|
||||
|
||||
.ritem .role_text {
|
||||
margin: 2px 3px 0 2px;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.ritem .role_name {
|
||||
width: 24px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ritem .role_num {
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.line_box {
|
||||
height: 32px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: #7d7d7d;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.line_box .line {
|
||||
height: 2px;
|
||||
flex-grow: 1;
|
||||
background-color: #ebebeb;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.red {
|
||||
color: #f21000;
|
||||
}
|
||||
|
||||
.orange {
|
||||
color: #ff8d00;
|
||||
}
|
||||
|
||||
.green {
|
||||
color: #12d88c;
|
||||
}
|
||||
|
||||
.blue {
|
||||
color: #4169e1;
|
||||
}
|
||||
|
||||
.purple {
|
||||
color: #7500ff;
|
||||
}
|
||||
|
||||
.minimum {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 9;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
border-radius: 3px;
|
||||
padding: 1px 3px;
|
||||
background-color: rgb(0 0 0 / 80%);
|
||||
font-family: "tttgbnumber", serif;
|
||||
}
|
||||
|
||||
.hasMore {
|
||||
font-size: 12px;
|
||||
margin: 6px 0;
|
||||
color: #7f858a;
|
||||
}
|
88
resources/genshin/gacha_log/gacha_log.html
Normal file
88
resources/genshin/gacha_log/gacha_log.html
Normal file
@ -0,0 +1,88 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
|
||||
<link rel="shortcut icon" href="#"/>
|
||||
<link rel="stylesheet" type="text/css" href="gacha_log.css"/>
|
||||
<link rel="preload" href="./../../fonts/tttgbnumber.ttf" as="font">
|
||||
<link rel="preload" href="./img/提纳里.png" as="image">
|
||||
<link rel="preload" href="./../abyss/background/roleStarBg5.png" as="image">
|
||||
<link rel="preload" href="./../abyss/background/roleStarBg4.png" as="image">
|
||||
<style>
|
||||
.head_box {
|
||||
background-position-x: 42px;
|
||||
background: #fff url(./img/提纳里.png) no-repeat;
|
||||
background-size: auto 101%;
|
||||
}
|
||||
</style>
|
||||
<title></title>
|
||||
</head>
|
||||
<body id="container" class="body_box">
|
||||
<div class="container">
|
||||
<div class="info_box">
|
||||
|
||||
<div class="head_box">
|
||||
<div class="id_text">
|
||||
ID: {{ uid }}
|
||||
</div>
|
||||
<h2 class="day_text">
|
||||
{{ allNum }}抽
|
||||
<span class="label label_{{type}}">{{ typeName }}池</span>
|
||||
</h2>
|
||||
<img class="genshin_logo" src="./../../bot/help/background/genshin.png" alt=""/>
|
||||
</div>
|
||||
|
||||
<div class="data_box">
|
||||
<div class="tab_lable">数据总览</div>
|
||||
{% for val in line %}
|
||||
<div class="data_line">
|
||||
{% for item in val %}
|
||||
<div class="data_line_item">
|
||||
<div class="num">{{item.num}}<span class="unit">{{item.unit}}</span></div>
|
||||
<div class="lable">{{item.lable}}</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="line_box">
|
||||
<span class="line"></span>
|
||||
<span class="text">五星历史 {{firstTime}} ~ {{lastTime}}</span>
|
||||
<span class="line"></span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card_list">
|
||||
{% for val in fiveLog %}
|
||||
<div class="item star5">
|
||||
{% if val.isUp %}
|
||||
<span class="minimum">UP</span>
|
||||
{% endif %}
|
||||
<img class="role" src="{{ val.icon }}" alt=""/>
|
||||
<!-- <div class="num">{{val.num}}</div>-->
|
||||
<div class="num_name">{{ val.count }}</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="line_box">
|
||||
<span class="line"></span>
|
||||
<span class="text">四星最近历史</span>
|
||||
<span class="line"></span>
|
||||
</div>
|
||||
|
||||
<div class="card_list">
|
||||
{% for val in fourLog %}
|
||||
<div class="item star4">
|
||||
<img class="role" src="{{ val.icon }}" alt=""/>
|
||||
<!-- <div class="num">{{val.num}}</div>-->
|
||||
<div class="num_name">{{ val.count }}</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="logo"> Template By Yunzai-Bot</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
BIN
resources/genshin/gacha_log/img/提纳里.png
Normal file
BIN
resources/genshin/gacha_log/img/提纳里.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
Loading…
Reference in New Issue
Block a user