nonebot-plugin-l4d2-server 1.0.0a1__py3-none-any.whl → 1.0.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nonebot_plugin_l4d2_server/__init__.py +4 -4
- nonebot_plugin_l4d2_server/__main__.py +65 -14
- nonebot_plugin_l4d2_server/config.py +11 -0
- nonebot_plugin_l4d2_server/l4_anne/__init__.py +125 -0
- nonebot_plugin_l4d2_server/l4_anne/ranne.py +18 -0
- nonebot_plugin_l4d2_server/l4_help/Help.json +67 -22
- nonebot_plugin_l4d2_server/l4_help/__init__.py +2 -2
- nonebot_plugin_l4d2_server/l4_help/icon//344/273/213/347/273/215.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//344/273/273/345/212/241.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//344/277/241/346/201/257.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/205/254/345/221/212.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/210/200/345/211/221.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/210/207/346/215/242.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/210/240/351/231/244.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/210/267/346/226/260.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/215/241/347/273/204.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/223/252/351/207/214.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/234/260/345/233/276.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/257/274/345/205/245.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/257/274/345/207/272.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//345/275/261.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/213/274/345/233/276.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/216/242/347/264/242.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/216/250/351/200/201.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/224/266/351/233/206.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/224/273/347/225/245.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/233/264/346/226/260.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/235/220/346/226/231.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/237/245/350/257/242.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/240/241/351/252/214.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/257/217/346/234/210.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/267/261/346/270/212.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/267/273/345/212/240.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//346/270/205/351/231/244.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//347/212/266/346/200/201.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//347/255/276/345/210/260.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//347/273/221/345/256/232.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//350/241/250.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//350/241/250/346/203/205.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//350/247/222/350/211/262.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//350/256/260/345/275/225.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//351/205/215/347/275/256.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/icon//351/207/215/345/220/257.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/texture2d/badge.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/texture2d/banner.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/texture2d/bg.jpg +0 -0
- nonebot_plugin_l4d2_server/l4_help/texture2d/button.png +0 -0
- nonebot_plugin_l4d2_server/l4_help/texture2d/icon.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/__init__.py +4 -4
- nonebot_plugin_l4d2_server/l4_image/anne_pil.py +18 -0
- nonebot_plugin_l4d2_server/l4_image/convert.py +9 -13
- nonebot_plugin_l4d2_server/l4_image/download.py +9 -7
- nonebot_plugin_l4d2_server/l4_image/html_img.py +47 -76
- nonebot_plugin_l4d2_server/l4_image/image_tools.py +19 -16
- nonebot_plugin_l4d2_server/l4_image/img/anne/back.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/anne/back1.jpg +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/head/head.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/header/logo.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/header/player1.jpg +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Bocchi_The_Rock.html +17 -30
- nonebot_plugin_l4d2_server/l4_image/img/template/Bocchi_The_Rock.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Pixel.html +17 -26
- nonebot_plugin_l4d2_server/l4_image/img/template/Pixel.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/Rainbow.html +48 -14
- nonebot_plugin_l4d2_server/l4_image/img/template/Rainbow.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/normal.html +14 -24
- nonebot_plugin_l4d2_server/{data/img → l4_image/img/template}/vac.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template/vac_white.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/vtfs.py +3 -3
- nonebot_plugin_l4d2_server/l4_local/__init__.py +94 -0
- nonebot_plugin_l4d2_server/l4_local/file.py +105 -0
- nonebot_plugin_l4d2_server/l4_request/__init__.py +68 -9
- nonebot_plugin_l4d2_server/l4_request/draw_msg.py +38 -43
- nonebot_plugin_l4d2_server/l4_request/utils.py +0 -0
- nonebot_plugin_l4d2_server/utils/api/api.py +8 -2
- nonebot_plugin_l4d2_server/utils/api/models.py +108 -0
- nonebot_plugin_l4d2_server/utils/api/request.py +257 -39
- nonebot_plugin_l4d2_server/utils/database/models.py +12 -23
- nonebot_plugin_l4d2_server/utils/utils.py +22 -11
- {nonebot_plugin_l4d2_server-1.0.0a1.dist-info → nonebot_plugin_l4d2_server-1.0.0b1.dist-info}/METADATA +19 -11
- nonebot_plugin_l4d2_server-1.0.0b1.dist-info/RECORD +98 -0
- nonebot_plugin_l4d2_server/data/L4D2/image/head/head.png +0 -0
- nonebot_plugin_l4d2_server/data/L4D2/image/header/logo.png +0 -0
- nonebot_plugin_l4d2_server/data/L4D2/image/header/player1.jpg +0 -0
- nonebot_plugin_l4d2_server/data/L4D2/image/template/anne.html +0 -68
- nonebot_plugin_l4d2_server/data/L4D2/image/template/back.png +0 -0
- nonebot_plugin_l4d2_server/data/L4D2/image/template/fingerprint.svg +0 -15
- nonebot_plugin_l4d2_server/data/L4D2/image/template/group_ip.html +0 -258
- nonebot_plugin_l4d2_server/data/L4D2/image/template/help.html +0 -262
- nonebot_plugin_l4d2_server/data/L4D2/image/template/help_dack.html +0 -269
- nonebot_plugin_l4d2_server/data/L4D2/image/template/ip.html +0 -54
- nonebot_plugin_l4d2_server/data/L4D2/image/template/l.svg +0 -10
- nonebot_plugin_l4d2_server/data/L4D2/image/template/m.svg +0 -1
- nonebot_plugin_l4d2_server/data/L4D2/image/template/vue.css +0 -531
- nonebot_plugin_l4d2_server/data/L4D2/image/template/w.svg +0 -1
- nonebot_plugin_l4d2_server/data/icon//344/273/213/347/273/215.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//344/273/273/345/212/241.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//344/277/241/346/201/257.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/205/254/345/221/212.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/210/200/345/211/221.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/210/207/346/215/242.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/210/240/351/231/244.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/210/267/346/226/260.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/215/241/347/273/204.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/223/252/351/207/214.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/234/260/345/233/276.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/257/274/345/205/245.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/257/274/345/207/272.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//345/275/261.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/213/274/345/233/276.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/216/242/347/264/242.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/216/250/351/200/201.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/224/266/351/233/206.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/224/273/347/225/245.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/233/264/346/226/260.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/235/220/346/226/231.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/237/245/350/257/242.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/240/241/351/252/214.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/257/217/346/234/210.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/267/261/346/270/212.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/267/273/345/212/240.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//346/270/205/351/231/244.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//347/212/266/346/200/201.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//347/255/276/345/210/260.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//347/273/221/345/256/232.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//350/241/250.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//350/241/250/346/203/205.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//350/247/222/350/211/262.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//350/256/260/345/275/225.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//351/205/215/347/275/256.png +0 -0
- nonebot_plugin_l4d2_server/data/icon//351/207/215/345/220/257.png +0 -0
- nonebot_plugin_l4d2_server/data/img/l4d2.png +0 -0
- nonebot_plugin_l4d2_server/data/img/linux.png +0 -0
- nonebot_plugin_l4d2_server/data/img/white.png +0 -0
- nonebot_plugin_l4d2_server/l4_image/img/template//345/276/256/350/275/257/351/233/205/351/273/221.ttf +0 -0
- nonebot_plugin_l4d2_server-1.0.0a1.dist-info/RECORD +0 -144
- {nonebot_plugin_l4d2_server-1.0.0a1.dist-info → nonebot_plugin_l4d2_server-1.0.0b1.dist-info}/WHEEL +0 -0
- {nonebot_plugin_l4d2_server-1.0.0a1.dist-info → nonebot_plugin_l4d2_server-1.0.0b1.dist-info}/licenses/LICENSE +0 -0
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding=utf-8
|
1
2
|
from typing import List, Optional, TypedDict
|
2
3
|
|
3
4
|
import a2s
|
@@ -27,3 +28,110 @@ class OutServer(TypedDict):
|
|
27
28
|
port: int
|
28
29
|
command: str
|
29
30
|
id_: int
|
31
|
+
|
32
|
+
|
33
|
+
class AnnePlayer(TypedDict):
|
34
|
+
mode: str
|
35
|
+
name: str
|
36
|
+
source: str
|
37
|
+
playtime: str
|
38
|
+
|
39
|
+
|
40
|
+
class AllServer(TypedDict):
|
41
|
+
command: str
|
42
|
+
active_server: int
|
43
|
+
max_server: int
|
44
|
+
active_player: int
|
45
|
+
max_player: int
|
46
|
+
|
47
|
+
|
48
|
+
class AnneSearch(TypedDict):
|
49
|
+
steamid: str
|
50
|
+
rank: str
|
51
|
+
name: str
|
52
|
+
score: str
|
53
|
+
play_time: str
|
54
|
+
last_time: str
|
55
|
+
|
56
|
+
|
57
|
+
class AnnePlayerDetail(TypedDict):
|
58
|
+
rank: int
|
59
|
+
source: str
|
60
|
+
avg_source: float
|
61
|
+
kills: str
|
62
|
+
kills_people: str
|
63
|
+
headshots: str
|
64
|
+
avg_headshots: float
|
65
|
+
map_play: str
|
66
|
+
|
67
|
+
|
68
|
+
class AnnePlayerError(TypedDict):
|
69
|
+
mistake_shout: str
|
70
|
+
kill_friend: str
|
71
|
+
down_friend: str
|
72
|
+
abandon_friend: str
|
73
|
+
put_into: str
|
74
|
+
agitate_witch: str
|
75
|
+
|
76
|
+
|
77
|
+
class AnnePlayerInfAvg(TypedDict):
|
78
|
+
avg_smoker: float
|
79
|
+
avg_boomer: float
|
80
|
+
avg_hunter: float
|
81
|
+
avg_charger: float
|
82
|
+
avg_spitter: float
|
83
|
+
avg_jockey: float
|
84
|
+
avg_tank: float
|
85
|
+
|
86
|
+
|
87
|
+
class AnnePlayerSur(TypedDict):
|
88
|
+
map_clear: str
|
89
|
+
prefect_into: str
|
90
|
+
get_oil: str
|
91
|
+
ammo_arrange: str
|
92
|
+
adrenaline_give: str
|
93
|
+
pills_give: str
|
94
|
+
"""给药"""
|
95
|
+
first_aid_give: str
|
96
|
+
"""给包"""
|
97
|
+
friend_up: str
|
98
|
+
diss_friend: str
|
99
|
+
save_friend: str
|
100
|
+
protect_friend: str
|
101
|
+
pro_from_smoker: str
|
102
|
+
pro_from_hunter: str
|
103
|
+
pro_from_charger: str
|
104
|
+
pro_from_jockey: str
|
105
|
+
melee_charge: str
|
106
|
+
"""刀牛"""
|
107
|
+
tank_kill: str
|
108
|
+
witch_instantly_kill: str
|
109
|
+
"""秒妹"""
|
110
|
+
|
111
|
+
|
112
|
+
class AnnePlayerInf(TypedDict):
|
113
|
+
sur_ace: str
|
114
|
+
sur_down: str
|
115
|
+
boommer_hit: str
|
116
|
+
hunter_prefect: str
|
117
|
+
hunter_success: str
|
118
|
+
tank_damage: str
|
119
|
+
charger_multiple: str
|
120
|
+
|
121
|
+
|
122
|
+
class AnnePlayerInfo(TypedDict):
|
123
|
+
name: str
|
124
|
+
avatar: str
|
125
|
+
steamid: str
|
126
|
+
playtime: str
|
127
|
+
lasttime: str
|
128
|
+
|
129
|
+
|
130
|
+
class AnnePlayer2(TypedDict):
|
131
|
+
kill_msg: str
|
132
|
+
info: AnnePlayerInfo
|
133
|
+
detail: AnnePlayerDetail
|
134
|
+
error: AnnePlayerError
|
135
|
+
inf_avg: AnnePlayerInfAvg
|
136
|
+
sur: AnnePlayerSur
|
137
|
+
inf: AnnePlayerInf
|
@@ -1,14 +1,28 @@
|
|
1
|
-
import
|
1
|
+
import asyncio
|
2
|
+
import contextlib
|
3
|
+
import socket
|
2
4
|
from copy import deepcopy
|
3
|
-
from typing import Any, Dict, List, Literal, Optional,
|
5
|
+
from typing import Any, Dict, List, Literal, Optional, Tuple, cast
|
4
6
|
|
5
7
|
import a2s
|
8
|
+
import ujson as js
|
9
|
+
from bs4 import BeautifulSoup
|
6
10
|
from httpx import AsyncClient
|
7
|
-
from lxml import etree
|
8
11
|
|
12
|
+
# from nonebot.log import logger
|
9
13
|
from ..utils import split_maohao
|
10
|
-
from .api import anne_ban
|
11
|
-
from .models import
|
14
|
+
from .api import AnnePlayerApi, AnneSearchApi, anne_ban
|
15
|
+
from .models import (
|
16
|
+
AnnePlayer2,
|
17
|
+
AnnePlayerDetail,
|
18
|
+
AnnePlayerError,
|
19
|
+
AnnePlayerInf,
|
20
|
+
AnnePlayerInfAvg,
|
21
|
+
AnnePlayerInfo,
|
22
|
+
AnnePlayerSur,
|
23
|
+
AnneSearch,
|
24
|
+
SourceBansInfo,
|
25
|
+
)
|
12
26
|
|
13
27
|
|
14
28
|
class L4D2Api:
|
@@ -18,23 +32,75 @@ class L4D2Api:
|
|
18
32
|
"(KHTML, like Gecko)"
|
19
33
|
"Chrome/126.0.0.0"
|
20
34
|
"Safari/537.36 Edg/126.0.0.0",
|
35
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
21
36
|
}
|
22
37
|
|
23
38
|
async def a2s_info(
|
24
39
|
self,
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
40
|
+
ip_list: List[Tuple[str, int]],
|
41
|
+
is_server: bool = True,
|
42
|
+
is_player: bool = False,
|
43
|
+
) -> List[Tuple[a2s.SourceInfo, List[a2s.Player]]]:
|
44
|
+
msg_list: List[Tuple[a2s.SourceInfo, List[a2s.Player]]] = []
|
45
|
+
sorted_msg_list = []
|
46
|
+
tasks = [] # 用来保存异步任务
|
47
|
+
if ip_list != []:
|
48
|
+
for index, i in enumerate(ip_list):
|
49
|
+
try:
|
50
|
+
tasks.append(
|
51
|
+
asyncio.create_task(
|
52
|
+
self.process_message(
|
53
|
+
i,
|
54
|
+
index,
|
55
|
+
is_server,
|
56
|
+
is_player,
|
57
|
+
),
|
58
|
+
),
|
59
|
+
)
|
60
|
+
except ValueError:
|
61
|
+
continue # 处理异常情况
|
62
|
+
|
63
|
+
msg_list = await asyncio.gather(*tasks)
|
64
|
+
sorted_msg_list = sorted(msg_list, key=lambda x: x[0].steam_id)
|
65
|
+
|
66
|
+
return sorted_msg_list
|
30
67
|
|
31
|
-
async def
|
68
|
+
async def process_message(
|
32
69
|
self,
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
70
|
+
ip: Tuple[str, int],
|
71
|
+
index: int,
|
72
|
+
is_server: bool,
|
73
|
+
is_player: bool,
|
74
|
+
):
|
75
|
+
server: a2s.SourceInfo = a2s.SourceInfo()
|
76
|
+
play: List[a2s.Player] = []
|
77
|
+
if is_server:
|
78
|
+
try:
|
79
|
+
server = await a2s.ainfo(ip)
|
80
|
+
if server is not None:
|
81
|
+
server.steam_id = index
|
82
|
+
|
83
|
+
except (
|
84
|
+
asyncio.exceptions.TimeoutError,
|
85
|
+
ConnectionRefusedError,
|
86
|
+
socket.gaierror,
|
87
|
+
):
|
88
|
+
server.steam_id = index
|
89
|
+
server.player_count = 0
|
90
|
+
server.max_players = 0
|
91
|
+
server.server_name = "服务器无响应"
|
92
|
+
server.map_name = "无"
|
93
|
+
server.folder = "m"
|
94
|
+
server.vac_enabled = False
|
95
|
+
|
96
|
+
if is_player:
|
97
|
+
with contextlib.suppress(
|
98
|
+
asyncio.exceptions.TimeoutError,
|
99
|
+
ConnectionRefusedError,
|
100
|
+
socket.gaierror,
|
101
|
+
):
|
102
|
+
play = await a2s.aplayers(ip)
|
103
|
+
return server, play
|
38
104
|
|
39
105
|
async def _server_request(
|
40
106
|
self,
|
@@ -45,7 +111,7 @@ class L4D2Api:
|
|
45
111
|
json: Optional[Dict[str, Any]] = None,
|
46
112
|
data: Optional[Dict[str, Any]] = None,
|
47
113
|
is_json: bool = True,
|
48
|
-
)
|
114
|
+
):
|
49
115
|
header = deepcopy(self._HEADER)
|
50
116
|
|
51
117
|
if json is not None:
|
@@ -85,35 +151,187 @@ class L4D2Api:
|
|
85
151
|
):
|
86
152
|
return raw_data["result"]["error_code"]
|
87
153
|
return raw_data
|
88
|
-
html_content = resp.
|
89
|
-
return
|
154
|
+
html_content = resp.content
|
155
|
+
return BeautifulSoup(html_content, "lxml")
|
90
156
|
|
91
|
-
async def get_sourceban(self,
|
92
|
-
|
157
|
+
async def get_sourceban(self, url: str = anne_ban):
|
158
|
+
"""从sourceban++获取服务器列表,目前未做名称处理"""
|
159
|
+
soup = await self._server_request(
|
93
160
|
url=url,
|
94
161
|
is_json=False,
|
95
|
-
)
|
96
|
-
name = name
|
97
|
-
# 检查响应状态码
|
162
|
+
)
|
98
163
|
|
99
|
-
|
100
|
-
|
164
|
+
if not isinstance(soup, BeautifulSoup):
|
165
|
+
return []
|
166
|
+
server_list = []
|
167
|
+
tbody = soup.select_one("tbody")
|
168
|
+
if tbody is None:
|
169
|
+
return []
|
170
|
+
tr_tags = tbody.select("tr")
|
171
|
+
for index, tr in enumerate(tr_tags):
|
172
|
+
td_tags = tr.select("td")
|
173
|
+
for num, td in enumerate(td_tags):
|
174
|
+
if num == 4:
|
175
|
+
host, port = split_maohao(td.text)
|
176
|
+
server_list.append(
|
177
|
+
SourceBansInfo(index=index, host=host, port=port),
|
178
|
+
)
|
179
|
+
|
180
|
+
return server_list
|
181
|
+
|
182
|
+
async def get_anne_steamid(self, name: str):
|
183
|
+
"""从电信anne服搜索昵称获取steamid"""
|
184
|
+
soup = await self._server_request(
|
185
|
+
url=AnneSearchApi,
|
186
|
+
data={"search": name},
|
187
|
+
method="POST",
|
188
|
+
is_json=False,
|
101
189
|
)
|
190
|
+
if not isinstance(soup, BeautifulSoup):
|
191
|
+
return None
|
102
192
|
server_list = []
|
103
|
-
|
104
|
-
|
105
|
-
|
193
|
+
tbody = soup.select_one("tbody")
|
194
|
+
if tbody is None:
|
195
|
+
return None
|
196
|
+
tr_tags = tbody.select("tr")
|
197
|
+
for tr in tr_tags:
|
198
|
+
onclick = tr.get("onclick")
|
199
|
+
if onclick is None or isinstance(onclick, list):
|
106
200
|
continue
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
201
|
+
steamid = onclick.split("steamid=")[1].replace("'", "")
|
202
|
+
td_tags = tr.select("td")
|
203
|
+
server_list.append(
|
204
|
+
{
|
205
|
+
"steamid": steamid,
|
206
|
+
"rank": td_tags[0].text.strip(),
|
207
|
+
"name": td_tags[1].text.strip(),
|
208
|
+
"score": td_tags[2].text.strip(),
|
209
|
+
"play_time": td_tags[3].text.strip(),
|
210
|
+
"last_time": td_tags,
|
211
|
+
},
|
212
|
+
)
|
213
|
+
print(server_list)
|
214
|
+
return cast(List[AnneSearch], server_list)
|
215
|
+
|
216
|
+
async def get_anne_playerdetail(self, steamid: str):
|
217
|
+
"""从电信anne服通过steamid获取战绩"""
|
218
|
+
soup = await self._server_request(
|
219
|
+
url=AnnePlayerApi,
|
220
|
+
method="GET",
|
221
|
+
params={"steamid": steamid},
|
222
|
+
is_json=False,
|
223
|
+
)
|
224
|
+
if not isinstance(soup, BeautifulSoup):
|
225
|
+
return None
|
226
|
+
|
227
|
+
tbody = soup.find(
|
228
|
+
"div",
|
229
|
+
class_="content text-center text-md-left",
|
230
|
+
style="background-color: #f2f2f2;",
|
231
|
+
)
|
232
|
+
if tbody is None:
|
233
|
+
return None
|
234
|
+
kill_tag = tbody.find(
|
235
|
+
"div",
|
236
|
+
class_="card-body worldmap d-flex flex-column justify-content-center text-center",
|
237
|
+
)
|
238
|
+
|
239
|
+
tbody_tags = tbody.find_all(
|
240
|
+
"table",
|
241
|
+
class_="table content-table-noborder text-left",
|
242
|
+
)
|
243
|
+
print(len(tbody_tags))
|
244
|
+
info_tag = tbody_tags[0]
|
245
|
+
detail_tag = tbody_tags[1]
|
246
|
+
error_tag = tbody_tags[2]
|
247
|
+
inf_avg_tag = tbody_tags[3]
|
248
|
+
sur_tag = tbody_tags[4]
|
249
|
+
inf_tag = tbody_tags[5]
|
250
|
+
|
251
|
+
info_tr = info_tag.select("tr")
|
252
|
+
info_dict = {
|
253
|
+
"name": info_tr[0].select("td")[1].text.strip(),
|
254
|
+
"avatar": info_tr[1].select("td")[1].text.strip(),
|
255
|
+
"steamid": info_tr[2].select("td")[1].text.strip(),
|
256
|
+
"playtime": info_tr[3].select("td")[1].text.strip(),
|
257
|
+
"lasttime": info_tr[4].select("td")[1].text.strip(),
|
258
|
+
}
|
259
|
+
detail_tag = {
|
260
|
+
"rank": detail_tag.select("tr")[0].select("td")[1].text.strip(),
|
261
|
+
"source": detail_tag.select("tr")[1].select("td")[1].text.strip(),
|
262
|
+
"avg_source": detail_tag.select("tr")[2].select("td")[1].text.strip(),
|
263
|
+
"kills": detail_tag.select("tr")[3].select("td")[1].text.strip(),
|
264
|
+
"kills_people": detail_tag.select("tr")[4].select("td")[1].text.strip(),
|
265
|
+
"headshots": detail_tag.select("tr")[5].select("td")[1].text.strip(),
|
266
|
+
"avg_headshots": detail_tag.select("tr")[6].select("td")[1].text.strip(),
|
267
|
+
"map_play": detail_tag.select("tr")[7].select("td")[1].text.strip(),
|
268
|
+
}
|
269
|
+
error_tag = {
|
270
|
+
"mistake_shout": error_tag.select("tr")[0].select("td")[1].text.strip(),
|
271
|
+
"kill_friend": error_tag.select("tr")[1].select("td")[1].text.strip(),
|
272
|
+
"down_friend": error_tag.select("tr")[2].select("td")[1].text.strip(),
|
273
|
+
"abandon_friend": error_tag.select("tr")[3].select("td")[1].text.strip(),
|
274
|
+
"put_into": error_tag.select("tr")[4].select("td")[1].text.strip(),
|
275
|
+
"agitate_witch": error_tag.select("tr")[5].select("td")[1].text.strip(),
|
276
|
+
}
|
277
|
+
inf_avg_dict = {
|
278
|
+
"avg_smoker": inf_avg_tag.select("tr")[0].select("td")[1].text.strip(),
|
279
|
+
"avg_boomer": inf_avg_tag.select("tr")[1].select("td")[1].text.strip(),
|
280
|
+
"avg_hunter": inf_avg_tag.select("tr")[2].select("td")[1].text.strip(),
|
281
|
+
"avg_charger": inf_avg_tag.select("tr")[3].select("td")[1].text.strip(),
|
282
|
+
"avg_spitter": inf_avg_tag.select("tr")[4].select("td")[1].text.strip(),
|
283
|
+
"avg_jockey": inf_avg_tag.select("tr")[5].select("td")[1].text.strip(),
|
284
|
+
"avg_tank": inf_avg_tag.select("tr")[6].select("td")[1].text.strip(),
|
285
|
+
}
|
286
|
+
sur_dict = {
|
287
|
+
"map_clear": sur_tag.select("tr")[0].select("td")[1].text.strip(),
|
288
|
+
"prefect_into": sur_tag.select("tr")[1].select("td")[1].text.strip(),
|
289
|
+
"get_oil": sur_tag.select("tr")[2].select("td")[1].text.strip(),
|
290
|
+
"ammo_arrange": sur_tag.select("tr")[3].select("td")[1].text.strip(),
|
291
|
+
"adrenaline_give": sur_tag.select("tr")[4].select("td")[1].text.strip(),
|
292
|
+
"pills_give": sur_tag.select("tr")[5].select("td")[1].text.strip(),
|
293
|
+
"first_aid_give": sur_tag.select("tr")[6].select("td")[1].text.strip(),
|
294
|
+
"friend_up": sur_tag.select("tr")[7].select("td")[1].text.strip(),
|
295
|
+
"diss_friend": sur_tag.select("tr")[8].select("td")[1].text.strip(),
|
296
|
+
"save_friend": sur_tag.select("tr")[9].select("td")[1].text.strip(),
|
297
|
+
"protect_friend": sur_tag.select("tr")[10].select("td")[1].text.strip(),
|
298
|
+
"pro_from_smoker": sur_tag.select("tr")[11].select("td")[1].text.strip(),
|
299
|
+
"pro_from_hunter": sur_tag.select("tr")[12].select("td")[1].text.strip(),
|
300
|
+
"pro_from_charger": sur_tag.select("tr")[13].select("td")[1].text.strip(),
|
301
|
+
"pro_from_jockey": sur_tag.select("tr")[14].select("td")[1].text.strip(),
|
302
|
+
"melee_charge": sur_tag.select("tr")[15].select("td")[1].text.strip(),
|
303
|
+
"tank_kill": sur_tag.select("tr")[16].select("td")[1].text.strip(),
|
304
|
+
"witch_instantly_kill": sur_tag.select("tr")[17]
|
305
|
+
.select("td")[1]
|
306
|
+
.text.strip(),
|
307
|
+
}
|
308
|
+
inf_dict = {
|
309
|
+
"sur_ace": inf_tag.select("tr")[0].select("td")[1].text.strip(),
|
310
|
+
"sur_down": inf_tag.select("tr")[1].select("td")[1].text.strip(),
|
311
|
+
"boommer_hit": inf_tag.select("tr")[2].select("td")[1].text.strip(),
|
312
|
+
"hunter_prefect": inf_tag.select("tr")[3].select("td")[1].text.strip(),
|
313
|
+
"hunter_success": inf_tag.select("tr")[4].select("td")[1].text.strip(),
|
314
|
+
"tank_damage": inf_tag.select("tr")[5].select("td")[1].text.strip(),
|
315
|
+
"charger_multiple": inf_tag.select("tr")[6].select("td")[1].text.strip(),
|
316
|
+
}
|
317
|
+
info_dict = cast(AnnePlayerInfo, info_dict)
|
318
|
+
detail_dict = cast(AnnePlayerDetail, detail_tag)
|
319
|
+
error_dict = cast(AnnePlayerError, error_tag)
|
320
|
+
inf_avg_dict = cast(AnnePlayerInfAvg, inf_avg_dict)
|
321
|
+
sur_dict = cast(AnnePlayerSur, sur_dict)
|
322
|
+
inf_dict = cast(AnnePlayerInf, inf_dict)
|
323
|
+
|
324
|
+
out_dict = {
|
325
|
+
"kill_msg": kill_tag.text if kill_tag is not None else "",
|
326
|
+
"info": info_dict,
|
327
|
+
"detail": detail_dict,
|
328
|
+
"inf_avg": inf_avg_dict,
|
329
|
+
"sur": sur_dict,
|
330
|
+
"inf": inf_dict,
|
331
|
+
"error": error_dict,
|
332
|
+
}
|
333
|
+
|
334
|
+
return cast(AnnePlayer2, out_dict)
|
117
335
|
|
118
336
|
|
119
337
|
L4API = L4D2Api()
|
@@ -1,29 +1,18 @@
|
|
1
|
-
from
|
1
|
+
from nonebot_plugin_tortoise_orm import add_model
|
2
|
+
from tortoise import fields
|
3
|
+
from tortoise.models import Model
|
2
4
|
|
3
|
-
|
4
|
-
from nonebot_plugin_datastore import get_plugin_data
|
5
|
-
from sqlalchemy.orm import Mapped, mapped_column
|
5
|
+
add_model(__name__)
|
6
6
|
|
7
|
-
plugin_data = get_plugin_data()
|
8
7
|
|
9
|
-
|
10
|
-
DATA = get_plugin_data()
|
11
|
-
DATA.set_migration_dir(Path("data/L4D2/") / "sql")
|
12
|
-
|
13
|
-
|
14
|
-
class SteamUser(DATA.Model):
|
8
|
+
class SteamUser(Model):
|
15
9
|
"""个人资料"""
|
16
10
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
matcher = on_command("test")
|
11
|
+
userid = fields.BigIntField(pk=True)
|
12
|
+
SteamID = fields.TextField(null=True)
|
13
|
+
SteamID64 = fields.TextField(null=True)
|
14
|
+
Name = fields.TextField(null=True)
|
23
15
|
|
24
|
-
#
|
25
|
-
|
26
|
-
|
27
|
-
# example = SteamUser(message="matcher")
|
28
|
-
# session.add(example)
|
29
|
-
# await session.commit()
|
16
|
+
class Meta: # type: ignore
|
17
|
+
table = "steam_user"
|
18
|
+
table_description = "个人资料"
|
@@ -5,8 +5,11 @@ from pathlib import Path
|
|
5
5
|
from typing import Any, Dict, List, Optional, Tuple
|
6
6
|
|
7
7
|
import aiofiles
|
8
|
+
import aiohttp
|
9
|
+
import nonebot
|
8
10
|
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent
|
9
11
|
from nonebot.log import logger
|
12
|
+
from nonebot_plugin_alconna import UniMessage
|
10
13
|
|
11
14
|
|
12
15
|
async def get_file(url: str, down_file: Path):
|
@@ -37,7 +40,7 @@ def get_vpk(map_path: Path, file_: str = ".vpk") -> List[str]:
|
|
37
40
|
def mes_list(mes: str, name_list: List[str]) -> str:
|
38
41
|
if name_list:
|
39
42
|
for idx, name in enumerate(name_list):
|
40
|
-
mes += f"\n{idx+1}、{name}"
|
43
|
+
mes += f"\n{idx + 1}、{name}"
|
41
44
|
return mes
|
42
45
|
|
43
46
|
|
@@ -72,16 +75,11 @@ def solve(msg: str):
|
|
72
75
|
return "\n".join(lines)
|
73
76
|
|
74
77
|
|
75
|
-
async def get_message_at(datas: str) -> List[int]:
|
76
|
-
data: Dict[str, Any] = json.loads(datas)
|
77
|
-
return [int(msg["data"]["qq"]) for msg in data["message"] if msg["type"] == "at"]
|
78
|
-
|
79
|
-
|
80
78
|
def at_to_usrid(at: List[int]):
|
81
79
|
return at[0] if at else None
|
82
80
|
|
83
81
|
|
84
|
-
async def save_file(file: bytes, path_name):
|
82
|
+
async def save_file(file: bytes, path_name: str):
|
85
83
|
"""保存文件"""
|
86
84
|
async with aiofiles.open(path_name, "wb") as files:
|
87
85
|
await files.write(file)
|
@@ -149,7 +147,7 @@ def register_menu_func(
|
|
149
147
|
|
150
148
|
|
151
149
|
def register_menu(*args, **kwargs):
|
152
|
-
def decorator(f):
|
150
|
+
def decorator(f): # noqa: ANN001
|
153
151
|
register_menu_func(*args, **kwargs)
|
154
152
|
return f
|
155
153
|
|
@@ -177,10 +175,8 @@ def split_maohao(msg: str) -> Tuple[str, int]:
|
|
177
175
|
return "", -1
|
178
176
|
|
179
177
|
|
180
|
-
import aiohttp
|
181
|
-
|
182
178
|
headers = {
|
183
|
-
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0",
|
179
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0",
|
184
180
|
}
|
185
181
|
|
186
182
|
|
@@ -202,3 +198,18 @@ async def url_to_msg(url: str):
|
|
202
198
|
if response.status == 200:
|
203
199
|
return await response.text()
|
204
200
|
return None
|
201
|
+
|
202
|
+
|
203
|
+
async def get_message_at(datas: str) -> Optional[int]:
|
204
|
+
data: Dict[str, Any] = json.loads(datas)
|
205
|
+
at_list = [int(msg["data"]["qq"]) for msg in data["message"] if msg["type"] == "at"]
|
206
|
+
return at_list[0] if at_list else None
|
207
|
+
|
208
|
+
|
209
|
+
async def send_ip_msg(msg: str):
|
210
|
+
try:
|
211
|
+
await UniMessage.text(msg).finish()
|
212
|
+
except nonebot.adapters.qq:
|
213
|
+
msg_new = msg.split("\n")[:-2]
|
214
|
+
msg_out = "\n".join(msg_new)
|
215
|
+
await UniMessage.text(msg_out).send()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: nonebot-plugin-l4d2-server
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.0b1
|
4
4
|
Summary: L4D2 server related operations plugin for NoneBot2
|
5
5
|
Keywords: steam,game,l4d2,nonebot2,plugin
|
6
6
|
Home-page: https://github.com/Agnes4m/nonebot_plugin_l4d2_server
|
@@ -19,12 +19,19 @@ Requires-Dist: nonebot2>=2.0.0
|
|
19
19
|
Requires-Dist: nonebot-plugin-htmlrender>=0.3.0
|
20
20
|
Requires-Dist: nonebot-adapter-onebot>=2.4.4
|
21
21
|
Requires-Dist: nonebot-plugin-alconna>=0.50.0
|
22
|
+
Requires-Dist: nonebot_plugin_datastore>=1.3.0
|
23
|
+
Requires-Dist: nonebot-plugin-tortoise-orm>=0.1.4
|
22
24
|
Requires-Dist: aiohttp>=3.8.4
|
23
25
|
Requires-Dist: jinja2>=3.0.0
|
24
26
|
Requires-Dist: srctools>=2.3.9
|
25
|
-
Requires-Dist:
|
26
|
-
Requires-Dist:
|
27
|
+
Requires-Dist: httpx<0.24.1,>=0.22.0
|
28
|
+
Requires-Dist: msgspec>=0.18.0
|
27
29
|
Requires-Dist: python-a2s>=1.3.0
|
30
|
+
Requires-Dist: ujson>=5.10.0
|
31
|
+
Requires-Dist: lxml>=5.2.2
|
32
|
+
Requires-Dist: rcon>=2.1.0
|
33
|
+
Requires-Dist: pillow>9
|
34
|
+
Requires-Dist: beautifulsoup4>=4.12.3
|
28
35
|
Description-Content-Type: text/markdown
|
29
36
|
|
30
37
|
<!-- markdownlint-disable MD026 MD031 MD033 MD036 MD041 MD046 MD051 -->
|
@@ -137,28 +144,29 @@ conda install nonebot-plugin-l4d2-server
|
|
137
144
|
|
138
145
|
## [数据结构](./docs/standand.md)
|
139
146
|
|
147
|
+
暂未更新
|
148
|
+
|
140
149
|
## env设置
|
141
150
|
|
142
151
|
"""bash
|
143
|
-
l4_anne
|
152
|
+
l4_anne = False
|
144
153
|
"""是否启用anne电信服相关功能"""
|
145
|
-
l4_enable
|
154
|
+
l4_enable = True
|
146
155
|
"""是否全局启用求生功能"""
|
147
|
-
l4_image
|
156
|
+
l4_image = False
|
148
157
|
"""是否启用图片"""
|
149
|
-
l4_connect
|
158
|
+
l4_connect = True
|
150
159
|
"""是否在查服命令后加入connect ip"""
|
151
|
-
l4_path
|
160
|
+
l4_path = "data/L4D2"
|
152
161
|
"""插件数据路径"""
|
153
|
-
l4_players
|
162
|
+
l4_players = 4
|
154
163
|
"""查询总图的时候展示的用户数量"""
|
155
|
-
l4_style
|
164
|
+
l4_style = "default"
|
156
165
|
"""图片风格,可选包括以下,默认简洁
|
157
166
|
- 暗风格
|
158
167
|
- 孤独摇滚
|
159
168
|
- 电玩像素
|
160
169
|
- 缤纷彩虹
|
161
|
-
- 求生之路
|
162
170
|
"""
|
163
171
|
|
164
172
|
## 其他
|