nonebot-plugin-l4d2-server 0.5.1__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 +364 -359
- nonebot_plugin_l4d2_server/__init__.py +1 -1
- nonebot_plugin_l4d2_server/chrome.py +44 -44
- nonebot_plugin_l4d2_server/command.py +232 -232
- nonebot_plugin_l4d2_server/config.py +210 -210
- 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/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 -63
- 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 -35
- 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 -252
- nonebot_plugin_l4d2_server/l4d2_web/webUI.py +241 -245
- 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.1.dist-info → nonebot_plugin_l4d2_server-0.5.2.dist-info}/LICENSE +674 -674
- {nonebot_plugin_l4d2_server-0.5.1.dist-info → nonebot_plugin_l4d2_server-0.5.2.dist-info}/METADATA +6 -1
- nonebot_plugin_l4d2_server-0.5.2.dist-info/RECORD +54 -0
- {nonebot_plugin_l4d2_server-0.5.1.dist-info → nonebot_plugin_l4d2_server-0.5.2.dist-info}/WHEEL +1 -1
- nonebot_plugin_l4d2_server-0.5.1.dist-info/RECORD +0 -54
@@ -1,32 +1,32 @@
|
|
1
|
-
from io import BytesIO
|
2
|
-
from pathlib import Path
|
3
|
-
from typing import Union
|
4
|
-
from base64 import b64encode
|
5
|
-
|
6
|
-
from PIL import Image
|
7
|
-
|
8
|
-
|
9
|
-
async def convert_img(
|
10
|
-
img: Union[Image.Image, str, Path, bytes], is_base64: bool = False
|
11
|
-
):
|
12
|
-
"""
|
13
|
-
:说明:
|
14
|
-
将PIL.Image对象转换为bytes或者base64格式。
|
15
|
-
:参数:
|
16
|
-
* img (Image): 图片。
|
17
|
-
* is_base64 (bool): 是否转换为base64格式, 不填默认转为bytes。
|
18
|
-
:返回:
|
19
|
-
* res: bytes对象或base64编码图片。
|
20
|
-
"""
|
21
|
-
if isinstance(img, Image.Image):
|
22
|
-
img = img.convert('RGBA')
|
23
|
-
result_buffer = BytesIO()
|
24
|
-
img.save(result_buffer, format='PNG', quality=80, subsampling=0)
|
25
|
-
res = result_buffer.getvalue()
|
26
|
-
if is_base64:
|
27
|
-
res = b64encode(res).decode()
|
28
|
-
return res
|
29
|
-
elif isinstance(img, bytes):
|
30
|
-
return b64encode(img).decode()
|
31
|
-
else:
|
32
|
-
return f'[CQ:image,file=file:///{str(img)}]'
|
1
|
+
from io import BytesIO
|
2
|
+
from pathlib import Path
|
3
|
+
from typing import Union
|
4
|
+
from base64 import b64encode
|
5
|
+
|
6
|
+
from PIL import Image
|
7
|
+
|
8
|
+
|
9
|
+
async def convert_img(
|
10
|
+
img: Union[Image.Image, str, Path, bytes], is_base64: bool = False
|
11
|
+
):
|
12
|
+
"""
|
13
|
+
:说明:
|
14
|
+
将PIL.Image对象转换为bytes或者base64格式。
|
15
|
+
:参数:
|
16
|
+
* img (Image): 图片。
|
17
|
+
* is_base64 (bool): 是否转换为base64格式, 不填默认转为bytes。
|
18
|
+
:返回:
|
19
|
+
* res: bytes对象或base64编码图片。
|
20
|
+
"""
|
21
|
+
if isinstance(img, Image.Image):
|
22
|
+
img = img.convert('RGBA')
|
23
|
+
result_buffer = BytesIO()
|
24
|
+
img.save(result_buffer, format='PNG', quality=80, subsampling=0)
|
25
|
+
res = result_buffer.getvalue()
|
26
|
+
if is_base64:
|
27
|
+
res = b64encode(res).decode()
|
28
|
+
return res
|
29
|
+
elif isinstance(img, bytes):
|
30
|
+
return b64encode(img).decode()
|
31
|
+
else:
|
32
|
+
return f'[CQ:image,file=file:///{str(img)}]'
|
@@ -1,83 +1,83 @@
|
|
1
|
-
# from PIL import Image
|
2
|
-
import httpx
|
3
|
-
import aiohttp
|
4
|
-
# from bs4 import BeautifulSoup
|
5
|
-
from urllib.parse import unquote
|
6
|
-
|
7
|
-
|
8
|
-
# async def web_player(url) -> Image :
|
9
|
-
# """steam个人资料获取头像"""
|
10
|
-
# data = BeautifulSoup(await url_for_byte(url), 'html.parser')
|
11
|
-
# print(data)
|
12
|
-
# head = data.find("div", class_="playerAvatarAutoSizeInner")
|
13
|
-
# img_elements = head.find_all("img")
|
14
|
-
# if len(img_elements)== 1:
|
15
|
-
# for img_element in img_elements:
|
16
|
-
# head = await url_for_byte(img_element["src"])
|
17
|
-
# im = Image.open(io.BytesIO(head)).resize((225, 225)).convert("RGBA")
|
18
|
-
# if len(img_elements) == 2:
|
19
|
-
# head,headd = img_elements
|
20
|
-
# head = await url_for_byte(img_element["src"])
|
21
|
-
# head = await url_for_byte(img_element["src"])
|
22
|
-
# # 下面是边框,不一定有
|
23
|
-
# try:
|
24
|
-
# headd = data.select("html.responsive body.flat_page.profile_page.has_profile_background.GhostTheme.responsive_page div.responsive_page_frame.with_header div.responsive_page_content div#responsive_page_template_content.responsive_page_template_content div.no_header.profile_page.has_profile_background div.profile_header_bg div.profile_header_bg_texture div.profile_header div.profile_header_content div.playerAvatar.profile_header_size.in-game div.playerAvatarAutoSizeInner div.profile_avatar_frame img")
|
25
|
-
# im2 = Image.open(io.BytesIO(headd)).resize((185, 185)).convert("RGBA")
|
26
|
-
# r, g, b, a2 = im2.split()
|
27
|
-
# # im.paste(im2,(20,20),mask=a2)
|
28
|
-
# except IndexError:
|
29
|
-
# pass
|
30
|
-
# return im
|
31
|
-
|
32
|
-
# async def url_for_byte(url):
|
33
|
-
# """所有代理_url终将绳之以法"""
|
34
|
-
# if not l4_proxies:
|
35
|
-
# print("代理不存在")
|
36
|
-
# data = await url_to_byte(url)
|
37
|
-
# headers = {
|
38
|
-
# 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
|
39
|
-
# }
|
40
|
-
# data = httpx.get(url,headers=headers,proxies=l4_proxies,timeout=60,verify=False).content
|
41
|
-
# return data
|
42
|
-
async def url_to_byte(url:str,filename:str =''):
|
43
|
-
"""获取URL数据的字节流"""
|
44
|
-
headers = {
|
45
|
-
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
|
46
|
-
}
|
47
|
-
async with aiohttp.ClientSession() as session:
|
48
|
-
async with session.get(url, headers=headers, timeout=600) as response:
|
49
|
-
if response.status == 200:
|
50
|
-
return await response.read()
|
51
|
-
else:
|
52
|
-
return None
|
53
|
-
|
54
|
-
async def url_to_byte_name(url:str,filename:str =''):
|
55
|
-
"""获取URL数据的字节流"""
|
56
|
-
headers = {
|
57
|
-
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
|
58
|
-
}
|
59
|
-
if filename == "htp":
|
60
|
-
response = httpx.get(url,headers=headers,timeout=600)
|
61
|
-
content_disposition:str = response.headers.get("Content-Disposition")
|
62
|
-
if not content_disposition:
|
63
|
-
return None
|
64
|
-
elif "''" in content_disposition:
|
65
|
-
file_name = content_disposition.split("''")[-1]
|
66
|
-
else:
|
67
|
-
file_name = content_disposition
|
68
|
-
file_name = unquote(file_name)
|
69
|
-
return [response.read(),file_name]
|
70
|
-
else:
|
71
|
-
async with aiohttp.ClientSession() as session:
|
72
|
-
async with session.get(url, headers=headers, timeout=600) as response:
|
73
|
-
content_disposition:str = response.headers.get("Content-Disposition")
|
74
|
-
if "''" in content_disposition:
|
75
|
-
file_name = content_disposition.split("''")[-1]
|
76
|
-
else:
|
77
|
-
file_name = content_disposition
|
78
|
-
file_name = unquote(file_name)
|
79
|
-
if response.status == 200:
|
80
|
-
return [await response.read(),file_name]
|
81
|
-
else:
|
82
|
-
return None
|
83
|
-
|
1
|
+
# from PIL import Image
|
2
|
+
import httpx
|
3
|
+
import aiohttp
|
4
|
+
# from bs4 import BeautifulSoup
|
5
|
+
from urllib.parse import unquote
|
6
|
+
|
7
|
+
|
8
|
+
# async def web_player(url) -> Image :
|
9
|
+
# """steam个人资料获取头像"""
|
10
|
+
# data = BeautifulSoup(await url_for_byte(url), 'html.parser')
|
11
|
+
# print(data)
|
12
|
+
# head = data.find("div", class_="playerAvatarAutoSizeInner")
|
13
|
+
# img_elements = head.find_all("img")
|
14
|
+
# if len(img_elements)== 1:
|
15
|
+
# for img_element in img_elements:
|
16
|
+
# head = await url_for_byte(img_element["src"])
|
17
|
+
# im = Image.open(io.BytesIO(head)).resize((225, 225)).convert("RGBA")
|
18
|
+
# if len(img_elements) == 2:
|
19
|
+
# head,headd = img_elements
|
20
|
+
# head = await url_for_byte(img_element["src"])
|
21
|
+
# head = await url_for_byte(img_element["src"])
|
22
|
+
# # 下面是边框,不一定有
|
23
|
+
# try:
|
24
|
+
# headd = data.select("html.responsive body.flat_page.profile_page.has_profile_background.GhostTheme.responsive_page div.responsive_page_frame.with_header div.responsive_page_content div#responsive_page_template_content.responsive_page_template_content div.no_header.profile_page.has_profile_background div.profile_header_bg div.profile_header_bg_texture div.profile_header div.profile_header_content div.playerAvatar.profile_header_size.in-game div.playerAvatarAutoSizeInner div.profile_avatar_frame img")
|
25
|
+
# im2 = Image.open(io.BytesIO(headd)).resize((185, 185)).convert("RGBA")
|
26
|
+
# r, g, b, a2 = im2.split()
|
27
|
+
# # im.paste(im2,(20,20),mask=a2)
|
28
|
+
# except IndexError:
|
29
|
+
# pass
|
30
|
+
# return im
|
31
|
+
|
32
|
+
# async def url_for_byte(url):
|
33
|
+
# """所有代理_url终将绳之以法"""
|
34
|
+
# if not l4_proxies:
|
35
|
+
# print("代理不存在")
|
36
|
+
# data = await url_to_byte(url)
|
37
|
+
# headers = {
|
38
|
+
# 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
|
39
|
+
# }
|
40
|
+
# data = httpx.get(url,headers=headers,proxies=l4_proxies,timeout=60,verify=False).content
|
41
|
+
# return data
|
42
|
+
async def url_to_byte(url:str,filename:str =''):
|
43
|
+
"""获取URL数据的字节流"""
|
44
|
+
headers = {
|
45
|
+
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
|
46
|
+
}
|
47
|
+
async with aiohttp.ClientSession() as session:
|
48
|
+
async with session.get(url, headers=headers, timeout=600) as response:
|
49
|
+
if response.status == 200:
|
50
|
+
return await response.read()
|
51
|
+
else:
|
52
|
+
return None
|
53
|
+
|
54
|
+
async def url_to_byte_name(url:str,filename:str =''):
|
55
|
+
"""获取URL数据的字节流"""
|
56
|
+
headers = {
|
57
|
+
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
|
58
|
+
}
|
59
|
+
if filename == "htp":
|
60
|
+
response = httpx.get(url,headers=headers,timeout=600)
|
61
|
+
content_disposition:str = response.headers.get("Content-Disposition")
|
62
|
+
if not content_disposition:
|
63
|
+
return None
|
64
|
+
elif "''" in content_disposition:
|
65
|
+
file_name = content_disposition.split("''")[-1]
|
66
|
+
else:
|
67
|
+
file_name = content_disposition
|
68
|
+
file_name = unquote(file_name)
|
69
|
+
return [response.read(),file_name]
|
70
|
+
else:
|
71
|
+
async with aiohttp.ClientSession() as session:
|
72
|
+
async with session.get(url, headers=headers, timeout=600) as response:
|
73
|
+
content_disposition:str = response.headers.get("Content-Disposition")
|
74
|
+
if "''" in content_disposition:
|
75
|
+
file_name = content_disposition.split("''")[-1]
|
76
|
+
else:
|
77
|
+
file_name = content_disposition
|
78
|
+
file_name = unquote(file_name)
|
79
|
+
if response.status == 200:
|
80
|
+
return [await response.read(),file_name]
|
81
|
+
else:
|
82
|
+
return None
|
83
|
+
|
@@ -1,40 +1,40 @@
|
|
1
|
-
|
2
|
-
from PIL import Image
|
3
|
-
from nonebot.log import logger
|
4
|
-
from io import BytesIO
|
5
|
-
# import sys
|
6
|
-
# sys.modules["srctools._cy_vtf_readwrite"] = None
|
7
|
-
from srctools.vtf import VTF, ImageFormats
|
8
|
-
|
9
|
-
async def img_to_vtf(pic_byte:bytes,tag) -> BytesIO:
|
10
|
-
pic = BytesIO(pic_byte)
|
11
|
-
pic = Image.open(pic).convert('RGBA')
|
12
|
-
vtf_io = BytesIO()
|
13
|
-
vtf_ = VTF(1024, 1024, fmt = ImageFormats.DXT5,thumb_fmt = ImageFormats.DXT1,version=(7,2))
|
14
|
-
if tag == '覆盖':
|
15
|
-
logger.info(tag)
|
16
|
-
img2 = Image.new('RGBA',(1024, 1024), (255, 255, 255,0))
|
17
|
-
r, g, b, a = pic.split()
|
18
|
-
img2.paste(pic,mask=a)
|
19
|
-
pic = pic.resize((1024,1024))
|
20
|
-
elif tag == '填充':
|
21
|
-
w, h = pic.size
|
22
|
-
if w > h:
|
23
|
-
ratio = 1024/w
|
24
|
-
new_width = 1024
|
25
|
-
new_height = int(h * ratio)
|
26
|
-
else:
|
27
|
-
ratio = 1024/h
|
28
|
-
new_height = 1024
|
29
|
-
new_width = int(w * ratio)
|
30
|
-
pic = pic.resize((new_width, new_height), Image.ANTIALIAS)
|
31
|
-
background = Image.new('RGBA', (1024, 1024), (255, 255, 255, 0))
|
32
|
-
background.paste(pic, ((1024-new_width)//2, (1024-new_height)//2))
|
33
|
-
pic = background
|
34
|
-
else:
|
35
|
-
logger.info('拉伸')
|
36
|
-
pic = pic.resize((1024,1024))
|
37
|
-
largest_frame = vtf_.get()
|
38
|
-
largest_frame.copy_from(pic.tobytes(), ImageFormats.RGBA8888)
|
39
|
-
vtf_.save(vtf_io,version=(7,2))
|
40
|
-
return vtf_io
|
1
|
+
|
2
|
+
from PIL import Image
|
3
|
+
from nonebot.log import logger
|
4
|
+
from io import BytesIO
|
5
|
+
# import sys
|
6
|
+
# sys.modules["srctools._cy_vtf_readwrite"] = None
|
7
|
+
from srctools.vtf import VTF, ImageFormats
|
8
|
+
|
9
|
+
async def img_to_vtf(pic_byte:bytes,tag) -> BytesIO:
|
10
|
+
pic = BytesIO(pic_byte)
|
11
|
+
pic = Image.open(pic).convert('RGBA')
|
12
|
+
vtf_io = BytesIO()
|
13
|
+
vtf_ = VTF(1024, 1024, fmt = ImageFormats.DXT5,thumb_fmt = ImageFormats.DXT1,version=(7,2))
|
14
|
+
if tag == '覆盖':
|
15
|
+
logger.info(tag)
|
16
|
+
img2 = Image.new('RGBA',(1024, 1024), (255, 255, 255,0))
|
17
|
+
r, g, b, a = pic.split()
|
18
|
+
img2.paste(pic,mask=a)
|
19
|
+
pic = pic.resize((1024,1024))
|
20
|
+
elif tag == '填充':
|
21
|
+
w, h = pic.size
|
22
|
+
if w > h:
|
23
|
+
ratio = 1024/w
|
24
|
+
new_width = 1024
|
25
|
+
new_height = int(h * ratio)
|
26
|
+
else:
|
27
|
+
ratio = 1024/h
|
28
|
+
new_height = 1024
|
29
|
+
new_width = int(w * ratio)
|
30
|
+
pic = pic.resize((new_width, new_height), Image.ANTIALIAS)
|
31
|
+
background = Image.new('RGBA', (1024, 1024), (255, 255, 255, 0))
|
32
|
+
background.paste(pic, ((1024-new_width)//2, (1024-new_height)//2))
|
33
|
+
pic = background
|
34
|
+
else:
|
35
|
+
logger.info('拉伸')
|
36
|
+
pic = pic.resize((1024,1024))
|
37
|
+
largest_frame = vtf_.get()
|
38
|
+
largest_frame.copy_from(pic.tobytes(), ImageFormats.RGBA8888)
|
39
|
+
vtf_.save(vtf_io,version=(7,2))
|
40
|
+
return vtf_io
|
@@ -1,114 +1,114 @@
|
|
1
|
-
import a2s
|
2
|
-
from typing import List
|
3
|
-
|
4
|
-
async def queries(ip:str,port:int):
|
5
|
-
port = int(port)
|
6
|
-
msg_dict = await queries_dict(ip,port)
|
7
|
-
message = 'ip:' + msg_dict['ip'] + '\n'
|
8
|
-
message += '名称:' + msg_dict['name'] + '\n'
|
9
|
-
message += f"地图:{msg_dict['map_']}\n"
|
10
|
-
message += f"延迟:{msg_dict['ping']}\n"
|
11
|
-
message += f"玩家:{msg_dict['players']} / {msg_dict['max_players']}\n"
|
12
|
-
return message
|
13
|
-
|
14
|
-
async def queries_dict(ip:str,port:int) -> dict:
|
15
|
-
port = int(port)
|
16
|
-
ip = str(ip)
|
17
|
-
msg_dict = {}
|
18
|
-
# message_dict = await l4d(ip,port)
|
19
|
-
msg:a2s.SourceInfo = await a2s.ainfo((ip,port))
|
20
|
-
# message_dict = await l4d2.server(ip,port,times=5)
|
21
|
-
msg_dict['folder'] = msg.folder
|
22
|
-
msg_dict['name'] = msg.server_name
|
23
|
-
msg_dict['map_'] = msg.map_name
|
24
|
-
msg_dict['players'] = msg.player_count
|
25
|
-
msg_dict['max_players'] = msg.max_players
|
26
|
-
msg_dict['rank_players'] = f'{msg.player_count}/{msg.max_players}'
|
27
|
-
msg_dict['ip'] = str(ip) + ':' +str(port)
|
28
|
-
msg_dict['ping'] = f"{msg.ping*1000:.0f}ms"
|
29
|
-
msg_dict['system'] = f"{msg.platform}.svg"
|
30
|
-
if msg_dict['players'] < msg_dict['max_players']:
|
31
|
-
msg_dict['enabled'] = True
|
32
|
-
else:
|
33
|
-
msg_dict['enabled'] = False
|
34
|
-
return msg_dict
|
35
|
-
|
36
|
-
async def player_queries_anne_dict(ip:str,port:int):
|
37
|
-
"""anne算法返回玩家"""
|
38
|
-
port = int(port)
|
39
|
-
# message_dic = await l4d2.APlayer(ip,port,times=5)
|
40
|
-
message_list:List[a2s.Player] = await a2s.aplayers((ip,port))
|
41
|
-
msg_list = []
|
42
|
-
if message_list != []:
|
43
|
-
for i in message_list:
|
44
|
-
msg_list.append({
|
45
|
-
'name':i.name,
|
46
|
-
'Score':i.score,
|
47
|
-
'Duration':await convert_duration(i.duration)
|
48
|
-
})
|
49
|
-
return msg_list
|
50
|
-
|
51
|
-
# async def player_queries_dict(ip:str,port:int):
|
52
|
-
# """一般算法返回玩家"""
|
53
|
-
# port = int(port)
|
54
|
-
# new_dict = {}
|
55
|
-
# message_dic = await l4d2.APlayer(ip,port,times=5)
|
56
|
-
# if message_dic == {}:
|
57
|
-
# new_dict['header'] = 0
|
58
|
-
# else:
|
59
|
-
# pass
|
60
|
-
# new_list = []
|
61
|
-
# for i in message_dic['Players']:
|
62
|
-
# new_list.append(i['Name'])
|
63
|
-
# new_dict.update({'Players':new_list})
|
64
|
-
# return new_dict
|
65
|
-
|
66
|
-
async def player_queries(ip:str,port:int):
|
67
|
-
port = int(port)
|
68
|
-
message_list = await player_queries_anne_dict(ip,port)
|
69
|
-
return await msg_ip_to_list(message_list)
|
70
|
-
|
71
|
-
async def msg_ip_to_list(message_list:list):
|
72
|
-
message = ''
|
73
|
-
n = 0
|
74
|
-
if message_list == []:
|
75
|
-
message += '服务器里,是空空的呢\n'
|
76
|
-
else:
|
77
|
-
max_duration_len = max([len(str(i['Duration'])) for i in message_list])
|
78
|
-
max_score_len = max([len(str(i['Score'])) for i in message_list])
|
79
|
-
for i in message_list:
|
80
|
-
print(i)
|
81
|
-
n += 1
|
82
|
-
name = i['name']
|
83
|
-
Score = i['Score']
|
84
|
-
if Score == '0':
|
85
|
-
Score = '摸'
|
86
|
-
Duration = i['Duration']
|
87
|
-
soc = "[{:>{}}]".format(Score,max_score_len)
|
88
|
-
dur = "{:^{}}".format(Duration, max_duration_len)
|
89
|
-
message += f'{soc} | {dur} | {name} \n'
|
90
|
-
return message
|
91
|
-
|
92
|
-
async def convert_duration(duration: int) -> str:
|
93
|
-
minutes, seconds = divmod(duration, 60)
|
94
|
-
hours, minutes = divmod(minutes, 60)
|
95
|
-
time_str = ""
|
96
|
-
if hours > 0:
|
97
|
-
time_str += f"{int(hours)}h "
|
98
|
-
if minutes > 0 or hours > 0:
|
99
|
-
time_str += f"{int(minutes)}m "
|
100
|
-
time_str += f"{int(seconds)}s"
|
101
|
-
return time_str.strip()
|
102
|
-
|
103
|
-
async def server_rule_dict(ip:str,port:int):
|
104
|
-
port = int(port)
|
105
|
-
ip = str(ip)
|
106
|
-
msg_dict = {}
|
107
|
-
# message_dict = await l4d(ip,port)
|
108
|
-
try:
|
109
|
-
msg:dict = await a2s.arules((ip,port))
|
110
|
-
msg_dict['tick'] = msg['l4d2_tickrate_enabler'] + "tick"
|
111
|
-
except:
|
112
|
-
msg_dict['tick'] = ''
|
113
|
-
return msg_dict
|
114
|
-
|
1
|
+
import a2s
|
2
|
+
from typing import List
|
3
|
+
|
4
|
+
async def queries(ip:str,port:int):
|
5
|
+
port = int(port)
|
6
|
+
msg_dict = await queries_dict(ip,port)
|
7
|
+
message = 'ip:' + msg_dict['ip'] + '\n'
|
8
|
+
message += '名称:' + msg_dict['name'] + '\n'
|
9
|
+
message += f"地图:{msg_dict['map_']}\n"
|
10
|
+
message += f"延迟:{msg_dict['ping']}\n"
|
11
|
+
message += f"玩家:{msg_dict['players']} / {msg_dict['max_players']}\n"
|
12
|
+
return message
|
13
|
+
|
14
|
+
async def queries_dict(ip:str,port:int) -> dict:
|
15
|
+
port = int(port)
|
16
|
+
ip = str(ip)
|
17
|
+
msg_dict = {}
|
18
|
+
# message_dict = await l4d(ip,port)
|
19
|
+
msg:a2s.SourceInfo = await a2s.ainfo((ip,port))
|
20
|
+
# message_dict = await l4d2.server(ip,port,times=5)
|
21
|
+
msg_dict['folder'] = msg.folder
|
22
|
+
msg_dict['name'] = msg.server_name
|
23
|
+
msg_dict['map_'] = msg.map_name
|
24
|
+
msg_dict['players'] = msg.player_count
|
25
|
+
msg_dict['max_players'] = msg.max_players
|
26
|
+
msg_dict['rank_players'] = f'{msg.player_count}/{msg.max_players}'
|
27
|
+
msg_dict['ip'] = str(ip) + ':' +str(port)
|
28
|
+
msg_dict['ping'] = f"{msg.ping*1000:.0f}ms"
|
29
|
+
msg_dict['system'] = f"{msg.platform}.svg"
|
30
|
+
if msg_dict['players'] < msg_dict['max_players']:
|
31
|
+
msg_dict['enabled'] = True
|
32
|
+
else:
|
33
|
+
msg_dict['enabled'] = False
|
34
|
+
return msg_dict
|
35
|
+
|
36
|
+
async def player_queries_anne_dict(ip:str,port:int):
|
37
|
+
"""anne算法返回玩家"""
|
38
|
+
port = int(port)
|
39
|
+
# message_dic = await l4d2.APlayer(ip,port,times=5)
|
40
|
+
message_list:List[a2s.Player] = await a2s.aplayers((ip,port))
|
41
|
+
msg_list = []
|
42
|
+
if message_list != []:
|
43
|
+
for i in message_list:
|
44
|
+
msg_list.append({
|
45
|
+
'name':i.name,
|
46
|
+
'Score':i.score,
|
47
|
+
'Duration':await convert_duration(i.duration)
|
48
|
+
})
|
49
|
+
return msg_list
|
50
|
+
|
51
|
+
# async def player_queries_dict(ip:str,port:int):
|
52
|
+
# """一般算法返回玩家"""
|
53
|
+
# port = int(port)
|
54
|
+
# new_dict = {}
|
55
|
+
# message_dic = await l4d2.APlayer(ip,port,times=5)
|
56
|
+
# if message_dic == {}:
|
57
|
+
# new_dict['header'] = 0
|
58
|
+
# else:
|
59
|
+
# pass
|
60
|
+
# new_list = []
|
61
|
+
# for i in message_dic['Players']:
|
62
|
+
# new_list.append(i['Name'])
|
63
|
+
# new_dict.update({'Players':new_list})
|
64
|
+
# return new_dict
|
65
|
+
|
66
|
+
async def player_queries(ip:str,port:int):
|
67
|
+
port = int(port)
|
68
|
+
message_list = await player_queries_anne_dict(ip,port)
|
69
|
+
return await msg_ip_to_list(message_list)
|
70
|
+
|
71
|
+
async def msg_ip_to_list(message_list:list):
|
72
|
+
message = ''
|
73
|
+
n = 0
|
74
|
+
if message_list == []:
|
75
|
+
message += '服务器里,是空空的呢\n'
|
76
|
+
else:
|
77
|
+
max_duration_len = max([len(str(i['Duration'])) for i in message_list])
|
78
|
+
max_score_len = max([len(str(i['Score'])) for i in message_list])
|
79
|
+
for i in message_list:
|
80
|
+
print(i)
|
81
|
+
n += 1
|
82
|
+
name = i['name']
|
83
|
+
Score = i['Score']
|
84
|
+
if Score == '0':
|
85
|
+
Score = '摸'
|
86
|
+
Duration = i['Duration']
|
87
|
+
soc = "[{:>{}}]".format(Score,max_score_len)
|
88
|
+
dur = "{:^{}}".format(Duration, max_duration_len)
|
89
|
+
message += f'{soc} | {dur} | {name} \n'
|
90
|
+
return message
|
91
|
+
|
92
|
+
async def convert_duration(duration: int) -> str:
|
93
|
+
minutes, seconds = divmod(duration, 60)
|
94
|
+
hours, minutes = divmod(minutes, 60)
|
95
|
+
time_str = ""
|
96
|
+
if hours > 0:
|
97
|
+
time_str += f"{int(hours)}h "
|
98
|
+
if minutes > 0 or hours > 0:
|
99
|
+
time_str += f"{int(minutes)}m "
|
100
|
+
time_str += f"{int(seconds)}s"
|
101
|
+
return time_str.strip()
|
102
|
+
|
103
|
+
async def server_rule_dict(ip:str,port:int):
|
104
|
+
port = int(port)
|
105
|
+
ip = str(ip)
|
106
|
+
msg_dict = {}
|
107
|
+
# message_dict = await l4d(ip,port)
|
108
|
+
try:
|
109
|
+
msg:dict = await a2s.arules((ip,port))
|
110
|
+
msg_dict['tick'] = msg['l4d2_tickrate_enabler'] + "tick"
|
111
|
+
except:
|
112
|
+
msg_dict['tick'] = ''
|
113
|
+
return msg_dict
|
114
|
+
|
@@ -1,43 +1,43 @@
|
|
1
|
-
import httpx
|
2
|
-
from typing import List,Union
|
3
|
-
from nonebot.log import logger
|
4
|
-
|
5
|
-
async def seach_map(msg:Union[list,str],qq:str,key:str,mode:str = 'zh'):
|
6
|
-
url = "http://106.13.207.45:4015/l4d2"
|
7
|
-
json = {
|
8
|
-
"mode":mode,
|
9
|
-
"map_name":msg,
|
10
|
-
"qq":qq,
|
11
|
-
"key":key
|
12
|
-
}
|
13
|
-
file = httpx.post(url=url,json=json)
|
14
|
-
if mode == 'zh':
|
15
|
-
if file.status_code == 200:
|
16
|
-
return file.json()
|
17
|
-
elif file.status_code == 204:
|
18
|
-
return "没有结果"
|
19
|
-
elif file.status_code == 406:
|
20
|
-
return "参数错误"
|
21
|
-
elif file.status_code == 401:
|
22
|
-
return file.json()
|
23
|
-
elif mode == 'ip':
|
24
|
-
rep:dict = file.json()
|
25
|
-
try:
|
26
|
-
logger.error(rep['error_'])
|
27
|
-
except:
|
28
|
-
pass
|
29
|
-
print(file.json())
|
30
|
-
return file.json()
|
31
|
-
elif mode == 'first':
|
32
|
-
ip_tag:list = file.json()
|
33
|
-
return ip_tag
|
34
|
-
|
35
|
-
|
36
|
-
async def map_dict_to_str(data:List[dict]):
|
37
|
-
msg = ""
|
38
|
-
for key,value in data[0].items():
|
39
|
-
if key == "url":
|
40
|
-
continue
|
41
|
-
msg += f"{key}:{value}\n"
|
42
|
-
return msg
|
43
|
-
|
1
|
+
import httpx
|
2
|
+
from typing import List,Union
|
3
|
+
from nonebot.log import logger
|
4
|
+
|
5
|
+
async def seach_map(msg:Union[list,str],qq:str,key:str,mode:str = 'zh'):
|
6
|
+
url = "http://106.13.207.45:4015/l4d2"
|
7
|
+
json = {
|
8
|
+
"mode":mode,
|
9
|
+
"map_name":msg,
|
10
|
+
"qq":qq,
|
11
|
+
"key":key
|
12
|
+
}
|
13
|
+
file = httpx.post(url=url,json=json)
|
14
|
+
if mode == 'zh':
|
15
|
+
if file.status_code == 200:
|
16
|
+
return file.json()
|
17
|
+
elif file.status_code == 204:
|
18
|
+
return "没有结果"
|
19
|
+
elif file.status_code == 406:
|
20
|
+
return "参数错误"
|
21
|
+
elif file.status_code == 401:
|
22
|
+
return file.json()
|
23
|
+
elif mode == 'ip':
|
24
|
+
rep:dict = file.json()
|
25
|
+
try:
|
26
|
+
logger.error(rep['error_'])
|
27
|
+
except:
|
28
|
+
pass
|
29
|
+
print(file.json())
|
30
|
+
return file.json()
|
31
|
+
elif mode == 'first':
|
32
|
+
ip_tag:list = file.json()
|
33
|
+
return ip_tag
|
34
|
+
|
35
|
+
|
36
|
+
async def map_dict_to_str(data:List[dict]):
|
37
|
+
msg = ""
|
38
|
+
for key,value in data[0].items():
|
39
|
+
if key == "url":
|
40
|
+
continue
|
41
|
+
msg += f"{key}:{value}\n"
|
42
|
+
return msg
|
43
|
+
|