nonebot-plugin-l4d2-server 0.5.0__py3-none-any.whl → 0.5.2__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.
- LICENSE +674 -674
- README.md +365 -349
- nonebot_plugin_l4d2_server/__init__.py +1 -1
- nonebot_plugin_l4d2_server/chrome.py +45 -0
- nonebot_plugin_l4d2_server/command.py +232 -233
- nonebot_plugin_l4d2_server/config.py +210 -318
- nonebot_plugin_l4d2_server/data/L4D2/image/template/anne.html +60 -60
- nonebot_plugin_l4d2_server/data/L4D2/image/template/fingerprint.svg +15 -15
- nonebot_plugin_l4d2_server/data/L4D2/image/template/help.html +233 -233
- nonebot_plugin_l4d2_server/data/L4D2/image/template/help_dack.html +231 -231
- nonebot_plugin_l4d2_server/data/L4D2/image/template/ip.html +48 -48
- nonebot_plugin_l4d2_server/data/L4D2/image/template/l.svg +9 -9
- nonebot_plugin_l4d2_server/data/L4D2/image/template/vue.css +530 -530
- nonebot_plugin_l4d2_server/l4d2_anne/__init__.py +251 -251
- nonebot_plugin_l4d2_server/l4d2_anne/analysis.py +51 -51
- nonebot_plugin_l4d2_server/l4d2_anne/anne_telecom.py +75 -75
- nonebot_plugin_l4d2_server/l4d2_anne/server.py +65 -65
- nonebot_plugin_l4d2_server/l4d2_anne/startand.py +17 -17
- nonebot_plugin_l4d2_server/l4d2_data/__init__.py +91 -91
- nonebot_plugin_l4d2_server/l4d2_data/config.py +17 -17
- nonebot_plugin_l4d2_server/l4d2_data/players.py +87 -87
- nonebot_plugin_l4d2_server/l4d2_data/serverip.py +32 -32
- nonebot_plugin_l4d2_server/l4d2_file/__init__.py +122 -122
- nonebot_plugin_l4d2_server/l4d2_file/ayromote.py +56 -56
- nonebot_plugin_l4d2_server/l4d2_file/remote.py +63 -66
- nonebot_plugin_l4d2_server/l4d2_image/__init__.py +103 -103
- nonebot_plugin_l4d2_server/l4d2_image/download.py +101 -101
- nonebot_plugin_l4d2_server/l4d2_image/htmlimg.py +32 -32
- nonebot_plugin_l4d2_server/l4d2_image/send_image_tool.py +32 -32
- nonebot_plugin_l4d2_server/l4d2_image/steam.py +83 -83
- nonebot_plugin_l4d2_server/l4d2_image/vtfs.py +40 -40
- nonebot_plugin_l4d2_server/l4d2_queries/__init__.py +114 -114
- nonebot_plugin_l4d2_server/l4d2_queries/api.py +43 -43
- nonebot_plugin_l4d2_server/l4d2_queries/ohter.py +35 -25
- nonebot_plugin_l4d2_server/l4d2_queries/qqgroup.py +288 -288
- nonebot_plugin_l4d2_server/l4d2_server/__init__.py +61 -61
- nonebot_plugin_l4d2_server/l4d2_server/rcon.py +28 -28
- nonebot_plugin_l4d2_server/l4d2_server/workshop.py +50 -50
- nonebot_plugin_l4d2_server/l4d2_web/web.py +234 -234
- nonebot_plugin_l4d2_server/l4d2_web/webUI.py +241 -241
- nonebot_plugin_l4d2_server/message.py +58 -58
- nonebot_plugin_l4d2_server/seach.py +33 -33
- nonebot_plugin_l4d2_server/txt_to_img.py +64 -64
- nonebot_plugin_l4d2_server/utils.py +272 -272
- {nonebot_plugin_l4d2_server-0.5.0.dist-info → nonebot_plugin_l4d2_server-0.5.2.dist-info}/LICENSE +674 -674
- {nonebot_plugin_l4d2_server-0.5.0.dist-info → nonebot_plugin_l4d2_server-0.5.2.dist-info}/METADATA +47 -32
- nonebot_plugin_l4d2_server-0.5.2.dist-info/RECORD +54 -0
- nonebot_plugin_l4d2_server-0.5.0.dist-info/RECORD +0 -53
- {nonebot_plugin_l4d2_server-0.5.0.dist-info → nonebot_plugin_l4d2_server-0.5.2.dist-info}/WHEEL +0 -0
@@ -1,252 +1,252 @@
|
|
1
|
-
|
2
|
-
from nonebot.log import logger
|
3
|
-
|
4
|
-
import pandas as pd
|
5
|
-
from typing import List
|
6
|
-
|
7
|
-
from .analysis import df_to_guoguanlv
|
8
|
-
from ..seach import *
|
9
|
-
from ..l4d2_data.players import L4D2Player
|
10
|
-
from ..l4d2_image import out_png
|
11
|
-
# from .anne_telecom import ANNE_API
|
12
|
-
|
13
|
-
|
14
|
-
s = L4D2Player()
|
15
|
-
|
16
|
-
|
17
|
-
async def anne_html(name:str):
|
18
|
-
"""搜索里提取玩家信息,返回列表字典"""
|
19
|
-
data_title = anne_search(name)
|
20
|
-
data = data_title[0]
|
21
|
-
title = data_title[1]
|
22
|
-
if len(data) ==0 or data[0] == "No Player found.":
|
23
|
-
return {}
|
24
|
-
data_list:list = []
|
25
|
-
logger.info(data)
|
26
|
-
for i in data:
|
27
|
-
i:BeautifulSoup
|
28
|
-
try:
|
29
|
-
Rank = i.find('td', {'data-title': 'Rank:'}).text.strip()
|
30
|
-
player = i.find('td', {'data-title': 'Player:'}).text.strip()
|
31
|
-
points = i.find('td', {'data-title': 'Points:'}).text.strip()
|
32
|
-
# country = i.find('img')['alt']
|
33
|
-
playtime = i.find('td', {'data-title': 'Playtime:'}).text.strip()
|
34
|
-
last_online = i.find('td', {'data-title': 'Last Online:'}).text.strip()
|
35
|
-
except AttributeError:
|
36
|
-
Rank = i.find('td', {'data-title': '排名:'}).text.strip()
|
37
|
-
player = i.find('td', {'data-title': '玩家:'}).text.strip()
|
38
|
-
points = i.find('td', {'data-title': '分数:'}).text.strip()
|
39
|
-
playtime = i.find('td', {'data-title': '游玩时间:'}).text.strip()
|
40
|
-
last_online = i.find('td', {'data-title': '最后上线时间:'}).text.strip()
|
41
|
-
onclick = i['onclick']
|
42
|
-
steamid = onclick.split('=')[2].strip("'")
|
43
|
-
play_json ={
|
44
|
-
title[0]:Rank,
|
45
|
-
title[1]:player,
|
46
|
-
title[2]:points,
|
47
|
-
# title[3]:country,
|
48
|
-
title[3]:playtime,
|
49
|
-
title[4]:last_online,
|
50
|
-
title[5]:steamid
|
51
|
-
}
|
52
|
-
data_list.append(play_json)
|
53
|
-
logger.info("搜寻数据")
|
54
|
-
return data_list
|
55
|
-
|
56
|
-
def anne_html_msg(data_list:list):
|
57
|
-
"""从搜索结果的字典列表中,返回发送信息"""
|
58
|
-
mes = '搜索到以下玩家信息'
|
59
|
-
ns = 0
|
60
|
-
|
61
|
-
for one in data_list:
|
62
|
-
one:dict
|
63
|
-
ns += 1
|
64
|
-
x = 6
|
65
|
-
|
66
|
-
titles = list(one.keys())
|
67
|
-
for i in range(x):
|
68
|
-
mes += '\n' + titles[i] + ':' + str(one[titles[i]])
|
69
|
-
mes += '\n--------------------'
|
70
|
-
if ns>4:
|
71
|
-
break
|
72
|
-
return mes
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
async def write_player(id,msg:str,nickname:str):
|
78
|
-
"""绑定用户"""
|
79
|
-
# 判断是steam
|
80
|
-
print(msg)
|
81
|
-
if msg.startswith('STEAM'):
|
82
|
-
# try:
|
83
|
-
data_tuple = s._query_player_qq(id)
|
84
|
-
if data_tuple != None:
|
85
|
-
qq , nicknam , steamid = data_tuple
|
86
|
-
else:
|
87
|
-
nicknam = None
|
88
|
-
await s._add_player_all(id , nicknam , msg)
|
89
|
-
# except TypeError:
|
90
|
-
# await s._add_player_steamid(id , msg)
|
91
|
-
mes = '绑定成功喵~\nQQ:' + nickname +'\n' + 'steamid:'+msg
|
92
|
-
return mes
|
93
|
-
else:
|
94
|
-
# try:
|
95
|
-
data_tuple = s._query_player_qq(id)
|
96
|
-
if data_tuple != None:
|
97
|
-
id , nicknam , steamid = data_tuple
|
98
|
-
else:
|
99
|
-
steamid = None
|
100
|
-
await s._add_player_all(id , msg , steamid)
|
101
|
-
# except TypeError:
|
102
|
-
# await s._add_player_nickname(id , msg )
|
103
|
-
mes = '绑定成功喵~\nQQ:' + nickname +'\n' + 'steam昵称:'+msg
|
104
|
-
return mes
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
def del_player(id:str):
|
110
|
-
"""删除绑定信息,返回消息"""
|
111
|
-
if not s._query_player_qq(id):
|
112
|
-
return '你还没有绑定过,请使用[求生绑定+昵称/steamid]'
|
113
|
-
if s._delete_player:
|
114
|
-
return '删除成功喵~'
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
async def id_to_mes(name:str):
|
119
|
-
"""根据name从数据库,返回steamid、或者空白"""
|
120
|
-
data_tuple = await s.search_data(None,name,None)
|
121
|
-
print(data_tuple)
|
122
|
-
if data_tuple:
|
123
|
-
steamid = data_tuple[2]
|
124
|
-
return steamid
|
125
|
-
return None
|
126
|
-
|
127
|
-
|
128
|
-
def anne_rank_dict(name:str):
|
129
|
-
"""用steamid,查详情,输出字典"""
|
130
|
-
data_dict = {}
|
131
|
-
url =f'https://sb.trygek.com/l4d_stats/ranking/player.php?steamid={name}'
|
132
|
-
headers = {
|
133
|
-
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
|
134
|
-
}
|
135
|
-
data = httpx.get(url=url,headers=headers,timeout=5)
|
136
|
-
if data.status_code != 200:
|
137
|
-
return [f"查询错误,状态码{data.status_code}"]
|
138
|
-
data = data.content.decode('utf-8')
|
139
|
-
data = BeautifulSoup(data, 'html.parser')
|
140
|
-
detail = data.find_all('table')
|
141
|
-
n = 0
|
142
|
-
while n < 2:
|
143
|
-
data_list:List[dict] = []
|
144
|
-
detail2 = detail[n]
|
145
|
-
tr = detail2.find_all('tr')
|
146
|
-
for i in tr:
|
147
|
-
title = i.find('td', {'class': 'w-50'})
|
148
|
-
value = title.find_next_sibling('td')
|
149
|
-
new_dict = {title.text:value.text}
|
150
|
-
data_dict.update(new_dict)
|
151
|
-
data_list.append(data_dict)
|
152
|
-
n += 1
|
153
|
-
# 获取头像
|
154
|
-
element:str = data.find_all(attrs={"style": "cursor:pointer"})[0].get("onclick")
|
155
|
-
player_url = element.split("'")[1]
|
156
|
-
data_list[0].update({"个人资料":player_url})
|
157
|
-
# 获取一言
|
158
|
-
message = data.select("html body div.content.text-center.text-md-left div.container.text-left div.col-md-12.h-100 div.card-body.worldmap.d-flex.flex-column.justify-content-center.text-center span")
|
159
|
-
msg_list = []
|
160
|
-
for i in message:
|
161
|
-
msg_list.append(i.text)
|
162
|
-
data_list[0].update({"一言":msg_list})
|
163
|
-
return data_list
|
164
|
-
|
165
|
-
def anne_rank_dict_msg(data_list):
|
166
|
-
"""字典转msg"""
|
167
|
-
msg = ''
|
168
|
-
for data_dict in data_list:
|
169
|
-
mes = ''
|
170
|
-
for i in data_dict:
|
171
|
-
mes +='\n'+ i + data_dict[i]
|
172
|
-
mes += '\n--------------------'
|
173
|
-
msg += mes
|
174
|
-
return msg
|
175
|
-
|
176
|
-
|
177
|
-
async def anne_messgae(name:str,usr_id:str):
|
178
|
-
"""获取anne信息可输出信息"""
|
179
|
-
if name:
|
180
|
-
logger.info("关键词查询" + name)
|
181
|
-
if not name.startswith('STEAM'):
|
182
|
-
steamid = await id_to_mes(name)
|
183
|
-
if not steamid:
|
184
|
-
logger.info("没有找到qq,使用默认头像")
|
185
|
-
message = await anne_html(name)
|
186
|
-
usr_id = "1145149191810"
|
187
|
-
if len(message) == 0:
|
188
|
-
return '没有叫这个名字的...\n'
|
189
|
-
if len(message) > 1:
|
190
|
-
return anne_html_msg(message)
|
191
|
-
name = message[0]['steamid']
|
192
|
-
else:
|
193
|
-
name = steamid
|
194
|
-
# steamid
|
195
|
-
msg = anne_rank_dict(name)[0]
|
196
|
-
if type(msg) == dict:
|
197
|
-
msg.update(await df_to_guoguanlv(await anne_map_msg(name)))
|
198
|
-
logger.info('使用图片')
|
199
|
-
msg = await out_png(usr_id,msg)
|
200
|
-
return msg
|
201
|
-
else:
|
202
|
-
"""
|
203
|
-
1、qq>数据>没有数据,返回
|
204
|
-
2、qq>数据>steamid>查询
|
205
|
-
3、qq>数据>昵称>查询
|
206
|
-
"""
|
207
|
-
logger.info("qq信息查询")
|
208
|
-
data_tuple = s._query_player_qq(usr_id)
|
209
|
-
logger.info(data_tuple)
|
210
|
-
if data_tuple== None:
|
211
|
-
return f"没有绑定信息...请使用【求生绑定 xxx】\n"
|
212
|
-
# 只有名字,先查询数据在判断
|
213
|
-
elif data_tuple[2]:
|
214
|
-
name = data_tuple[2]
|
215
|
-
elif data_tuple[1]:
|
216
|
-
name = await id_to_mes(data_tuple[1])
|
217
|
-
logger.info(name)
|
218
|
-
if not name:
|
219
|
-
message = await anne_html(data_tuple[1])
|
220
|
-
usr_id = "1145149191810"
|
221
|
-
if len(message) == 0:
|
222
|
-
return '没有叫这个名字的...\n'
|
223
|
-
if len(message) > 1:
|
224
|
-
return anne_html_msg(message)
|
225
|
-
name = message[0]['steamid']
|
226
|
-
# name是steamid
|
227
|
-
msg = anne_rank_dict(name)[0]
|
228
|
-
if type(msg) == dict:
|
229
|
-
msg.update(await df_to_guoguanlv(await anne_map_msg(name)))
|
230
|
-
logger.info('使用图片')
|
231
|
-
msg = await out_png(usr_id,msg)
|
232
|
-
return msg
|
233
|
-
|
234
|
-
async def anne_map_msg(steamid:str):
|
235
|
-
"""steamid->地图信息"""
|
236
|
-
url = f"https://sb.trygek.com/l4d_stats/ranking/timedmaps.php?steamid={steamid}"
|
237
|
-
headers = {
|
238
|
-
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
|
239
|
-
}
|
240
|
-
data = httpx.get(url,headers=headers,timeout=5).content.decode('utf-8')
|
241
|
-
soup = BeautifulSoup(data, 'html.parser')
|
242
|
-
data_list = []
|
243
|
-
cards = soup.select('div.card.rounded-0')
|
244
|
-
for card in cards:
|
245
|
-
tbodies = card.select('tbody')
|
246
|
-
for tbody in tbodies:
|
247
|
-
rows = [td.text.strip() for td in tbody.find_all('td')]
|
248
|
-
for i in range(0, len(rows), 9):
|
249
|
-
row = rows[i:i+9]
|
250
|
-
data_list.append(row)
|
251
|
-
df = pd.DataFrame(data_list, columns=['游戏模式', '地图', '难度', '完成时间', '特感数量', '刷新间隔', 'B数使用', '刷特模式', 'Anne版本'])
|
1
|
+
|
2
|
+
from nonebot.log import logger
|
3
|
+
|
4
|
+
import pandas as pd
|
5
|
+
from typing import List
|
6
|
+
|
7
|
+
from .analysis import df_to_guoguanlv
|
8
|
+
from ..seach import *
|
9
|
+
from ..l4d2_data.players import L4D2Player
|
10
|
+
from ..l4d2_image import out_png
|
11
|
+
# from .anne_telecom import ANNE_API
|
12
|
+
|
13
|
+
|
14
|
+
s = L4D2Player()
|
15
|
+
|
16
|
+
|
17
|
+
async def anne_html(name:str):
|
18
|
+
"""搜索里提取玩家信息,返回列表字典"""
|
19
|
+
data_title = anne_search(name)
|
20
|
+
data = data_title[0]
|
21
|
+
title = data_title[1]
|
22
|
+
if len(data) ==0 or data[0] == "No Player found.":
|
23
|
+
return {}
|
24
|
+
data_list:list = []
|
25
|
+
logger.info(data)
|
26
|
+
for i in data:
|
27
|
+
i:BeautifulSoup
|
28
|
+
try:
|
29
|
+
Rank = i.find('td', {'data-title': 'Rank:'}).text.strip()
|
30
|
+
player = i.find('td', {'data-title': 'Player:'}).text.strip()
|
31
|
+
points = i.find('td', {'data-title': 'Points:'}).text.strip()
|
32
|
+
# country = i.find('img')['alt']
|
33
|
+
playtime = i.find('td', {'data-title': 'Playtime:'}).text.strip()
|
34
|
+
last_online = i.find('td', {'data-title': 'Last Online:'}).text.strip()
|
35
|
+
except AttributeError:
|
36
|
+
Rank = i.find('td', {'data-title': '排名:'}).text.strip()
|
37
|
+
player = i.find('td', {'data-title': '玩家:'}).text.strip()
|
38
|
+
points = i.find('td', {'data-title': '分数:'}).text.strip()
|
39
|
+
playtime = i.find('td', {'data-title': '游玩时间:'}).text.strip()
|
40
|
+
last_online = i.find('td', {'data-title': '最后上线时间:'}).text.strip()
|
41
|
+
onclick = i['onclick']
|
42
|
+
steamid = onclick.split('=')[2].strip("'")
|
43
|
+
play_json ={
|
44
|
+
title[0]:Rank,
|
45
|
+
title[1]:player,
|
46
|
+
title[2]:points,
|
47
|
+
# title[3]:country,
|
48
|
+
title[3]:playtime,
|
49
|
+
title[4]:last_online,
|
50
|
+
title[5]:steamid
|
51
|
+
}
|
52
|
+
data_list.append(play_json)
|
53
|
+
logger.info("搜寻数据")
|
54
|
+
return data_list
|
55
|
+
|
56
|
+
def anne_html_msg(data_list:list):
|
57
|
+
"""从搜索结果的字典列表中,返回发送信息"""
|
58
|
+
mes = '搜索到以下玩家信息'
|
59
|
+
ns = 0
|
60
|
+
|
61
|
+
for one in data_list:
|
62
|
+
one:dict
|
63
|
+
ns += 1
|
64
|
+
x = 6
|
65
|
+
|
66
|
+
titles = list(one.keys())
|
67
|
+
for i in range(x):
|
68
|
+
mes += '\n' + titles[i] + ':' + str(one[titles[i]])
|
69
|
+
mes += '\n--------------------'
|
70
|
+
if ns>4:
|
71
|
+
break
|
72
|
+
return mes
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
async def write_player(id,msg:str,nickname:str):
|
78
|
+
"""绑定用户"""
|
79
|
+
# 判断是steam
|
80
|
+
print(msg)
|
81
|
+
if msg.startswith('STEAM'):
|
82
|
+
# try:
|
83
|
+
data_tuple = s._query_player_qq(id)
|
84
|
+
if data_tuple != None:
|
85
|
+
qq , nicknam , steamid = data_tuple
|
86
|
+
else:
|
87
|
+
nicknam = None
|
88
|
+
await s._add_player_all(id , nicknam , msg)
|
89
|
+
# except TypeError:
|
90
|
+
# await s._add_player_steamid(id , msg)
|
91
|
+
mes = '绑定成功喵~\nQQ:' + nickname +'\n' + 'steamid:'+msg
|
92
|
+
return mes
|
93
|
+
else:
|
94
|
+
# try:
|
95
|
+
data_tuple = s._query_player_qq(id)
|
96
|
+
if data_tuple != None:
|
97
|
+
id , nicknam , steamid = data_tuple
|
98
|
+
else:
|
99
|
+
steamid = None
|
100
|
+
await s._add_player_all(id , msg , steamid)
|
101
|
+
# except TypeError:
|
102
|
+
# await s._add_player_nickname(id , msg )
|
103
|
+
mes = '绑定成功喵~\nQQ:' + nickname +'\n' + 'steam昵称:'+msg
|
104
|
+
return mes
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
def del_player(id:str):
|
110
|
+
"""删除绑定信息,返回消息"""
|
111
|
+
if not s._query_player_qq(id):
|
112
|
+
return '你还没有绑定过,请使用[求生绑定+昵称/steamid]'
|
113
|
+
if s._delete_player:
|
114
|
+
return '删除成功喵~'
|
115
|
+
|
116
|
+
|
117
|
+
|
118
|
+
async def id_to_mes(name:str):
|
119
|
+
"""根据name从数据库,返回steamid、或者空白"""
|
120
|
+
data_tuple = await s.search_data(None,name,None)
|
121
|
+
print(data_tuple)
|
122
|
+
if data_tuple:
|
123
|
+
steamid = data_tuple[2]
|
124
|
+
return steamid
|
125
|
+
return None
|
126
|
+
|
127
|
+
|
128
|
+
def anne_rank_dict(name:str):
|
129
|
+
"""用steamid,查详情,输出字典"""
|
130
|
+
data_dict = {}
|
131
|
+
url =f'https://sb.trygek.com/l4d_stats/ranking/player.php?steamid={name}'
|
132
|
+
headers = {
|
133
|
+
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
|
134
|
+
}
|
135
|
+
data = httpx.get(url=url,headers=headers,timeout=5)
|
136
|
+
if data.status_code != 200:
|
137
|
+
return [f"查询错误,状态码{data.status_code}"]
|
138
|
+
data = data.content.decode('utf-8')
|
139
|
+
data = BeautifulSoup(data, 'html.parser')
|
140
|
+
detail = data.find_all('table')
|
141
|
+
n = 0
|
142
|
+
while n < 2:
|
143
|
+
data_list:List[dict] = []
|
144
|
+
detail2 = detail[n]
|
145
|
+
tr = detail2.find_all('tr')
|
146
|
+
for i in tr:
|
147
|
+
title = i.find('td', {'class': 'w-50'})
|
148
|
+
value = title.find_next_sibling('td')
|
149
|
+
new_dict = {title.text:value.text}
|
150
|
+
data_dict.update(new_dict)
|
151
|
+
data_list.append(data_dict)
|
152
|
+
n += 1
|
153
|
+
# 获取头像
|
154
|
+
element:str = data.find_all(attrs={"style": "cursor:pointer"})[0].get("onclick")
|
155
|
+
player_url = element.split("'")[1]
|
156
|
+
data_list[0].update({"个人资料":player_url})
|
157
|
+
# 获取一言
|
158
|
+
message = data.select("html body div.content.text-center.text-md-left div.container.text-left div.col-md-12.h-100 div.card-body.worldmap.d-flex.flex-column.justify-content-center.text-center span")
|
159
|
+
msg_list = []
|
160
|
+
for i in message:
|
161
|
+
msg_list.append(i.text)
|
162
|
+
data_list[0].update({"一言":msg_list})
|
163
|
+
return data_list
|
164
|
+
|
165
|
+
def anne_rank_dict_msg(data_list):
|
166
|
+
"""字典转msg"""
|
167
|
+
msg = ''
|
168
|
+
for data_dict in data_list:
|
169
|
+
mes = ''
|
170
|
+
for i in data_dict:
|
171
|
+
mes +='\n'+ i + data_dict[i]
|
172
|
+
mes += '\n--------------------'
|
173
|
+
msg += mes
|
174
|
+
return msg
|
175
|
+
|
176
|
+
|
177
|
+
async def anne_messgae(name:str,usr_id:str):
|
178
|
+
"""获取anne信息可输出信息"""
|
179
|
+
if name:
|
180
|
+
logger.info("关键词查询" + name)
|
181
|
+
if not name.startswith('STEAM'):
|
182
|
+
steamid = await id_to_mes(name)
|
183
|
+
if not steamid:
|
184
|
+
logger.info("没有找到qq,使用默认头像")
|
185
|
+
message = await anne_html(name)
|
186
|
+
usr_id = "1145149191810"
|
187
|
+
if len(message) == 0:
|
188
|
+
return '没有叫这个名字的...\n'
|
189
|
+
if len(message) > 1:
|
190
|
+
return anne_html_msg(message)
|
191
|
+
name = message[0]['steamid']
|
192
|
+
else:
|
193
|
+
name = steamid
|
194
|
+
# steamid
|
195
|
+
msg = anne_rank_dict(name)[0]
|
196
|
+
if type(msg) == dict:
|
197
|
+
msg.update(await df_to_guoguanlv(await anne_map_msg(name)))
|
198
|
+
logger.info('使用图片')
|
199
|
+
msg = await out_png(usr_id,msg)
|
200
|
+
return msg
|
201
|
+
else:
|
202
|
+
"""
|
203
|
+
1、qq>数据>没有数据,返回
|
204
|
+
2、qq>数据>steamid>查询
|
205
|
+
3、qq>数据>昵称>查询
|
206
|
+
"""
|
207
|
+
logger.info("qq信息查询")
|
208
|
+
data_tuple = s._query_player_qq(usr_id)
|
209
|
+
logger.info(data_tuple)
|
210
|
+
if data_tuple== None:
|
211
|
+
return f"没有绑定信息...请使用【求生绑定 xxx】\n"
|
212
|
+
# 只有名字,先查询数据在判断
|
213
|
+
elif data_tuple[2]:
|
214
|
+
name = data_tuple[2]
|
215
|
+
elif data_tuple[1]:
|
216
|
+
name = await id_to_mes(data_tuple[1])
|
217
|
+
logger.info(name)
|
218
|
+
if not name:
|
219
|
+
message = await anne_html(data_tuple[1])
|
220
|
+
usr_id = "1145149191810"
|
221
|
+
if len(message) == 0:
|
222
|
+
return '没有叫这个名字的...\n'
|
223
|
+
if len(message) > 1:
|
224
|
+
return anne_html_msg(message)
|
225
|
+
name = message[0]['steamid']
|
226
|
+
# name是steamid
|
227
|
+
msg = anne_rank_dict(name)[0]
|
228
|
+
if type(msg) == dict:
|
229
|
+
msg.update(await df_to_guoguanlv(await anne_map_msg(name)))
|
230
|
+
logger.info('使用图片')
|
231
|
+
msg = await out_png(usr_id,msg)
|
232
|
+
return msg
|
233
|
+
|
234
|
+
async def anne_map_msg(steamid:str):
|
235
|
+
"""steamid->地图信息"""
|
236
|
+
url = f"https://sb.trygek.com/l4d_stats/ranking/timedmaps.php?steamid={steamid}"
|
237
|
+
headers = {
|
238
|
+
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
|
239
|
+
}
|
240
|
+
data = httpx.get(url,headers=headers,timeout=5).content.decode('utf-8')
|
241
|
+
soup = BeautifulSoup(data, 'html.parser')
|
242
|
+
data_list = []
|
243
|
+
cards = soup.select('div.card.rounded-0')
|
244
|
+
for card in cards:
|
245
|
+
tbodies = card.select('tbody')
|
246
|
+
for tbody in tbodies:
|
247
|
+
rows = [td.text.strip() for td in tbody.find_all('td')]
|
248
|
+
for i in range(0, len(rows), 9):
|
249
|
+
row = rows[i:i+9]
|
250
|
+
data_list.append(row)
|
251
|
+
df = pd.DataFrame(data_list, columns=['游戏模式', '地图', '难度', '完成时间', '特感数量', '刷新间隔', 'B数使用', '刷特模式', 'Anne版本'])
|
252
252
|
return df
|
@@ -1,52 +1,52 @@
|
|
1
|
-
from .startand import SAVE_MAP,NUMBER_MAP
|
2
|
-
import pandas as pd
|
3
|
-
|
4
|
-
async def df_to_guoguanlv(df:pd.DataFrame):
|
5
|
-
"""分析救援关过图率"""
|
6
|
-
data = df[df['游戏模式'] == 'AnneHappy药役']
|
7
|
-
other = df[df['游戏模式'].isin(['牛牛冲刺', '单人装逼'])]
|
8
|
-
all_map = len(data['地图'])
|
9
|
-
other_map = len(other['地图'])
|
10
|
-
resen = 0
|
11
|
-
last_maps = {}
|
12
|
-
for m in SAVE_MAP:
|
13
|
-
prefix = m.split('m')[0]
|
14
|
-
if prefix in last_maps:
|
15
|
-
last_maps[prefix] = max(last_maps[prefix], m)
|
16
|
-
else:
|
17
|
-
last_maps[prefix] = m
|
18
|
-
|
19
|
-
map_counts = {}
|
20
|
-
|
21
|
-
n = 0
|
22
|
-
for key in last_maps:
|
23
|
-
count = len(data[data['地图'].str.startswith(key)])
|
24
|
-
if count == 0:
|
25
|
-
continue
|
26
|
-
last_map = last_maps[key]
|
27
|
-
map_count = len(data[data['地图'] == last_map])
|
28
|
-
map_counts[key] = map_count*NUMBER_MAP[n] / count
|
29
|
-
quan = count/all_map
|
30
|
-
resen += quan * map_counts[key]
|
31
|
-
n += 1
|
32
|
-
|
33
|
-
# result = []
|
34
|
-
# for i in range(1, 15):
|
35
|
-
# key = 'c{}'.format(i)
|
36
|
-
# if key in map_counts:
|
37
|
-
# result.append('{}:{}%'.format(key, round(map_counts[key] * 100)))
|
38
|
-
|
39
|
-
# print(result)
|
40
|
-
# result = '救援图过关率: {:.2%}'.format(resen)
|
41
|
-
|
42
|
-
# 加上特殊关卡
|
43
|
-
try:
|
44
|
-
resen += other_map / (all_map + other_map)
|
45
|
-
result = {"救援关":str('{:.2%}'.format(resen))}
|
46
|
-
except (TypeError,KeyError):
|
47
|
-
result = {"救援关":"错误"}
|
48
|
-
except ZeroDivisionError:
|
49
|
-
result = {"救援关":"0.00%"}
|
50
|
-
except:
|
51
|
-
result = {"救援关":"错误"}
|
1
|
+
from .startand import SAVE_MAP,NUMBER_MAP
|
2
|
+
import pandas as pd
|
3
|
+
|
4
|
+
async def df_to_guoguanlv(df:pd.DataFrame):
|
5
|
+
"""分析救援关过图率"""
|
6
|
+
data = df[df['游戏模式'] == 'AnneHappy药役']
|
7
|
+
other = df[df['游戏模式'].isin(['牛牛冲刺', '单人装逼'])]
|
8
|
+
all_map = len(data['地图'])
|
9
|
+
other_map = len(other['地图'])
|
10
|
+
resen = 0
|
11
|
+
last_maps = {}
|
12
|
+
for m in SAVE_MAP:
|
13
|
+
prefix = m.split('m')[0]
|
14
|
+
if prefix in last_maps:
|
15
|
+
last_maps[prefix] = max(last_maps[prefix], m)
|
16
|
+
else:
|
17
|
+
last_maps[prefix] = m
|
18
|
+
|
19
|
+
map_counts = {}
|
20
|
+
|
21
|
+
n = 0
|
22
|
+
for key in last_maps:
|
23
|
+
count = len(data[data['地图'].str.startswith(key)])
|
24
|
+
if count == 0:
|
25
|
+
continue
|
26
|
+
last_map = last_maps[key]
|
27
|
+
map_count = len(data[data['地图'] == last_map])
|
28
|
+
map_counts[key] = map_count*NUMBER_MAP[n] / count
|
29
|
+
quan = count/all_map
|
30
|
+
resen += quan * map_counts[key]
|
31
|
+
n += 1
|
32
|
+
|
33
|
+
# result = []
|
34
|
+
# for i in range(1, 15):
|
35
|
+
# key = 'c{}'.format(i)
|
36
|
+
# if key in map_counts:
|
37
|
+
# result.append('{}:{}%'.format(key, round(map_counts[key] * 100)))
|
38
|
+
|
39
|
+
# print(result)
|
40
|
+
# result = '救援图过关率: {:.2%}'.format(resen)
|
41
|
+
|
42
|
+
# 加上特殊关卡
|
43
|
+
try:
|
44
|
+
resen += other_map / (all_map + other_map)
|
45
|
+
result = {"救援关":str('{:.2%}'.format(resen))}
|
46
|
+
except (TypeError,KeyError):
|
47
|
+
result = {"救援关":"错误"}
|
48
|
+
except ZeroDivisionError:
|
49
|
+
result = {"救援关":"0.00%"}
|
50
|
+
except:
|
51
|
+
result = {"救援关":"错误"}
|
52
52
|
return result
|