feature(Splatoon): 新增splatoon3地图查询功能

This commit is contained in:
ClovertaTheTrilobita 2026-02-01 23:34:20 +02:00
parent f60d008241
commit 4f7a3776f3
22 changed files with 1577 additions and 4 deletions

View file

@ -117,4 +117,11 @@ codeforces:
# 查询codeforces比赛列表
# 但如果仅查询比赛列表或个人rating本内容可以不用配置
key: "<KEY>"
secret: "<KEY>"
secret: "<KEY>"
splatoon:
v3:
schedules: "https://splatoon3.ink/data/schedules.json"
v2:
schedules: "https://splatoon2.ink/data/schedules.json"

View file

@ -0,0 +1,104 @@
from datetime import datetime
from os import getcwd
from src.clover_splatoon.stages import RegularScheduleItem, BankaraScheduleItem, CoopScheduleItem
from src.configs.path_config import temp_path
from nonebot_plugin_htmlrender import template_to_pic
from playwright.async_api import async_playwright
from src.clover_splatoon.splatoon_data import stage3
async def save_img(data: bytes):
"""
保存日报图片
:param data:
:return:
"""
file_path = temp_path + f"{datetime.now().date()}splatoon.png"
with open(file_path, "wb") as file:
file.write(data)
async def generate_splatoon_report_image(regular: RegularScheduleItem, bankara: BankaraScheduleItem, coop: CoopScheduleItem):
now = datetime.now()
week = { # noqa: RUF012
0: "周一",
1: "周二",
2: "周三",
3: "周四",
4: "周五",
5: "周六",
6: "周日",
}
regular_list = [
[
stage3[str(regular.regularMatchSetting.vsStages[0].vsStageId)]["cname"],
regular.regularMatchSetting.vsStages[0].image.url
],
[
stage3[str(regular.regularMatchSetting.vsStages[1].vsStageId)]["cname"],
regular.regularMatchSetting.vsStages[1].image.url
]
]
bankara_list_challenge = [
[
stage3[str(bankara.bankaraMatchSettings[0].vsStages[0].vsStageId)]["cname"],
bankara.bankaraMatchSettings[0].vsStages[0].image.url
],
[
stage3[str(bankara.bankaraMatchSettings[0].vsStages[1].vsStageId)]["cname"],
bankara.bankaraMatchSettings[0].vsStages[1].image.url
]
]
bankara_list_open = [
[
stage3[str(bankara.bankaraMatchSettings[1].vsStages[0].vsStageId)]["cname"],
bankara.bankaraMatchSettings[1].vsStages[0].image.url
],
[
stage3[str(bankara.bankaraMatchSettings[1].vsStages[1].vsStageId)]["cname"],
bankara.bankaraMatchSettings[1].vsStages[1].image.url
]
]
coop_list = [
[
stage3[coop.setting.coopStage.name]["name"],
coop.setting.coopStage.thumbnailImage.url
],
[
wp.image.url for wp in coop.setting.weapons
]
]
data = {
"data_regular": regular_list,
"data_bankara_challenge": bankara_list_challenge,
"data_bankara_open": bankara_list_open,
"data_coop": coop_list,
"week": week[now.weekday()],
"date": now.date(),
"time": datetime.now().strftime("%H:%M"),
"full_show": True,
}
async with async_playwright() as p:
browser = await p.chromium.launch()
image_bytes = await template_to_pic(
template_path=getcwd() + "/src/clover_splatoon/resources",
template_name="main.html",
templates={"data": data},
pages={
"viewport": {"width": 578, "height": 1885},
"base_url": f"file://{getcwd()}",
},
wait=2,
)
await save_img(image_bytes)
await browser.close()
return image_bytes

View file

@ -0,0 +1,441 @@
body {
position: absolute;
left: -8px;
top: -8px;
}
@font-face {
font-family: "Noto Sans SC B";
src: url("./res/font/NotoSansSC-Bold.otf") format("opentype");
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Noto Sans SC";
src: url("./res/font/NotoSansSC-Regular.otf") format("opentype");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "SSFangTangTi";
src: url("./res/font/SSFangTangTi.ttf");
}
.wrapper {
/* height: 1885px; */
width: 578px;
background-color: #2B2A2A;
position: relative;
padding: 15px;
/* box-sizing: border-box; */
}
.main {
/* height: 1860px; */
width: 555px;
background-color: #57595B;
position: relative;
border-radius: 10px;
padding: 10px;
background-image: repeating-linear-gradient(
45deg,
rgba(255, 255, 255, 0.12) 0px,
rgba(255, 255, 255, 0.12) 30px,
rgba(0, 0, 0, 0) 30px,
rgba(0, 0, 0, 0) 60px
);
}
.top-border {
display: flex;
}
.zx-img {
height: 155px;
}
.top-title {
position: relative;
width: 322px;
}
.zx-title {
font-family: "SSFangTangTi";
color: #EEEEEE;
font-size: 72px;
position: absolute;
top: -73px;
left: 10px;
text-shadow: 4px 4px 8px #2f1d70;
}
.zx-paragraph {
font-family: "SSFangTangTi";
color: #EEEEEE;
font-size: 42px;
}
.zx-tip {
color: #EEEEEE;
font-family: "Noto Sans SC B";
font-size: 33px;
position: absolute;
top: 73px;
left: 20px;
}
.zx-title-num{
color: #E4FF30;
font-size: 1.3em; /* 比父元素大一些;也可以写 28px 这种绝对值 */
font-weight: 700; /* 可选:更醒目 */
line-height: 1; /* 可选:避免数字把行高撑得太怪 */
}
.top-date {
background-color: #E4FF30;
border-radius: 10px;
height: 108px;
width: 120px;
margin-top: 30px;
margin-left: 35px;
position: relative;
box-shadow: 4px 4px 8px #000000;
}
.top-date-week {
color: #4D2FB2;
font-size: 35px;
font-family: "Noto Sans SC B";
position: absolute;
left: 26px;
top: -34px;
}
.top-date-date {
color: #E4FF30;
font-family: "Noto Sans SC B";
font-size: 12px;
background-color: #4D2FB2;
margin-top: 50px;
height: 25px;
display: flex;
align-items: center;
justify-content: center;
}
.top-date-cn {
font-family: "Noto Sans SC B";
color: #4D2FB2;
font-size: 15px;
display: flex;
align-items: center;
justify-content: center;
line-height: 0;
}
.match-img{
border-radius: 20px;
border: #E4FF30 8px solid;
margin-top: 8px;
margin-bottom: 12px;
/*height: 100px;*/
/*box-shadow: 2px 2px 4px #000000;*/
}
.one-border {
display: flex;
height: 320px;
margin-top: 50px;
font-family: "Noto Sans SC";
}
.moyu-border {
font-family: "Noto Sans SC";
height: 240px;
padding: 15px 10px;
border-radius: 10px;
border: #2B2A2A 3px solid;
width: 157px;
position: relative;
}
.moyu-title {
border: #2B2A2A 2px solid;
position: absolute;
background-color: #EDE4C2;
align-items: center;
justify-content: center;
border-radius: 10px;
color: #15173D;
padding: 5px 10px;
font-size: 23px;
font-family: "Noto Sans SC B";
top: -19px;
left: 37px;
display: flex;
}
.moyu-title-sub {
border: #2B2A2A 2px solid;
position: absolute;
background-color: #EDE4C2;
align-items: center;
justify-content: center;
border-radius: 10px;
color: #15173D;
padding: 5px 10px;
font-size: 23px;
font-family: "Noto Sans SC B";
top: -19px;
right: 37px;
display: flex;
}
.title-img {
height: 30px;
width: 30px;
margin-right: 5px;
}
.title-img-salmon {
height: 25px;
width: 77px;
margin-right: 5px;
}
.title-img-weapon {
height: 30px;
width: 30px;
margin-right: 2px;
}
.moyu-inner {
display: flex;
line-height: 15px;
font-size: 13px;
}
.moyu-day {
width: 37px;
display: flex;
align-items: center;
justify-content: center;
}
.moyu-day-name {
color: #2B2A2A;
background-color: #daf8ff;
display: flex;
align-items: center;
justify-content: center;
width: 55px;
}
.bili-border {
font-family: "Noto Sans SC";
border: #2B2A2A 3px solid;
height: 240px;
margin-left: 15px;
padding: 15px 10px 15px 40px;
border-radius: 10px;
width: 300px;
position: relative;
font-size: 13px;
}
.bili-text {
display: flex;
align-items: center;
line-height: 5px;
margin-top: 7px;
margin-bottom: 6px;
}
.hot-text {
background-color: #b5deef;
height: 17px;
width: 17px;
color: white;
display: flex;
align-items: center;
justify-content: center;
margin-right: 5px;
border-radius: 2px;
}
.two-border {
border: #2B2A2A 3px solid;
width: 512px;
height: 370px;
border-radius: 10px;
position: relative;
padding: 17px;
font-family: "Noto Sans SC";
background-color: #57595B;
}
.two-border-border {
float: left;
}
.anime-border {
height: 170px;
width: 105px;
font-size: 10px;
font-size: 13px;
text-align: center;
line-height: 3px;
float: left;
margin: 8px 10px;
line-height: 15px;
}
.anime-text {
overflow: hidden;
margin-top: 3px;
height: 48px;
}
.anime-img {
height: 130px;
width: 90px;
}
.three-border-regular {
border: #2B2A2A 3px solid;
width: 552px;
border-radius: 10px;
position: relative;
/* float: left; */
padding: 17px;
font-family: "Noto Sans SC";
margin-top: 46px;
background-color: #2c860a;
font-size: 15px;
box-sizing: border-box;
background-image:
radial-gradient(circle at 10% 12%, rgba(0,0,0,.22) 0 70px, transparent 72px),
radial-gradient(circle at 52% 18%, rgba(0,0,0,.16) 0 55px, transparent 57px),
radial-gradient(circle at 85% 20%, rgba(0,0,0,.18) 0 60px, transparent 62px),
radial-gradient(circle at 40% 55%, rgba(0,0,0,.20) 0 85px, transparent 87px),
radial-gradient(circle at 92% 52%, rgba(0,0,0,.15) 0 50px, transparent 52px),
radial-gradient(circle at 22% 88%, rgba(0,0,0,.17) 0 65px, transparent 67px),
radial-gradient(circle at 82% 88%, rgba(0,0,0,.19) 0 78px, transparent 80px);
}
.three-border-bankara {
border: #2B2A2A 3px solid;
width: 552px;
border-radius: 10px;
position: relative;
/* float: left; */
padding: 17px;
font-family: "Noto Sans SC";
margin-top: 46px;
background-color: #e44501;
font-size: 15px;
box-sizing: border-box;
background-image:
radial-gradient(circle at 10% 12%, rgba(0,0,0,.22) 0 70px, transparent 72px),
radial-gradient(circle at 28% 30%, rgba(0,0,0,.14) 0 45px, transparent 47px),
radial-gradient(circle at 52% 18%, rgba(0,0,0,.16) 0 55px, transparent 57px),
radial-gradient(circle at 40% 55%, rgba(0,0,0,.20) 0 85px, transparent 87px),
radial-gradient(circle at 92% 52%, rgba(0,0,0,.15) 0 50px, transparent 52px),
radial-gradient(circle at 55% 84%, rgba(0,0,0,.12) 0 48px, transparent 50px),
radial-gradient(circle at 82% 88%, rgba(0,0,0,.19) 0 78px, transparent 80px);
}
.three-border-coop {
border: #2B2A2A 3px solid;
width: 552px;
border-radius: 10px;
position: relative;
/* float: left; */
padding: 17px;
font-family: "Noto Sans SC";
margin-top: 46px;
background-color: #b19500;
font-size: 15px;
box-sizing: border-box;
background-image:
radial-gradient(circle at 15% 20%, rgba(0,0,0,.25) 0 70px, transparent 72px),
radial-gradient(circle at 80% 30%, rgba(0,0,0,.18) 0 55px, transparent 57px),
radial-gradient(circle at 70% 85%, rgba(0,0,0,.22) 0 80px, transparent 82px);
}
.three-border {
border: #2B2A2A 3px solid;
width: 552px;
border-radius: 10px;
position: relative;
/* float: left; */
padding: 17px;
font-family: "Noto Sans SC";
margin-top: 46px;
background-color: #e44501;
font-size: 15px;
box-sizing: border-box;
}
.four-border {
border: #2B2A2A 3px solid;
width: 512px;
border-radius: 10px;
position: relative;
/* float: left; */
padding: 17px;
font-family: "Noto Sans SC";
margin-top: 46px;
background-color: #57595B;
font-size: 15px;
}
.five-border {
border: #2B2A2A 3px solid;
width: 520px;
border-radius: 10px;
position: relative;
/* float: left; */
padding: 13px;
font-family: "Noto Sans SC";
margin-top: 46px;
font-size: 19px;
color: #2B2A2A;
font-weight: 600;
background-color: #57595B;
}
.normal-text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
/* width: 450px; */
}
ul {
list-style-position: inside; /* 将项目符号放在内容内部 */
/* width: 450px; */
}
li::marker {
display: inline-block; /* 确保项目符号可见 */
}

View file

@ -0,0 +1,84 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="wrapper">
<div class="main">
<div class="top-border">
<div class="top-title">
<p class="zx-title">Splatoon<span class="zx-title-num">3</span></p>
<p class="zx-tip">当前地图</p>
</div>
<div class="top-date">
<p class="top-date-week">{{data.week}}</p>
<p class="top-date-date">{{data.date}}</p>
<p class="top-date-cn">{{data.time}}</p>
</div>
</div>
<br><br>
<div class="three-border-regular">
<div class="moyu-title"><img src="./res/icon/regular.png" class="title-img">一般比赛</div>
<ul class="match-list">
{% for match in data.data_regular %}
<li class="zx-paragraph">{{ match[0] }}</li>
{% if match[1] %}
<img class="match-img" src="{{ match[1] }}" alt="{{ match[0] }}">
{% endif %}
{% endfor %}
</ul>
</div>
<div class="three-border-bankara">
<div class="moyu-title"><img src="./res/icon/rank.png" class="title-img">蛮颓比赛(挑战)</div>
<ul class="match-list">
{% for match in data.data_bankara_challenge %}
<li class="zx-paragraph">{{ match[0] }}</li>
{% if match[1] %}
<img class="match-img" src="{{ match[1] }}" alt="{{ match[0] }}">
{% endif %}
{% endfor %}
</ul>
</div>
<div class="three-border-bankara">
<div class="moyu-title"><img src="./res/icon/rank.png" class="title-img">蛮颓比赛(开放)</div>
<ul class="match-list">
{% for match in data.data_bankara_open %}
<li class="zx-paragraph">{{ match[0] }}</li>
{% if match[1] %}
<img class="match-img" src="{{ match[1] }}" alt="{{ match[0] }}">
{% endif %}
{% endfor %}
</ul>
</div>
<div class="three-border-coop">
<div class="moyu-title"><img src="./res/icon/salmon_run.png" class="title-img-salmon">鲑鱼跑</div>
<div class="moyu-title-sub">武器: {% for img in data.data_coop[1] %}<img src="{{ img }}" class="title-img-weapon"> {% endfor %}</div>
<ul class="match-list">
<li class="zx-paragraph">{{ data.data_coop[0][0] }}</li>
{% if data.data_coop[0][1] %}
<img class="match-img" src="{{ data.data_coop[0][1] }}" alt="{{ data.data_coop[0][1] }}">
{% endif %}
</ul>
</div>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View file

@ -0,0 +1,571 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
# sys.setdefaultencoding('utf-8')
# friend_list = [424374030,2763844098,645642]
friend_list = [645642, 1050725160, 641569063, 731015337, 291611226, 624006585, 1792404681, 1530669363, 741853137,
87606250, 913228762, 1025943438, 1723364, 469862870, 526674852, 657437047, 864829711, 891997651,
1374157631]
game_types = {
'蛤蜊': '24px-Mode_Icon_Clam_Blitz.png',
'': '24px-Mode_Icon_Rainmaker.png',
'区域': '24px-Mode_Icon_Splat_Zones.png',
'': '24px-Mode_Icon_Tower_Control.png'
}
stage = {"0": {"image": "stage/300px-S2_Stage_The_Reef.png", "name": "寿司街"},
"1": {"image": "stage/300px-S2_Stage_Musselforge_Fitness.png", "name": "健身房"},
"2": {"image": "stage/300px-S2_Stage_Starfish_Mainstage.png", "name": "音乐堂"},
"4": {"image": "stage/300px-S2_Stage_Inkblot_Art_Academy.png", "name": "美術大学"},
"3": {"image": "stage/300px-S2_Stage_Sturgeon_Shipyard.png", "name": "造船厂"},
"5": {"image": "stage/300px-S2_Stage_Humpback_Pump_Track.png", "name": "赛道"},
"6": {"image": "stage/300px-S2_Stage_Manta_Maria.png", "name": "玛丽号"},
"7": {"image": "stage/300px-S2_Stage_Port_Mackerel.png", "name": "码头"},
"8": {"image": "stage/300px-S2_Stage_Moray_Towers.png", "name": "停车场"},
"9": {"image": "stage/300px-S2_Stage_Snapper_Canal.png", "name": "河川"},
"10": {"image": "stage/300px-S2_Stage_Kelp_Dome.png", "name": "农园"},
"11": {"image": "stage/300px-S2_Stage_Blackbelly_Skatepark.png", "name": "滑板公园"},
"12": {"image": "stage/300px-S2_Stage_Shellendorf_Institute.png", "name": "海洋館"},
"13": {"image": "stage/300px-S2_Stage_MakoMart.png", "name": "超市"},
"14": {"image": "stage/300px-S2_Stage_Walleye_Warehouse.png", "name": "倉庫"},
"15": {"image": "stage/300px-S2_Stage_Arowana_Mall.png", "name": "购物街"},
"16": {"image": "stage/300px-S2_Stage_Camp_Triggerfish.png", "name": "露营地"},
"17": {"image": "stage/300px-S2_Stage_Piranha_Pit.png", "name": "矿山"},
"18": {"image": "stage/300px-S2_Stage_Goby_Arena.png", "name": "篮球场"},
"19": {"image": "stage/300px-S2_Stage_New_Albacore_Hotel.png", "name": "酒店"},
"20": {"image": "stage/300px-S2_Stage_Wahoo_World.png", "name": "游乐园"},
"21": {"image": "stage/300px-S2_Stage_Ancho-V_Games.png", "name": "游戏房"},
"22": {"image": "stage/300px-S2_Stage_Skipper_Pavilion.png", "name": "针鱼楼"},
"Salmonid Smokeyard": {"image": "stage/run/200px-S2_Stage_Salmonid_Smokeyard.png", "name": "工房"},
"Spawning Grounds": {"image": "stage/run/200px-S2_Stage_Spawning_Grounds.png", "name": "大坝"},
"Marooner's Bay": {"image": "stage/run/200px-S2_Stage_Marooner's_Bay.png", "name": "破船"},
"Lost Outpost": {"image": "stage/run/200px-S2_Stage_Lost_Outpost.png", "name": "集落"},
"Ruins of Ark Polaris": {"image": "stage/run/200px-S2_Ruins_of_Ark_Polaris_Promo_Image1.jpg", "name": "方舟"}
}
stage3 = {"1": {"image": "stage/3/300px-Scorch_Gorge_Promo.jpg", "name": "Scorch Gorge", "cname": "温泉花大峡谷"},
"2": {"image": "stage/3/300px-S3_promo_screenshot_Eeltail_Alley_00.jpg", "name": "Eeltail Alley",
"cname": "鳗鲶区"},
"3": {"image": "stage/3/300px-S3HagglefishMarketIcon.webp.png", "name": "Hagglefish Market",
"cname": "烟管鱼市场"},
"4": {"image": "stage/3/300px-S3UndertowSpillwayIcon.webp.png", "name": "Undertow Spillway",
"cname": "竹蛏疏洪道"},
"5": {"image": "stage/3/300px-S3_Stage_Um'ami_Ruins.png", "name": "Um'ami Ruins", "cname": "鱼露遗迹"},
"6": {"image": "stage/3/300px-S3MincemeatMetalworksIcon.webp.png", "name": "Mincemeat Metalworks",
"cname": "鱼肉碎金属"},
"7": {"image": "stage/3/300px-S3_Brinewater_Springs.png", "name": "Brinewater Springs",
"cname": "臭鱼干温泉"},
"8": {"image": "stage/3/300px-S3_Stage_Barnacle_&_Dime.png", "name": "Barnacle & Dime",
"cname": "塔拉波特购物公园"},
"9": {"image": "stage/3/300px-S3_Stage_Flounder_Heights.png", "name": "Flounder Heights",
"cname": "比目鱼住宅区"},
"10": {"image": "stage/3/300px-S3HammerheadBridgeIcon.jpeg", "name": "Hammerhead Bridge",
"cname": "真鲭跨海大桥"},
"11": {"image": "stage/3/300px-S3_Stage_Museum_d'Alfonsino_Promo_1.jpg", "name": "Museum d'Alfonsino",
"cname": "金眼鲷美术馆"},
"12": {"image": "stage/3/300px-S3MahiMahiResortIcon.jpeg", "name": "Mahi-Mahi Resort",
"cname": "鬼头刀SPA度假区"},
"13": {"image": "stage/3/300px-S3_Inkblot_Art_Academy.jpeg", "name": "Inkblot Art Academy",
"cname": "海女美术大学"},
"14": {"image": "stage/3/300px-S3_Sturgeon_Shipyard.jpg", "name": "Sturgeon Shipyard", "cname": "鲟鱼造船厂"},
"15": {"image": "stage/3/300px-S3_Mako_Mart.jpg", "name": "MakoMart", "cname": "座头购物中心"},
"16": {"image": "stage/3/300px-S3_Wahoo_World.jpg", "name": "Wahoo World", "cname": "醋饭海洋世界"},
"17": {"image": "stage/3/300px-S3_Stage_Humpback_Pump_Track.png", "name": "Humpback Pump Track",
"cname": "昆布赛道"},
"18": {"image": "stage/3/300px-S3_Stage_Manta_Maria.png", "name": "Manta Maria", "cname": "鬼蝠鲼玛利亚号"},
"19": {"name": "Crableg Capital", "cname": "高脚经济特区"},
"20": {"name": "Shipshape Cargo Co.", "cname": "大比目鱼海运中心"},
"21": {"name": "Robo ROM-en", "cname": "贝见亭"},
"22": {"name": "Bluefin Depot", "cname": "葱鲔鱼煤矿场"},
"23": {"name": "Marlin Airport", "cname": "旗鱼机场"},
"24": {"name": "Lemuria Hub", "cname": "龙宫转运站"},
"26": {"name": "Urchin Underpass", "cname": "十路通高架桥下"},
"Jammin' Salmon Junction": {
"name": "生筋子系统交流道遗址"
},
"Sockeye Station": {
"name": "新卷堡"
},
"Gone Fission Hydroplant": {
"name": "麦年海洋发电所"
},
"Marooner's Bay": {
"name": "漂浮落难船"
},
"Spawning Grounds": {
"name": "鲑坝"
},
"Salmonid Smokeyard": {
"name": "时不知鲑烟熏工房"
},
"Bonerattle Arena": {
"name": "鲑鱼心脏斗技场"
}
}
rank_mode = {"clam_blitz": "蛤蜊", "rainmaker": "抢鱼", "tower_control": "推塔", "splat_zones": "区域"}
fest_ranks = {
'0': '粉丝',
'1': '着迷',
'2': '守护者',
'3': '冠军',
'4': '王者'
}
weapons = {
"0": {"en": "Sploosh-o-matic", "cn": "喇叭枪", "image": "weapons/Wst_Shooter_Short_00.png", "sub_name": "冰壶",
"speical_name": "捶地"},
"1": {"en": "Neo Sploosh-o-matic", "cn": "喇叭枪(贴牌)", "image": "weapons/Wst_Shooter_Short_01.png",
"sub_name": "跳点", "speical_name": "导弹"},
"2": {"en": "Sploosh-o-matic 7", "cn": "喇叭枪(贴牌)", "image": "weapons/Shooter_Short_02.png",
"sub_name": "三角雷", "speical_name": "大锤"},
"10": {"en": "Splattershot Jr.", "cn": "新叶", "image": "weapons/Wst_Shooter_First_00.png", "sub_name": "三角雷",
"speical_name": "墨甲"},
"11": {"en": "Custom Splattershot Jr.", "cn": "枫叶", "image": "weapons/Wst_Shooter_First_01.png",
"sub_name": "小鸡", "speical_name": ""},
"12": {"en": "Kensa Splattershot Jr.", "cn": "新叶(它牌)", "image": "weapons/Wst_Shooter_First_02.png",
"sub_name": "鱼雷", "speical_name": "泡泡"},
"20": {"en": "Splash-o-matic", "cn": "针管", "image": "weapons/Wst_Shooter_Precision_00.png", "sub_name": "毒雾",
"speical_name": "飞机"},
"21": {"en": "Neo Splash-o-matic", "cn": "针管(贴牌)", "image": "weapons/Wst_Shooter_Precision_01.png",
"sub_name": "水球", "speical_name": "粘弹rush"},
"30": {"en": "Aerospray MG", "cn": "银喷", "image": "weapons/Wst_Shooter_Blaze_00.png", "sub_name": "粘弹",
"speical_name": "冰壶rush"},
"31": {"en": "Aerospray RG", "cn": "金喷", "image": "weapons/Wst_Shooter_Blaze_01.png", "sub_name": "花洒",
"speical_name": "仓鼠球"},
"32": {"en": "Aerospray PG", "cn": "铜喷", "image": "weapons/Shooter_Blaze_02.png", "sub_name": "水球",
"speical_name": "nice弹"},
"40": {"en": "Splattershot", "cn": "小绿", "image": "weapons/Wst_Shooter_Normal_00.png", "sub_name": "水球",
"speical_name": "捶地"},
"41": {"en": "Tentatek Splattershot", "cn": "小绿(贴牌)", "image": "weapons/Wst_Shooter_Normal_01.png",
"sub_name": "三角雷", "speical_name": "飞机"},
"42": {"en": "Kensa Splattershot", "cn": "小绿(它牌)", "image": "weapons/Wst_Shooter_Normal_02.png",
"sub_name": "粘弹", "speical_name": "导弹"},
"45": {"en": "Hero Shot Replica", "cn": "P90", "image": "weapons/Wst_Shooter_Normal_H.png", "sub_name": "水球",
"speical_name": "捶地"},
"46": {"en": "Octo Shot Replica", "cn": "小黑(章鱼)", "image": "weapons/Wst_Shooter_Normal_Oct.png",
"sub_name": "三角雷", "speical_name": "飞机"},
"50": {"en": ".52 Gal", "cn": "52", "image": "weapons/Wst_Shooter_Gravity_00.png", "sub_name": "追踪器",
"speical_name": "仓鼠球"},
"51": {"en": ".52 Gal Deco", "cn": "52(贴牌)", "image": "weapons/Wst_Shooter_Gravity_01.png", "sub_name": "冰壶",
"speical_name": "水枪"},
"52": {"en": "Kensa .52 Gal", "cn": "52(它牌)", "image": "weapons/Wst_Shooter_Gravity_02.png", "sub_name": "雨帘",
"speical_name": "nice弹"},
"60": {"en": "N-ZAP '85", "cn": "85", "image": "weapons/Wst_Shooter_QuickMiddle_00.png", "sub_name": "粘弹",
"speical_name": "墨甲"},
"61": {"en": "N-ZAP '89", "cn": "89", "image": "weapons/Wst_Shooter_QuickMiddle_01.png", "sub_name": "小鸡",
"speical_name": "导弹"},
"62": {"en": "N-ZAP '83", "cn": "83", "image": "weapons/Shooter_QuickMiddle_02.png", "sub_name": "花洒",
"speical_name": ""},
"70": {"en": "Splattershot Pro", "cn": "精英枪", "image": "weapons/Wst_Shooter_Expert_00.png", "sub_name": "追踪器",
"speical_name": ""},
"71": {"en": "Forge Splattershot Pro", "cn": "精英枪(贴牌)", "image": "weapons/Wst_Shooter_Expert_01.png",
"sub_name": "粘弹", "speical_name": "泡泡"},
"72": {"en": "Kensa Splattershot Pro", "cn": "精英枪(它牌)", "image": "weapons/Wst_Shooter_Expert_02.png",
"sub_name": "三角雷", "speical_name": "nice弹"},
"80": {"en": ".96 Gal", "cn": "96", "image": "weapons/Wst_Shooter_Heavy_00.png", "sub_name": "花洒",
"speical_name": "墨甲"},
"81": {"en": ".96 Gal Deco", "cn": "96(贴牌)", "image": "weapons/Wst_Shooter_Heavy_01.png", "sub_name": "雨帘",
"speical_name": "捶地"},
"90": {"en": "Jet Squelcher", "cn": "蓝管", "image": "weapons/Wst_Shooter_Long_00.png", "sub_name": "毒雾",
"speical_name": "导弹"},
"91": {"en": "Custom Jet Squelcher", "cn": "蓝管(贴牌)", "image": "weapons/Wst_Shooter_Long_01.png",
"sub_name": "水球", "speical_name": "水枪"},
"200": {"en": "Luna Blaster", "cn": "露娜泡", "image": "weapons/Wst_Shooter_BlasterShort_00.png",
"sub_name": "三角雷", "speical_name": "仓鼠球"},
"201": {"en": "Luna Blaster Neo", "cn": "露娜泡(贴牌)", "image": "weapons/Wst_Shooter_BlasterShort_01.png",
"sub_name": "陷阱", "speical_name": "粘弹rush"},
"202": {"en": "Kensa Luna Blaster", "cn": "露娜泡(它牌)", "image": "weapons/Wst_Shooter_BlasterShort_02.png",
"sub_name": "碳酸弹", "speical_name": ""},
"210": {"en": "Blaster", "cn": "热泡", "image": "weapons/Wst_Shooter_BlasterMiddle_00.png", "sub_name": "毒雾",
"speical_name": "捶地"},
"211": {"en": "Custom Blaster", "cn": "热泡(贴牌)", "image": "weapons/Wst_Shooter_BlasterMiddle_01.png",
"sub_name": "小鸡", "speical_name": "飞机"},
"215": {"en": "Hero Blaster Replica", "cn": "英雄泡", "image": "weapons/Wst_Shooter_BlasterMiddle_H.png",
"sub_name": "毒雾", "speical_name": "捶地"},
"220": {"en": "Range Blaster", "cn": "长热泡枪", "image": "weapons/Wst_Shooter_BlasterLong_00.png",
"sub_name": "粘弹", "speical_name": ""},
"221": {"en": "Custom Range Blaster", "cn": "长热泡(贴牌)", "image": "weapons/Wst_Shooter_BlasterLong_01.png",
"sub_name": "冰壶", "speical_name": "泡泡"},
"222": {"en": "Grim Range Blaster", "cn": "长热泡(贴牌)", "image": "weapons/Shooter_BlasterLong_02.png",
"sub_name": "水球", "speical_name": "导弹"},
"230": {"en": "Clash Blaster", "cn": "蜡笔泡", "image": "weapons/Wst_Shooter_BlasterLightShort_00.png",
"sub_name": "三角雷", "speical_name": "水枪"},
"231": {"en": "Clash Blaster Neo", "cn": "蜡笔泡(贴牌)", "image": "weapons/Wst_Shooter_BlasterLightShort_01.png",
"sub_name": "冰壶", "speical_name": "导弹"},
"240": {"en": "Rapid Blaster", "cn": "红泡", "image": "weapons/Wst_Shooter_BlasterLight_00.png", "sub_name": "陷阱",
"speical_name": "三角雷rush"},
"241": {"en": "Rapid Blaster Deco", "cn": "红泡(贴牌)", "image": "weapons/Wst_Shooter_BlasterLight_01.png",
"sub_name": "粘弹", "speical_name": "飞机"},
"242": {"en": "Kensa Rapid Blaster", "cn": "红泡(它牌)", "image": "weapons/Wst_Shooter_BlasterLight_02.png",
"sub_name": "鱼雷", "speical_name": "仓鼠球"},
"250": {"en": "Rapid Blaster Pro", "cn": "长红泡", "image": "weapons/Wst_Shooter_BlasterLightLong_00.png",
"sub_name": "毒雾", "speical_name": ""},
"251": {"en": "Rapid Blaster Pro Deco", "cn": "长红泡(贴牌)",
"image": "weapons/Wst_Shooter_BlasterLightLong_01.png", "sub_name": "雨帘", "speical_name": "墨甲"},
"300": {"en": "L-3 Nozzlenose", "cn": "L3", "image": "weapons/Wst_Shooter_TripleQuick_00.png", "sub_name": "冰壶",
"speical_name": "仓鼠球"},
"301": {"en": "L-3 Nozzlenose D", "cn": "L3(贴牌)", "image": "weapons/Wst_Shooter_TripleQuick_01.png",
"sub_name": "水球", "speical_name": "飞机"},
"302": {"en": "Kensa L-3 Nozzlenose", "cn": "L3(它牌)", "image": "weapons/Wst_Shooter_TripleQuick_02.png",
"sub_name": "雨帘", "speical_name": "大锤"},
"310": {"en": "H-3 Nozzlenose", "cn": "H3", "image": "weapons/Wst_Shooter_TripleMiddle_00.png",
"sub_name": "追踪器", "speical_name": "导弹"},
"311": {"en": "H-3 Nozzlenose D", "cn": "H3(贴牌)", "image": "weapons/Wst_Shooter_TripleMiddle_01.png",
"sub_name": "粘弹", "speical_name": "墨甲"},
"312": {"en": "Cherry H-3 Nozzlenose", "cn": "H3(贴牌)", "image": "weapons/Shooter_TripleMiddle_02.png",
"sub_name": "雨帘", "speical_name": "泡泡"},
"400": {"en": "Squeezer", "cn": "香槟枪", "image": "weapons/Wst_Shooter_Flash_00.png", "sub_name": "雨帘",
"speical_name": "水枪"},
"401": {"en": "Foil Squeezer", "cn": "香槟枪(贴牌)", "image": "weapons/Wst_Shooter_Flash_01.png",
"sub_name": "三角雷", "speical_name": "泡泡"},
"1000": {"en": "Carbon Roller", "cn": "碳刷", "image": "weapons/Wst_Roller_Compact_00.png", "sub_name": "小鸡",
"speical_name": ""},
"1001": {"en": "Carbon Roller Deco", "cn": "碳刷(贴牌)", "image": "weapons/Wst_Roller_Compact_01.png",
"sub_name": "水球", "speical_name": "小鸡rush"},
"1010": {"en": "Splat Roller", "cn": "中刷", "image": "weapons/Wst_Roller_Normal_00.png", "sub_name": "冰壶",
"speical_name": "捶地"},
"1011": {"en": "Krak-On Splat Roller", "cn": "中刷(贴牌)", "image": "weapons/Wst_Roller_Normal_01.png",
"sub_name": "跳点", "speical_name": "仓鼠球"},
"1012": {"en": "Kensa Splat Roller", "cn": "中刷(贴牌)", "image": "weapons/Wst_Roller_Normal_02.png",
"sub_name": "三角雷", "speical_name": "泡泡"},
"1015": {"en": "Hero Roller Replica", "cn": "英雄中刷", "image": "weapons/Wst_Roller_Normal_H.png",
"sub_name": "冰壶", "speical_name": "捶地"},
"1020": {"en": "Dynamo Roller", "cn": "重刷", "image": "weapons/Wst_Roller_Heavy_00.png", "sub_name": "陷阱",
"speical_name": "水枪"},
"1021": {"en": "Gold Dynamo Roller", "cn": "重刷(贴牌)", "image": "weapons/Wst_Roller_Heavy_01.png",
"sub_name": "三角雷", "speical_name": "墨甲"},
"1022": {"en": "Kensa Dynamo Roller", "cn": "重刷(它牌)", "image": "weapons/Wst_Roller_Heavy_02.png",
"sub_name": "花洒", "speical_name": "nice弹"},
"1030": {"en": "Flingza Roller", "cn": "钢笔刷", "image": "weapons/Wst_Roller_Hunter_00.png", "sub_name": "雨帘",
"speical_name": "三角雷rush"},
"1031": {"en": "Foil Flingza Roller", "cn": "钢笔刷(贴牌)", "image": "weapons/Wst_Roller_Hunter_01.png",
"sub_name": "粘弹", "speical_name": "导弹"},
"1100": {"en": "Inkbrush", "cn": "笔刷", "image": "weapons/Wst_Roller_BrushMini_00.png", "sub_name": "三角雷",
"speical_name": "捶地"},
"1101": {"en": "Inkbrush Nouveau", "cn": "笔刷(贴牌)", "image": "weapons/Wst_Roller_BrushMini_01.png",
"sub_name": "陷阱", "speical_name": "仓鼠球"},
"1102": {"en": "Permanent Inkbrush", "cn": "笔刷(贴牌)", "image": "weapons/Roller_BrushMini_02.png",
"sub_name": "花洒", "speical_name": "墨甲"},
"1110": {"en": "Octobrush", "cn": "北斋", "image": "weapons/Wst_Roller_BrushNormal_00.png", "sub_name": "小鸡",
"speical_name": "飞机"},
"1111": {"en": "Octobrush Nouveau", "cn": "北斋(贴牌)", "image": "weapons/Wst_Roller_BrushNormal_01.png",
"sub_name": "跳点", "speical_name": "导弹"},
"1112": {"en": "Kensa Octobrush", "cn": "北斋(它牌)", "image": "weapons/Wst_Roller_BrushNormal_02.png",
"sub_name": "粘弹", "speical_name": "大锤"},
"1115": {"en": "Herobrush Replica", "cn": "英雄北斋", "image": "weapons/Wst_Roller_BrushNormal_H.png",
"sub_name": "小鸡", "speical_name": "飞机"},
"2000": {"en": "Classic Squiffer", "cn": "洗洁精", "image": "weapons/Wst_Charger_Quick_00.png",
"sub_name": "追踪器", "speical_name": "墨甲"},
"2001": {"en": "New Squiffer", "cn": "洗洁精(贴牌)", "image": "weapons/Wst_Charger_Quick_01.png",
"sub_name": "小鸡", "speical_name": "仓鼠球"},
"2002": {"en": "Fresh Squiffer", "cn": "洗洁精(贴牌)", "image": "weapons/Charger_Quick_02.png", "sub_name": "粘弹",
"speical_name": "飞机"},
"2010": {"en": "Splat Charger", "cn": "短狙", "image": "weapons/Wst_Charger_Normal_00.png", "sub_name": "三角雷",
"speical_name": "水枪"},
"2011": {"en": "Firefin Splat Charger", "cn": "短狙(贴牌)", "image": "weapons/Wst_Charger_Normal_01.png",
"sub_name": "雨帘", "speical_name": "粘弹rush"},
"2012": {"en": "Kensa Charger", "cn": "短狙(它牌)", "image": "weapons/Wst_Charger_Normal_02.png",
"sub_name": "花洒", "speical_name": "仓鼠球"},
"2015": {"en": "Hero Charger Replica", "cn": "英雄狙", "image": "weapons/Wst_Charger_Normal_H.png",
"sub_name": "三角雷", "speical_name": "水枪"},
"2020": {"en": "Splatterscope", "cn": "有镜短狙", "image": "weapons/Wst_Charger_NormalScope_00.png",
"sub_name": "三角雷", "speical_name": "水枪"},
"2021": {"en": "Firefin Splatterscope", "cn": "有镜短狙(贴牌)", "image": "weapons/Wst_Charger_NormalScope_01.png",
"sub_name": "雨帘", "speical_name": "粘弹rush"},
"2022": {"en": "Kensa Splatterscope", "cn": "有镜短狙(它牌)", "image": "weapons/Wst_Charger_NormalScope_01.png",
"sub_name": "花洒", "speical_name": "仓鼠球"},
"2030": {"en": "E-liter 4K", "cn": "4K", "image": "weapons/Wst_Charger_Long_00.png", "sub_name": "陷阱",
"speical_name": ""},
"2031": {"en": "Custom E-liter 4K", "cn": "4k(贴牌)", "image": "weapons/Wst_Charger_Long_01.png",
"sub_name": "跳点", "speical_name": "泡泡"},
"2040": {"en": "E-liter 4K Scope", "cn": "有镜4K", "image": "weapons/Wst_Charger_LongScope_00.png",
"sub_name": "陷阱", "speical_name": ""},
"2041": {"en": "Custom E-liter 4K Scope", "cn": "有镜4K(贴牌)", "image": "weapons/Wst_Charger_LongScope_01.png",
"sub_name": "跳点", "speical_name": "泡泡"},
"2050": {"en": "Bamboozler 14 Mk I", "cn": "竹狙", "image": "weapons/Wst_Charger_Light_00.png", "sub_name": "冰壶",
"speical_name": "导弹"},
"2051": {"en": "Bamboozler 14 Mk II", "cn": "竹狙(贴牌)", "image": "weapons/Wst_Charger_Light_01.png",
"sub_name": "毒雾", "speical_name": "水球rush"},
"2052": {"en": "Bamboozler 14 Mk III", "cn": "竹狙(贴牌)", "image": "weapons/Charger_Light_02.png",
"sub_name": "碳酸弹", "speical_name": "泡泡"},
"2060": {"en": "Goo Tuber", "cn": "水管狙", "image": "weapons/Wst_Charger_Keeper_00.png", "sub_name": "粘弹",
"speical_name": "捶地"},
"2061": {"en": "Custom Goo Tuber", "cn": "水管狙(贴牌)", "image": "weapons/Wst_Charger_Keeper_01.png",
"sub_name": "冰壶", "speical_name": "飞机"},
"3000": {"en": "Slosher", "cn": "红桶", "image": "weapons/Wst_Slosher_Strong_00.png", "sub_name": "粘弹",
"speical_name": "导弹"},
"3001": {"en": "Slosher Deco", "cn": "红桶(贴牌)", "image": "weapons/Wst_Slosher_Strong_01.png", "sub_name": "花洒",
"speical_name": "仓鼠球"},
"3002": {"en": "Soda Slosher", "cn": "苏打桶", "image": "weapons/Slosher_Strong_02.png", "sub_name": "三角雷",
"speical_name": "水球rush"},
"3005": {"en": "Hero Slosher Replica", "cn": "英雄桶", "image": "weapons/Wst_Slosher_Strong_H.png",
"sub_name": "粘弹", "speical_name": "导弹"},
"3010": {"en": "Tri-Slosher", "cn": "绿桶(贴牌)", "image": "weapons/Wst_Slosher_Diffusion_00.png",
"sub_name": "水球", "speical_name": "墨甲"},
"3011": {"en": "Tri-Slosher Nouveau", "cn": "绿桶(贴牌)", "image": "weapons/Wst_Slosher_Diffusion_01.png",
"sub_name": "三角雷", "speical_name": ""},
"3020": {"en": "Sloshing Machine", "cn": "洗衣机", "image": "weapons/Wst_Slosher_Launcher_00.png",
"sub_name": "小鸡", "speical_name": "水枪"},
"3021": {"en": "Sloshing Machine Neo", "cn": "洗衣机(贴牌)", "image": "weapons/Wst_Slosher_Launcher_01.png",
"sub_name": "追踪器", "speical_name": "三角雷rush"},
"3022": {"en": "Kensa Sloshing Machine", "cn": "洗衣机(它牌)", "image": "weapons/Wst_Slosher_Launcher_02.png",
"sub_name": "碳酸弹", "speical_name": "捶地"},
"3030": {"en": "Bloblobber", "cn": "浴缸", "image": "weapons/Wst_Slosher_Bathtub_00.png", "sub_name": "雨帘",
"speical_name": ""},
"3031": {"en": "Bloblobber Deco", "cn": "浴缸(贴牌)", "image": "weapons/Wst_Slosher_Bathtub_01.png",
"sub_name": "花洒", "speical_name": "粘弹rush"},
"3040": {"en": "Explosher", "cn": "重桶", "image": "weapons/Wst_Slosher_Washtub_00.png", "sub_name": "花洒",
"speical_name": "泡泡"},
"3041": {"en": "Custom Explosher", "cn": "重桶(贴牌)", "image": "weapons/Wst_Slosher_Washtub_01.png",
"sub_name": "追踪器", "speical_name": "仓鼠球"},
"4000": {"en": "Mini Splatling", "cn": "轻加", "image": "weapons/Wst_Spinner_Quick_00.png", "sub_name": "水球",
"speical_name": "导弹"},
"4001": {"en": "Zink Mini Splatling", "cn": "轻加(贴牌)", "image": "weapons/Wst_Spinner_Quick_01.png",
"sub_name": "冰壶", "speical_name": ""},
"4002": {"en": "Kensa Mini Splatling", "cn": "轻加(它牌)", "image": "weapons/Wst_Spinner_Quick_02.png",
"sub_name": "毒雾", "speical_name": "大锤"},
"4010": {"en": "Heavy Splatling", "cn": "中加", "image": "weapons/Wst_Spinner_Standard_00.png", "sub_name": "花洒",
"speical_name": "水枪"},
"4011": {"en": "Heavy Splatling Deco", "cn": "中加(贴牌)", "image": "weapons/Wst_Spinner_Standard_01.png",
"sub_name": "雨帘", "speical_name": "泡泡"},
"4012": {"en": "Heavy Splatling Remix", "cn": "中加(贴牌)", "image": "weapons/Spinner_Standard_02.png",
"sub_name": "追踪器", "speical_name": "nice弹"},
"4015": {"en": "Hero Splatling Replica", "cn": "英雄中加", "image": "weapons/Wst_Spinner_Standard_H.png",
"sub_name": "花洒", "speical_name": "水枪"},
"4020": {"en": "Hydra Splatling", "cn": "消防栓", "image": "weapons/Wst_Spinner_Hyper_00.png", "sub_name": "小鸡",
"speical_name": "捶地"},
"4021": {"en": "Custom Hydra Splatling", "cn": "消防栓(贴牌)", "image": "weapons/Wst_Spinner_Hyper_01.png",
"sub_name": "陷阱", "speical_name": "墨甲"},
"4030": {"en": "Ballpoint Splatling", "cn": "圆珠笔", "image": "weapons/Wst_Spinner_Downpour_00.png",
"sub_name": "毒雾", "speical_name": "飞机"},
"4031": {"en": "Ballpoint Splatling Nouveau", "cn": "圆珠笔(贴牌)", "image": "weapons/Wst_Spinner_Downpour_01.png",
"sub_name": "跳点", "speical_name": ""},
"4040": {"en": "Nautilus 47", "cn": "鹦鹉螺", "image": "weapons/Wst_Spinner_Serein_00.png", "sub_name": "追踪器",
"speical_name": "仓鼠球"},
"4041": {"en": "Nautilus 79", "cn": "鹦鹉螺(贴牌)", "image": "weapons/Wst_Spinner_Serein_01.png",
"sub_name": "粘弹", "speical_name": "飞机"},
"5000": {"en": "Dapple Dualies", "cn": "红牙刷", "image": "weapons/Wst_Twins_Short_00.png", "sub_name": "跳点",
"speical_name": "粘弹rush"},
"5001": {"en": "Dapple Dualies Nouveau", "cn": "蓝牙刷", "image": "weapons/Wst_Twins_Short_01.png",
"sub_name": "毒雾", "speical_name": ""},
"5002": {"en": "Clear Dapple Dualies", "cn": "白牙刷", "image": "weapons/Twins_Short_02.png", "sub_name": "鱼雷",
"speical_name": "捶地"},
"5010": {"en": "Splat Dualies", "cn": "绿双", "image": "weapons/Wst_Twins_Normal_00.png", "sub_name": "水球",
"speical_name": "导弹"},
"5011": {"en": "Enperry Splat Dualies", "cn": "金双", "image": "weapons/Wst_Twins_Normal_01.png",
"sub_name": "冰壶", "speical_name": "飞机"},
"5012": {"en": "Kensa Splat Dualies", "cn": "黑双(它牌)", "image": "weapons/Wst_Twins_Normal_02.png",
"sub_name": "粘弹", "speical_name": "仓鼠球"},
"5015": {"en": "Hero Dualie Replicas", "cn": "英雄双枪", "image": "weapons/Wst_Twins_Normal_H.png",
"sub_name": "水球", "speical_name": "导弹"},
"5020": {"en": "Glooga Dualies", "cn": "525", "image": "weapons/Wst_Twins_Gallon_00.png", "sub_name": "陷阱",
"speical_name": "飞机"},
"5021": {"en": "Glooga Dualies Deco", "cn": "525(贴牌)", "image": "weapons/Wst_Twins_Gallon_01.png",
"sub_name": "雨帘", "speical_name": "仓鼠球"},
"5022": {"en": "Kensa Glooga Dualies", "cn": "525(它牌)", "image": "weapons/Wst_Twins_Gallon_02.png",
"sub_name": "碳酸弹", "speical_name": "墨甲"},
"5030": {"en": "Dualie Squelchers", "cn": "红双(贴牌)", "image": "weapons/Wst_Twins_Dual_00.png",
"sub_name": "追踪器", "speical_name": "导弹"},
"5031": {"en": "Custom Dualie Squelchers", "cn": "红双(贴牌)", "image": "weapons/Wst_Twins_Dual_01.png",
"sub_name": "三角雷", "speical_name": ""},
"5040": {"en": "Dark Tetra Dualies", "cn": "气垫", "image": "weapons/Wst_Twins_Stepper_00.png", "sub_name": "小鸡",
"speical_name": "捶地"},
"5041": {"en": "Light Tetra Dualies", "cn": "气垫(贴牌)", "image": "weapons/Wst_Twins_Stepper_01.png",
"sub_name": "花洒", "speical_name": "小鸡rush"},
"6000": {"en": "Splat Brella", "cn": "", "image": "weapons/Wst_Umbrella_Normal_00.png", "sub_name": "花洒",
"speical_name": ""},
"6001": {"en": "Sorella Brella", "cn": "银伞", "image": "weapons/Wst_Umbrella_Normal_01.png", "sub_name": "小鸡",
"speical_name": "三角雷rush"},
"6005": {"en": "Hero Brella Replica", "cn": "英雄伞", "image": "weapons/Wst_Umbrella_Normal_H.png",
"sub_name": "花洒", "speical_name": ""},
"6010": {"en": "Tenta Brella", "cn": "重伞", "image": "weapons/Wst_Umbrella_Wide_00.png", "sub_name": "跳点",
"speical_name": "泡泡"},
"6011": {"en": "Tenta Sorella Brella", "cn": "重伞(贴牌)", "image": "weapons/Wst_Umbrella_Wide_01.png",
"sub_name": "雨帘", "speical_name": "冰壶rush"},
"6012": {"en": "Tenta Camo Brella", "cn": "重伞(贴牌)", "image": "weapons/Umbrella_Wide_02.png", "sub_name": "陷阱",
"speical_name": "大锤"},
"6020": {"en": "Undercover Brella", "cn": "间谍伞", "image": "weapons/Wst_Umbrella_Compact_00.png",
"sub_name": "陷阱", "speical_name": "捶地"},
"6021": {"en": "Undercover Sorella Brella", "cn": "间谍伞(贴牌)", "image": "weapons/Wst_Umbrella_Compact_01.png",
"sub_name": "三角雷", "speical_name": "仓鼠球"},
"6022": {"en": "Kensa Undercover Brella", "cn": "间谍伞(贴牌)", "image": "weapons/Wst_Umbrella_Compact_02.png",
"sub_name": "鱼雷", "speical_name": "墨甲"},
"-1": {"en": "random", "cn": "随机", "image": "weapons/run/S2_Weapon_Main_Random.png"},
"-2": {"en": "random", "cn": "随机", "image": "weapons/run/S2_Weapon_Main_Random_2.png"},
"-3": {"en": "random", "cn": "随机熊武器", "image": "weapons/run/S2_Weapon_Main_Random_2.png"},
"-4": {"en": "random", "cn": "熊伞", "image": "weapons/run/64px-S2_Weapon_Main_Grizzco_Brella.png"},
"-5": {"en": "random", "cn": "熊泡", "image": "weapons/run/64px-S2_Weapon_Main_Grizzco_Blaster.png"},
"-6": {"en": "random", "cn": "熊狙", "image": "weapons/run/64px-S2_Weapon_Main_Grizzco_Charger.png"},
"-3": {"en": "random", "cn": "熊桶", "image": "weapons/run/64px-S2_Weapon_Main_Grizzco_Slosher.png"}
}
weapons3 = {
'Sploosh-o-matic': {'wimg': '3/Path_Wst_Shooter_Short_00.png', 'subname': 'Curling Bomb',
'subimg': 'Wsb_Bomb_Curling00.png', 'spename': 'Ultra Stamp',
'speimg': 'Wsp_SpUltraStamp00.png'},
'Splattershot Jr.': {'wimg': '3/Path_Wst_Shooter_First_00.png', 'subname': 'Splat Bomb',
'subimg': 'Wsb_Bomb_Splash00.png', 'spename': 'Big Bubbler',
'speimg': 'Wsp_SpGreatBarrier00.png'},
'Splash-o-matic': {'wimg': '3/Path_Wst_Shooter_Precision_00.png', 'subname': 'Burst Bomb',
'subimg': 'Wsb_Bomb_Quick00.png', 'spename': 'Crab Tank', 'speimg': 'Wsp_SpChariot00.png'},
'Aerospray MG': {'wimg': '3/Path_Wst_Shooter_Blaze_00.png', 'subname': 'Fizzy Bomb',
'subimg': 'Wsb_Bomb_Fizzy00.png', 'spename': 'Reefslider', 'speimg': 'Wsp_SpSkewer00.png'},
'Splattershot': {'wimg': '3/Path_Wst_Shooter_Normal_00.png', 'subname': 'Suction Bomb',
'subimg': 'Wsb_Bomb_Suction00.png', 'spename': 'Trizooka', 'speimg': 'Wsp_SpUltraShot00.png'},
'Hero Shot Replica': {'wimg': '3/Path_Wst_Shooter_Normal_H.png', 'subname': 'Suction Bomb',
'subimg': 'Wsb_Bomb_Suction00.png', 'spename': 'Trizooka', 'speimg': 'Wsp_SpUltraShot00.png'},
'.52 Gal': {'wimg': '3/Path_Wst_Shooter_Gravity_00.png', 'subname': 'Splash Wall', 'subimg': 'Wsb_Shield00.png',
'spename': 'Killer Wail 5.1', 'speimg': 'Wsp_SpMicroLaser00.png'},
'N-ZAP \'85': {'wimg': '3/Path_Wst_Shooter_QuickMiddle_00.png', 'subname': 'Suction Bomb',
'subimg': 'Wsb_Bomb_Suction00.png', 'spename': 'Tacticooler', 'speimg': 'Wsp_SpEnergyStand00.png'},
'Splattershot Pro': {'wimg': '3/Path_Wst_Shooter_Expert_00.png', 'subname': 'Angle Shooter',
'subimg': 'Wsb_LineMarker00.png', 'spename': 'Crab Tank', 'speimg': 'Wsp_SpChariot00.png'},
'.96 Gal': {'wimg': '3/Path_Wst_Shooter_Heavy_00.png', 'subname': 'Sprinkler', 'subimg': 'Wsb_Sprinkler00.png',
'spename': 'Ink Vac', 'speimg': 'Wsp_SpBlower00.png'},
'Jet Squelcher': {'wimg': '3/Path_Wst_Shooter_Long_00.png', 'subname': 'Angle Shooter',
'subimg': 'Wsb_LineMarker00.png', 'spename': 'Ink Vac', 'speimg': 'Wsp_SpBlower00.png'},
'Luna Blaster': {'wimg': '3/Path_Wst_Blaster_Short_00.png', 'subname': 'Splat Bomb',
'subimg': 'Wsb_Bomb_Splash00.png', 'spename': 'Zipcaster', 'speimg': 'Wsp_SpSuperHook00.png'},
'Blaster': {'wimg': '3/Path_Wst_Blaster_Middle_00.png', 'subname': 'Autobomb', 'subimg': 'Wsb_Bomb_Robot00.png',
'spename': 'Big Bubbler', 'speimg': 'Wsp_SpGreatBarrier00.png'},
'Range Blaster': {'wimg': '3/Path_Wst_Blaster_Long_00.png', 'subname': 'Suction Bomb',
'subimg': 'Wsb_Bomb_Suction00.png', 'spename': 'Wave Breaker',
'speimg': 'Wsp_SpShockSonar00.png'},
'Clash Blaster': {'wimg': '3/Path_Wst_Blaster_LightShort_00.png', 'subname': 'Splat Bomb',
'subimg': 'Wsb_Bomb_Splash00.png', 'spename': 'Trizooka', 'speimg': 'Wsp_SpUltraShot00.png'},
'Rapid Blaster': {'wimg': '3/Path_Wst_Blaster_Light_00.png', 'subname': 'Ink Mine', 'subimg': 'Wsb_Trap00.png',
'spename': 'Triple Inkstrike', 'speimg': 'Wsp_SpTripleTornado00.png'},
'Rapid Blaster Pro': {'wimg': '3/Path_Wst_Blaster_LightLong_00.png', 'subname': 'Toxic Mist',
'subimg': 'Wsb_PoisonMist00.png', 'spename': 'Ink Vac', 'speimg': 'Wsp_SpBlower00.png'},
'L-3 Nozzlenose': {'wimg': '3/Path_Wst_Shooter_TripleQuick_00.png', 'subname': 'Curling Bomb',
'subimg': 'Wsb_Bomb_Curling00.png', 'spename': 'Crab Tank', 'speimg': 'Wsp_SpChariot00.png'},
'H-3 Nozzlenose': {'wimg': '3/Path_Wst_Shooter_TripleMiddle_00.png', 'subname': 'Point Sensor',
'subimg': 'Wsb_PointSensor00.png', 'spename': 'Tacticooler',
'speimg': 'Wsp_SpEnergyStand00.png'},
'Squeezer': {'wimg': '3/Path_Wst_Shooter_Flash_00.png', 'subname': 'Splash Wall', 'subimg': 'Wsb_Shield00.png',
'spename': 'Trizooka', 'speimg': 'Wsp_SpUltraShot00.png'},
'Carbon Roller': {'wimg': '3/Path_Wst_Roller_Compact_00.png', 'subname': 'Autobomb',
'subimg': 'Wsb_Bomb_Robot00.png', 'spename': 'Zipcaster', 'speimg': 'Wsp_SpSuperHook00.png'},
'Splat Roller': {'wimg': '3/Path_Wst_Roller_Normal_00.png', 'subname': 'Curling Bomb',
'subimg': 'Wsb_Bomb_Curling00.png', 'spename': 'Big Bubbler',
'speimg': 'Wsp_SpGreatBarrier00.png'},
'Dynamo Roller': {'wimg': '3/Path_Wst_Roller_Heavy_00.png', 'subname': 'Sprinkler', 'subimg': 'Wsb_Sprinkler00.png',
'spename': 'Tacticooler', 'speimg': 'Wsp_SpEnergyStand00.png'},
'Flingza Roller': {'wimg': '3/Path_Wst_Roller_Hunter_00.png', 'subname': 'Ink Mine', 'subimg': 'Wsb_Trap00.png',
'spename': 'Tenta Missiles', 'speimg': 'Wsp_SpMultiMissile00.png'},
'Inkbrush': {'wimg': '3/Path_Wst_Brush_Mini_00.png', 'subname': 'Splat Bomb', 'subimg': 'Wsb_Bomb_Splash00.png',
'spename': 'Killer Wail 5.1', 'speimg': 'Wsp_SpMicroLaser00.png'},
'Octobrush': {'wimg': '3/Path_Wst_Brush_Normal_00.png', 'subname': 'Suction Bomb',
'subimg': 'Wsb_Bomb_Suction00.png', 'spename': 'Zipcaster', 'speimg': 'Wsp_SpSuperHook00.png'},
'Classic Squiffer': {'wimg': '3/Path_Wst_Charger_Quick_00.png', 'subname': 'Point Sensor',
'subimg': 'Wsb_PointSensor00.png', 'spename': 'Big Bubbler',
'speimg': 'Wsp_SpGreatBarrier00.png'},
'Splat Charger': {'wimg': '3/Path_Wst_Charger_Normal_00.png', 'subname': 'Splat Bomb',
'subimg': 'Wsb_Bomb_Splash00.png', 'spename': 'Ink Vac', 'speimg': 'Wsp_SpBlower00.png'},
'Splatterscope': {'wimg': '3/Path_Wst_Charger_NormalScope_00.png', 'subname': 'Splat Bomb',
'subimg': 'Wsb_Bomb_Splash00.png', 'spename': 'Ink Vac', 'speimg': 'Wsp_SpBlower00.png'},
'E-liter 4K': {'wimg': '3/Path_Wst_Charger_Long_00.png', 'subname': 'Ink Mine', 'subimg': 'Wsb_Trap00.png',
'spename': 'Wave Breaker', 'speimg': 'Wsp_SpShockSonar00.png'},
'E-liter 4K Scope': {'wimg': '3/Path_Wst_Charger_LongScope_00.png', 'subname': 'Ink Mine',
'subimg': 'Wsb_Trap00.png', 'spename': 'Wave Breaker', 'speimg': 'Wsp_SpShockSonar00.png'},
'Bamboozler 14 Mk I': {'wimg': '3/Path_Wst_Charger_Light_00.png', 'subname': 'Autobomb',
'subimg': 'Wsb_Bomb_Robot00.png', 'spename': 'Killer Wail 5.1',
'speimg': 'Wsp_SpMicroLaser00.png'},
'Goo Tuber': {'wimg': '3/Path_Wst_Charger_Keeper_00.png', 'subname': 'Torpedo', 'subimg': 'Wsb_Bomb_Torpedo00.png',
'spename': 'Tenta Missiles', 'speimg': 'Wsp_SpMultiMissile00.png'},
'Slosher': {'wimg': '3/Path_Wst_Slosher_Strong_00.png', 'subname': 'Splat Bomb', 'subimg': 'Wsb_Bomb_Splash00.png',
'spename': 'Triple Inkstrike', 'speimg': 'Wsp_SpTripleTornado00.png'},
'Tri-Slosher': {'wimg': '3/Path_Wst_Slosher_Diffusion_00.png', 'subname': 'Toxic Mist',
'subimg': 'Wsb_PoisonMist00.png', 'spename': 'Inkjet', 'speimg': 'Wsp_SpJetpack00.png'},
'Sloshing Machine': {'wimg': '3/Path_Wst_Slosher_Launcher_00.png', 'subname': 'Fizzy Bomb',
'subimg': 'Wsb_Bomb_Fizzy00.png', 'spename': 'Booyah Bomb', 'speimg': 'Wsp_SpNiceBall00.png'},
'Bloblobber': {'wimg': '3/Path_Wst_Slosher_Bathtub_00.png', 'subname': 'Sprinkler', 'subimg': 'Wsb_Sprinkler00.png',
'spename': 'Ink Storm', 'speimg': 'Wsp_SpInkStorm00.png'},
'Explosher': {'wimg': '3/Path_Wst_Slosher_Washtub_00.png', 'subname': 'Point Sensor',
'subimg': 'Wsb_PointSensor00.png', 'spename': 'Ink Storm', 'speimg': 'Wsp_SpInkStorm00.png'},
'Mini Splatling': {'wimg': '3/Path_Wst_Spinner_Quick_00.png', 'subname': 'Burst Bomb',
'subimg': 'Wsb_Bomb_Quick00.png', 'spename': 'Ultra Stamp', 'speimg': 'Wsp_SpUltraStamp00.png'},
'Heavy Splatling': {'wimg': '3/Path_Wst_Spinner_Standard_00.png', 'subname': 'Sprinkler',
'subimg': 'Wsb_Sprinkler00.png', 'spename': 'Wave Breaker', 'speimg': 'Wsp_SpShockSonar00.png'},
'Hydra Splatling': {'wimg': '3/Path_Wst_Spinner_Hyper_00.png', 'subname': 'Autobomb',
'subimg': 'Wsb_Bomb_Robot00.png', 'spename': 'Booyah Bomb', 'speimg': 'Wsp_SpNiceBall00.png'},
'Ballpoint Splatling': {'wimg': '3/Path_Wst_Spinner_Downpour_00.png', 'subname': 'Fizzy Bomb',
'subimg': 'Wsb_Bomb_Fizzy00.png', 'spename': 'Inkjet', 'speimg': 'Wsp_SpJetpack00.png'},
'Nautilus 47': {'wimg': '3/Path_Wst_Spinner_Serein_00.png', 'subname': 'Point Sensor',
'subimg': 'Wsb_PointSensor00.png', 'spename': 'Ink Storm', 'speimg': 'Wsp_SpInkStorm00.png'},
'Dapple Dualies': {'wimg': '3/Path_Wst_Maneuver_Short_00.png', 'subname': 'Squid Beakon',
'subimg': 'Wsb_Beacon00.png', 'spename': 'Tacticooler', 'speimg': 'Wsp_SpEnergyStand00.png'},
'Splat Dualies': {'wimg': '3/Path_Wst_Maneuver_Normal_00.png', 'subname': 'Suction Bomb',
'subimg': 'Wsb_Bomb_Suction00.png', 'spename': 'Crab Tank', 'speimg': 'Wsp_SpChariot00.png'},
'Glooga Dualies': {'wimg': '3/Path_Wst_Maneuver_Gallon_00.png', 'subname': 'Splash Wall',
'subimg': 'Wsb_Shield00.png', 'spename': 'Booyah Bomb', 'speimg': 'Wsp_SpNiceBall00.png'},
'Dualie Squelchers': {'wimg': '3/Path_Wst_Maneuver_Dual_00.png', 'subname': 'Splat Bomb',
'subimg': 'Wsb_Bomb_Splash00.png', 'spename': 'Wave Breaker',
'speimg': 'Wsp_SpShockSonar00.png'},
'Dark Tetra Dualies': {'wimg': '3/Path_Wst_Maneuver_Stepper_00.png', 'subname': 'Autobomb',
'subimg': 'Wsb_Bomb_Robot00.png', 'spename': 'Reefslider', 'speimg': 'Wsp_SpSkewer00.png'},
'Splat Brella': {'wimg': '3/Path_Wst_Shelter_Normal_00.png', 'subname': 'Sprinkler',
'subimg': 'Wsb_Sprinkler00.png', 'spename': 'Triple Inkstrike',
'speimg': 'Wsp_SpTripleTornado00.png'},
'Tenta Brella': {'wimg': '3/Path_Wst_Shelter_Wide_00.png', 'subname': 'Squid Beakon', 'subimg': 'Wsb_Beacon00.png',
'spename': 'Ink Vac', 'speimg': 'Wsp_SpBlower00.png'},
'Undercover Brella': {'wimg': '3/Path_Wst_Shelter_Compact_00.png', 'subname': 'Ink Mine',
'subimg': 'Wsb_Trap00.png', 'spename': 'Reefslider', 'speimg': 'Wsp_SpSkewer00.png'},
'Tri-Stringer': {'wimg': '3/Path_Wst_Stringer_Normal_00.png', 'subname': 'Toxic Mist',
'subimg': 'Wsb_PoisonMist00.png', 'spename': 'Killer Wail 5.1',
'speimg': 'Wsp_SpMicroLaser00.png'},
'REEF-LUX 450': {'wimg': '3/Path_Wst_Stringer_Short_00.png', 'subname': 'Curling Bomb',
'subimg': 'Wsb_Bomb_Curling00.png', 'spename': 'Tenta Missiles',
'speimg': 'Wsp_SpMultiMissile00.png'},
'Splatana Stamper': {'wimg': '3/Path_Wst_Saber_Normal_00.png', 'subname': 'Burst Bomb',
'subimg': 'Wsb_Bomb_Quick00.png', 'spename': 'Zipcaster', 'speimg': 'Wsp_SpSuperHook00.png'},
'Splatana Wiper': {'wimg': '3/Path_Wst_Saber_Lite_00.png', 'subname': 'Torpedo', 'subimg': 'Wsb_Bomb_Torpedo00.png',
'spename': 'Ultra Stamp', 'speimg': 'Wsp_SpUltraStamp00.png'},
'Big Swig Roller': {'wimg': '3/256px-S3_Weapon_Main_Big_Swig_Roller.png', 'subname': 'Splash Wall',
'subimg': 'Wsb_Shield00.png', 'spename': 'Ink Vac', 'speimg': 'Wsp_SpBlower00.png'},
'Snipewriter 5H': {'wimg': '3/256px-S3_Weapon_Main_Snipewriter_5H.png', 'subname': 'Sprinkler',
'subimg': 'Wsb_Sprinkler00.png', 'spename': 'Tacticooler', 'speimg': 'Wsp_SpEnergyStand00.png'},
'Splattershot Nova': {'wimg': '3/256px-S3_Weapon_Main_Splattershot_Nova.png', 'subname': 'Point Sensor',
'subimg': 'Wsb_PointSensor00.png', 'spename': 'Killer Wail 5.1',
'speimg': 'Wsp_SpMicroLaser00.png'},
'Random': {'wimg': '3/random.png', 'subname': 'Random', 'subimg': 'Random.png', 'spename': 'Random',
'speimg': 'random.png'},
}
subweapon_path = "subspe/"
subweapons = {
"小鸡": "Wsb_Bomb_Robo.png",
"水球": "Wsb_Bomb_Quick.png",
"冰壶": "Wsb_Bomb_Curling.png",
"碳酸弹": "Wsb_Bomb_Piyo.png",
"陷阱": "Wsb_TimerTrap.png",
"追踪器": "Wsb_PointSensor.png",
"雨帘": "Wsb_Shield.png",
"三角雷": "Wsb_Bomb_Splash.png",
"花洒": "Wsb_Sprinkler.png",
"跳点": "Wsb_Flag.png",
"粘弹": "Wsb_Bomb_Suction.png",
"鱼雷": "Wsb_Bomb_Tako.png",
"毒雾": "Wsb_PoisonFog.png"
}
specials = {
"导弹": "Wsp_SuperMissile.png",
"仓鼠球": "Wsp_AquaBall.png",
"捶地": "Wsp_SuperLanding.png",
"泡泡": "Wsp_SuperBubble.png",
"墨甲": "Wsp_SuperArmor.png",
"飞机": "Wsp_Jetpack.png",
"水枪": "Wsp_WaterCutter.png",
"": "Wsp_RainCloud.png",
"粘弹rush": "Wsp_LauncherSuction.png",
"小鸡rush": "Wsp_LauncherRobo.png",
"三角雷rush": "Wsp_LauncherSplash.png",
"水球rush": "Wsp_LauncherQuick.png",
"冰壶rush": "Wsp_LauncherCurling.png",
"nice弹": "Wsp_BooyahBomb.png",
"大锤": "Wsp_Ultra_Stamp.png"}

View file

@ -0,0 +1,218 @@
from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime
from typing import Any, Optional, List
from src.clover_splatoon.tools import parse_iso_z
"""
涂地
"""
@dataclass(frozen=True)
class Image:
url: str
@classmethod
def from_dict(cls, d: dict[str, Any]) -> "Image":
return cls(url=d["url"])
@dataclass(frozen=True)
class VsStage:
vsStageId: int
name: str
image: Image
id: str
@classmethod
def from_dict(cls, d: dict[str, Any]) -> "VsStage":
return cls(
vsStageId=int(d["vsStageId"]),
name=d["name"],
image=Image.from_dict(d["image"]),
id=d["id"],
)
@dataclass(frozen=True)
class VsRule:
name: str
rule: str
id: str
@classmethod
def from_dict(cls, d: dict[str, Any]) -> "VsRule":
return cls(
name=d["name"],
rule=d["rule"],
id=d["id"],
)
@dataclass(frozen=True)
class RegularMatchSetting:
isVsSetting: str
typename: str
vsStages: List[VsStage]
vsRule: VsRule
@classmethod
def from_dict(cls, d: dict[str, Any]) -> "RegularMatchSetting":
stages = [VsStage.from_dict(x) for x in d.get("vsStages", [])]
return cls(
isVsSetting=d.get("__isVsSetting", ""),
typename=d.get("__typename", ""),
vsStages=stages,
vsRule=VsRule.from_dict(d["vsRule"]),
)
@dataclass(frozen=True)
class RegularScheduleItem:
startTime: datetime
endTime: datetime
regularMatchSetting: Optional[RegularMatchSetting]
festMatchSettings: Optional[Any]
@classmethod
def from_dict(cls, d: dict[str, Any]) -> "RegularScheduleItem":
rms = d.get("regularMatchSetting")
return cls(
startTime=parse_iso_z(d["startTime"]),
endTime=parse_iso_z(d["endTime"]),
regularMatchSetting=RegularMatchSetting.from_dict(rms) if rms else None,
festMatchSettings=d.get("festMatchSettings"),
)
"""
打工
"""
@dataclass(frozen=True)
class Image:
url: str
@classmethod
def from_dict(cls, d: dict[str, Any]) -> "Image":
return cls(url=d["url"])
@dataclass(frozen=True)
class Boss:
name: str
id: str
@classmethod
def from_dict(cls, d: dict[str, Any]) -> "Boss":
return cls(name=d["name"], id=d["id"])
@dataclass(frozen=True)
class CoopStage:
name: str
thumbnailImage: Image
image: Image
id: str
@classmethod
def from_dict(cls, d: dict[str, Any]) -> "CoopStage":
return cls(
name=d["name"],
thumbnailImage=Image.from_dict(d["thumbnailImage"]),
image=Image.from_dict(d["image"]),
id=d["id"],
)
@dataclass(frozen=True)
class Weapon:
splatoon3ink_id: str
name: str
image: Image
@classmethod
def from_dict(cls, d: dict[str, Any]) -> "Weapon":
return cls(
splatoon3ink_id=d.get("__splatoon3ink_id", ""),
name=d["name"],
image=Image.from_dict(d["image"]),
)
@dataclass(frozen=True)
class CoopNormalSetting:
typename: str
isCoopSetting: str
boss: Boss
coopStage: CoopStage
weapons: List[Weapon]
@classmethod
def from_dict(cls, d: dict[str, Any]) -> "CoopNormalSetting":
return cls(
typename=d.get("__typename", ""),
isCoopSetting=d.get("__isCoopSetting", ""),
boss=Boss.from_dict(d["boss"]),
coopStage=CoopStage.from_dict(d["coopStage"]),
weapons=[Weapon.from_dict(w) for w in d.get("weapons", [])],
)
@dataclass(frozen=True)
class CoopScheduleItem:
startTime: datetime
endTime: datetime
setting: CoopNormalSetting
king_salmonid_guess: Optional[str]
@classmethod
def from_dict(cls, d: dict[str, Any]) -> "CoopScheduleItem":
return cls(
startTime=parse_iso_z(d["startTime"]),
endTime=parse_iso_z(d["endTime"]),
setting=CoopNormalSetting.from_dict(d["setting"]),
king_salmonid_guess=d.get("__splatoon3ink_king_salmonid_guess"),
)
"""
蛮颓
"""
@dataclass(frozen=True)
class BankaraMatchSetting:
isVsSetting: str
typename: str
vsStages: List[VsStage]
vsRule: VsRule
bankaraMode: str # "CHALLENGE" / "OPEN"
@classmethod
def from_dict(cls, d: dict[str, Any]) -> "BankaraMatchSetting":
return cls(
isVsSetting=d.get("__isVsSetting", ""),
typename=d.get("__typename", ""),
vsStages=[VsStage.from_dict(x) for x in d.get("vsStages", [])],
vsRule=VsRule.from_dict(d["vsRule"]),
bankaraMode=d["bankaraMode"],
)
@dataclass(frozen=True)
class BankaraScheduleItem:
startTime: datetime
endTime: datetime
bankaraMatchSettings: List[BankaraMatchSetting]
festMatchSettings: Optional[Any]
@classmethod
def from_dict(cls, d: dict[str, Any]) -> "BankaraScheduleItem":
return cls(
startTime=parse_iso_z(d["startTime"]),
endTime=parse_iso_z(d["endTime"]),
bankaraMatchSettings=[
BankaraMatchSetting.from_dict(x)
for x in d.get("bankaraMatchSettings", [])
],
festMatchSettings=d.get("festMatchSettings"),
)

View file

@ -0,0 +1,93 @@
import datetime
from datetime import datetime, timezone
from io import BytesIO
import time
import uuid
import PIL.Image
import PIL.ImageFont
import PIL.ImageDraw
import random
import json,base64
from src.clover_splatoon.splatoon_data import weapons,stage,subweapons,specials, friend_list,stage3,weapons3
def get_counter(now):
global counter
global date
if date == now:
counter += 1
else:
date = datetime.now().strftime('%Y-%m-%d')
counter = 1
return counter
def random_id(rtype):
if rtype == 'wep':
r = int(random.choice(list(weapons.keys())))
if r < 0:
r = random_id('wep')
else:
return r
elif rtype == 'map':
r = (random.choice(list(stage.keys())))
if r.isdigit():
return r
else:
r = random_id('map')
else:
pass
return r
def img_to_b64(pic: PIL.Image.Image):
buf = BytesIO()
pic.save(buf, format="PNG")
base64_str = base64.b64encode(buf.getbuffer()).decode()
return "base64://" + base64_str
def circle_corner(img, radii):
# 画圆用于分离4个角
circle = PIL.Image.new('L', (radii * 2, radii * 2), 0) # 创建黑色方形
# circle.save('1.jpg','JPEG',qulity=100)
draw = PIL.ImageDraw.Draw(circle)
draw.ellipse((0, 0, radii * 2, radii * 2), fill=255) # 黑色方形内切白色圆形
# circle.save('2.jpg','JPEG',qulity=100)
img = img.convert("RGBA")
w, h = img.size
alpha = PIL.Image.new('L', img.size, 255)
alpha.paste(circle.crop((0, 0, radii, radii)), (0, 0)) # 左上角
alpha.paste(circle.crop((radii, 0, radii * 2, radii)), (w - radii, 0)) # 右上角
alpha.paste(circle.crop((radii, radii, radii * 2, radii * 2)), (w - radii, h - radii)) # 右下角
alpha.paste(circle.crop((0, radii, radii, radii * 2)), (0, h - radii)) # 左下角
img.putalpha(alpha) # 白色区域透明可见,黑色区域不可见
return img
def merge_image(base_img, tmp_img, img_x, img_y, scale):
# 加载底图
# base_img = Image.open(u'C:\\download\\games\\bg1.png')
# 加载需要P上去的图片
# tmp_img = Image.open(u'C:\\download\\games\\b.png')
# 这里可以选择一块区域或者整张图片
region = tmp_img
width = int(region.size[0] * scale)
height = int(region.size[1] * scale)
region = region.resize((width, height), PIL.Image.ANTIALIAS)
base_img = base_img.convert("RGBA")
region = region.convert("RGBA")
# 透明png不变黑白背景需要加第三个参数,jpg和png不能直接合并
base_img.paste(region, (img_x, img_y), region)
return base_img
def parse_iso_z(dt_str: str) -> datetime:
"""
Parse ISO8601 string like '2026-02-01T14:00:00Z' into aware datetime (UTC).
"""
# Python datetime.fromisoformat 不认 'Z',把 Z 换成 +00:00
return datetime.fromisoformat(dt_str.replace("Z", "+00:00")).astimezone(timezone.utc)

View file

@ -102,4 +102,10 @@ qrserver_size= config['qr']['size']
CodeForces API
"""
codeforces_key = config['codeforces']['key']
codeforces_secret = config['codeforces']['secret']
codeforces_secret = config['codeforces']['secret']
"""
Splatoon3 API
"""
splatoon3_api = config['splatoon']['v3']["schedules"]

View file

@ -3,7 +3,7 @@ from pathlib import Path
path = os.getcwd()+'/src/resources'
resources_path = path
# 塔罗牌图片路径
image_local_qq_image_path = path+'/image/qq_image'
os.makedirs(image_local_qq_image_path, exist_ok=True)
@ -43,6 +43,8 @@ os.makedirs(log_path, exist_ok=True)
# 视频路径
video_path = path+'/video/'
os.makedirs(video_path, exist_ok=True)
# splatoon资源路径
splatoon_path = path+'/image/splatoon/'
#jm配置文件路径
jm_config_path = os.getcwd()+'/src/configs/jm_config.yml'

View file

@ -11,7 +11,7 @@ from src.configs.api_config import v3_enabled, deepseek_enabled, silicon_flow_en
menu = ["/重启","/今日运势","/今日塔罗","/图","/随机图","/搜番","/日报","/点歌","/摸摸头","/群老婆","/今日老婆", "/开启ai","/关闭ai","/角色列表","/添加人设", "/更新人设", "/删除人设", "/切换人设", "/管理员注册",
"/待办", "/test","/天气","我喜欢你", "", "/待办查询", "/新建待办", "/删除待办" ,"/cf","/B站搜索", "/BV搜索", "/喜报", "/悲报", "/luxun","/鲁迅说",
"/奶龙", "/repo", "/info", "/menu", "/轻小说","/本季新番","/下季新番","/新番观察","/绝对色感" ,"/jm", "/cfrt", "/问答"]
"/奶龙", "/repo", "/info", "/menu", "/轻小说","/本季新番","/下季新番","/新番观察","/绝对色感" ,"/jm", "/cfrt", "/问答", "/喷喷地图"]
send_menu = ["/menu","/今日运势","/今日塔罗","/图","/随机图","搜番","/日报","/点歌","/摸摸头","/群老婆","/待办","/天气",
"/待办查询", "/新建待办", "/删除待办" , "/cf", "/cfrt", "/B站搜索", "/BV搜索", "/喜报", "/悲报","/鲁迅说",
@ -94,3 +94,4 @@ test = on_command("test", rule=to_me(), priority=10, block=True)
@test.handle()
async def bot_on_ready():
await test.finish("\nBoost & Magnum, ready fight!!!")

30
src/plugins/splatoon.py Normal file
View file

@ -0,0 +1,30 @@
from pathlib import Path
from datetime import datetime
from nonebot.rule import to_me
from src.clover_splatoon.splatoon_data import weapons,stage,subweapons,specials, friend_list,stage3,weapons3
from nonebot import on_command
import src.plugins.utils.network as network
from src.configs.api_config import splatoon3_api
from nonebot.adapters.qq import MessageEvent, Bot, ActionFailed, Message, Event
from nonebot.adapters.qq import MessageSegment
from src.clover_splatoon.stages import RegularScheduleItem, BankaraScheduleItem, CoopScheduleItem
from src.configs.path_config import splatoon_path, temp_path
from src.clover_splatoon.html_to_image import generate_splatoon_report_image
stages11 = on_command("Splatoon地图", aliases={"splatooon地图", "喷喷地图"},rule=to_me(), priority=10, block=True)
@stages11.handle()
async def stage_handle():
await stages11.send("正在专门为超鱿型的您整理比赛场地!\n请稍等哦~ᔦꙬᔨ")
response = await network.fetch_json(splatoon3_api)
data = response["data"]
regular_schedule = data["regularSchedules"]["nodes"]
bankara_schedule = data["bankaraSchedules"]["nodes"]
coop_schedule = data["coopGroupingSchedule"]["regularSchedules"]["nodes"]
regular_match_now = RegularScheduleItem.from_dict(regular_schedule[0])
bankara_match_now = BankaraScheduleItem.from_dict(bankara_schedule[0])
coop_match_now = CoopScheduleItem.from_dict(coop_schedule[0])
await stages11.finish(MessageSegment.file_image(await generate_splatoon_report_image(regular_match_now, bankara_match_now, coop_match_now)))

View file

@ -0,0 +1,16 @@
import asyncio
import aiohttp
async def fetch_json(url: str) -> dict:
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
resp.raise_for_status() # 不是 2xx 就抛异常
return await resp.json() # 解析 JSON返回 dict/list
async def main():
url = "https://httpbin.org/json"
data = await fetch_json(url)
print(data)
if __name__ == "__main__":
asyncio.run(main())

BIN
src/resources/font/msyh.ttc Normal file

Binary file not shown.

Binary file not shown.