nonebot-plugin-l4d2-server 0.5.1__py3-none-any.whl → 0.5.3__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 +373 -359
- nonebot_plugin_l4d2_server/__init__.py +13 -13
- nonebot_plugin_l4d2_server/command.py +232 -232
- nonebot_plugin_l4d2_server/config.py +209 -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/database.py +0 -0
- 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/image.py +292 -0
- 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/index.py +0 -0
- 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_update/__init__.py +143 -0
- nonebot_plugin_l4d2_server/l4d2_update/draw_update_log.py +41 -0
- nonebot_plugin_l4d2_server/l4d2_update/restart.py +67 -0
- nonebot_plugin_l4d2_server/l4d2_update/texture2d/art.png +0 -0
- nonebot_plugin_l4d2_server/l4d2_update/texture2d/bento.png +0 -0
- nonebot_plugin_l4d2_server/l4d2_update/texture2d/bug.png +0 -0
- nonebot_plugin_l4d2_server/l4d2_update/texture2d/feat.png +0 -0
- nonebot_plugin_l4d2_server/l4d2_update/texture2d/log_title.png +0 -0
- nonebot_plugin_l4d2_server/l4d2_update/texture2d/other.png +0 -0
- nonebot_plugin_l4d2_server/l4d2_update/texture2d/zap.png +0 -0
- nonebot_plugin_l4d2_server/l4d2_update/update.py +65 -0
- 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/rule.py +15 -0
- nonebot_plugin_l4d2_server/seach.py +33 -33
- nonebot_plugin_l4d2_server/txt_to_img.py +64 -64
- nonebot_plugin_l4d2_server/utils.py +297 -272
- {nonebot_plugin_l4d2_server-0.5.1.dist-info → nonebot_plugin_l4d2_server-0.5.3.dist-info}/LICENSE +674 -674
- {nonebot_plugin_l4d2_server-0.5.1.dist-info → nonebot_plugin_l4d2_server-0.5.3.dist-info}/METADATA +19 -4
- nonebot_plugin_l4d2_server-0.5.3.dist-info/RECORD +68 -0
- {nonebot_plugin_l4d2_server-0.5.1.dist-info → nonebot_plugin_l4d2_server-0.5.3.dist-info}/WHEEL +1 -1
- nonebot_plugin_l4d2_server/chrome.py +0 -45
- nonebot_plugin_l4d2_server-0.5.1.dist-info/RECORD +0 -54
@@ -1,62 +1,62 @@
|
|
1
|
-
import asyncio
|
2
|
-
from rcon.source.proto import Packet,Type
|
3
|
-
from rcon.source.async_rcon import communicate,close
|
4
|
-
|
5
|
-
async def main(host):
|
6
|
-
host = '43.142.178.212'
|
7
|
-
port = 40003
|
8
|
-
password = '1145149191810'
|
9
|
-
encoding = 'utf-8'
|
10
|
-
|
11
|
-
# Connect to RCON server
|
12
|
-
|
13
|
-
|
14
|
-
# Main loop
|
15
|
-
while True:
|
16
|
-
# Read user input
|
17
|
-
command = input('> ')
|
18
|
-
if not command:
|
19
|
-
break
|
20
|
-
|
21
|
-
# 连接服务器
|
22
|
-
reader, writer = await asyncio.open_connection(host, port)
|
23
|
-
login = Packet.make_login(password, encoding=encoding)
|
24
|
-
response = await communicate(reader, writer, login)
|
25
|
-
|
26
|
-
# 等待 SERVERDATA_AUTH_RESPONSE 数据包
|
27
|
-
while response.type != Type.SERVERDATA_AUTH_RESPONSE:
|
28
|
-
response = await Packet.aread(reader)
|
29
|
-
|
30
|
-
if response.id == -1:
|
31
|
-
await close(writer)
|
32
|
-
raise WrongPassword()
|
33
|
-
|
34
|
-
# 循环接收用户输入并发送指令
|
35
|
-
while True:
|
36
|
-
try:
|
37
|
-
command = input('请输入指令:')
|
38
|
-
|
39
|
-
except EOFError:
|
40
|
-
break
|
41
|
-
|
42
|
-
if command=='停止':
|
43
|
-
break
|
44
|
-
# 发送指令
|
45
|
-
|
46
|
-
command = f'say {command}'
|
47
|
-
request = Packet.make_command(command, encoding=encoding)
|
48
|
-
response = await communicate(reader, writer, request)
|
49
|
-
|
50
|
-
# if response.id != request.id:
|
51
|
-
# raise SessionTimeout()
|
52
|
-
|
53
|
-
print(response.payload.decode(encoding, errors='ignore'))
|
54
|
-
|
55
|
-
# 断开连接
|
56
|
-
await close(writer)
|
57
|
-
|
58
|
-
class WrongPassword(Exception):
|
59
|
-
"""Indicates a wrong password."""
|
60
|
-
|
61
|
-
class SessionTimeout(Exception):
|
1
|
+
import asyncio
|
2
|
+
from rcon.source.proto import Packet,Type
|
3
|
+
from rcon.source.async_rcon import communicate,close
|
4
|
+
|
5
|
+
async def main(host):
|
6
|
+
host = '43.142.178.212'
|
7
|
+
port = 40003
|
8
|
+
password = '1145149191810'
|
9
|
+
encoding = 'utf-8'
|
10
|
+
|
11
|
+
# Connect to RCON server
|
12
|
+
|
13
|
+
|
14
|
+
# Main loop
|
15
|
+
while True:
|
16
|
+
# Read user input
|
17
|
+
command = input('> ')
|
18
|
+
if not command:
|
19
|
+
break
|
20
|
+
|
21
|
+
# 连接服务器
|
22
|
+
reader, writer = await asyncio.open_connection(host, port)
|
23
|
+
login = Packet.make_login(password, encoding=encoding)
|
24
|
+
response = await communicate(reader, writer, login)
|
25
|
+
|
26
|
+
# 等待 SERVERDATA_AUTH_RESPONSE 数据包
|
27
|
+
while response.type != Type.SERVERDATA_AUTH_RESPONSE:
|
28
|
+
response = await Packet.aread(reader)
|
29
|
+
|
30
|
+
if response.id == -1:
|
31
|
+
await close(writer)
|
32
|
+
raise WrongPassword()
|
33
|
+
|
34
|
+
# 循环接收用户输入并发送指令
|
35
|
+
while True:
|
36
|
+
try:
|
37
|
+
command = input('请输入指令:')
|
38
|
+
|
39
|
+
except EOFError:
|
40
|
+
break
|
41
|
+
|
42
|
+
if command=='停止':
|
43
|
+
break
|
44
|
+
# 发送指令
|
45
|
+
|
46
|
+
command = f'say {command}'
|
47
|
+
request = Packet.make_command(command, encoding=encoding)
|
48
|
+
response = await communicate(reader, writer, request)
|
49
|
+
|
50
|
+
# if response.id != request.id:
|
51
|
+
# raise SessionTimeout()
|
52
|
+
|
53
|
+
print(response.payload.decode(encoding, errors='ignore'))
|
54
|
+
|
55
|
+
# 断开连接
|
56
|
+
await close(writer)
|
57
|
+
|
58
|
+
class WrongPassword(Exception):
|
59
|
+
"""Indicates a wrong password."""
|
60
|
+
|
61
|
+
class SessionTimeout(Exception):
|
62
62
|
"""Indicates that the session timed out."""
|
File without changes
|
@@ -1,29 +1,29 @@
|
|
1
|
-
from rcon.source import rcon
|
2
|
-
import asyncio
|
3
|
-
from pathlib import Path
|
4
|
-
from ..config import l4_config,CHECK_FILE
|
5
|
-
# from ..config import l4_rcon,l4_host,l4_port,l4_rcon
|
6
|
-
|
7
|
-
|
8
|
-
async def rcon_server(PASSWORD:str,msg:str):
|
9
|
-
# response = await rcon(command=msg, host=l4_host, port=l4_port, passwd=PASSWORD,encoding='utf-8')
|
10
|
-
# return response
|
11
|
-
try:
|
12
|
-
response = await asyncio.wait_for(rcon(command=msg, host=l4_config.l4_ipall[CHECK_FILE]['host'], port = l4_config.l4_ipall[CHECK_FILE]['port'], passwd=PASSWORD), timeout=30)
|
13
|
-
return response
|
14
|
-
except asyncio.TimeoutError:
|
15
|
-
return '超时'
|
16
|
-
|
17
|
-
async def read_server_cfg_rcon():
|
18
|
-
"""如果没有输入rcon,尝试自动获取"""
|
19
|
-
if not l4_config.l4_ipall[CHECK_FILE]['rcon']:
|
20
|
-
cfg_server = Path(l4_config.l4_ipall[CHECK_FILE]['location'],'left4dead2/cfg/server.cfg')
|
21
|
-
with open(cfg_server,'r')as cfg:
|
22
|
-
content:str = cfg.read()
|
23
|
-
lines = content.split('\n')
|
24
|
-
for line in lines:
|
25
|
-
if line.startswith('rcon_password'):
|
26
|
-
password = line.split(' ')[-1]
|
27
|
-
password = password.strip('"')
|
28
|
-
return password
|
1
|
+
from rcon.source import rcon
|
2
|
+
import asyncio
|
3
|
+
from pathlib import Path
|
4
|
+
from ..config import l4_config,CHECK_FILE
|
5
|
+
# from ..config import l4_rcon,l4_host,l4_port,l4_rcon
|
6
|
+
|
7
|
+
|
8
|
+
async def rcon_server(PASSWORD:str,msg:str):
|
9
|
+
# response = await rcon(command=msg, host=l4_host, port=l4_port, passwd=PASSWORD,encoding='utf-8')
|
10
|
+
# return response
|
11
|
+
try:
|
12
|
+
response = await asyncio.wait_for(rcon(command=msg, host=l4_config.l4_ipall[CHECK_FILE]['host'], port = l4_config.l4_ipall[CHECK_FILE]['port'], passwd=PASSWORD), timeout=30)
|
13
|
+
return response
|
14
|
+
except asyncio.TimeoutError:
|
15
|
+
return '超时'
|
16
|
+
|
17
|
+
async def read_server_cfg_rcon():
|
18
|
+
"""如果没有输入rcon,尝试自动获取"""
|
19
|
+
if not l4_config.l4_ipall[CHECK_FILE]['rcon']:
|
20
|
+
cfg_server = Path(l4_config.l4_ipall[CHECK_FILE]['location'],'left4dead2/cfg/server.cfg')
|
21
|
+
with open(cfg_server,'r')as cfg:
|
22
|
+
content:str = cfg.read()
|
23
|
+
lines = content.split('\n')
|
24
|
+
for line in lines:
|
25
|
+
if line.startswith('rcon_password'):
|
26
|
+
password = line.split(' ')[-1]
|
27
|
+
password = password.strip('"')
|
28
|
+
return password
|
29
29
|
return l4_config.l4_ipall[CHECK_FILE]['rcon']
|
@@ -1,50 +1,50 @@
|
|
1
|
-
import httpx
|
2
|
-
from nonebot.log import logger
|
3
|
-
try:
|
4
|
-
import ujson as json
|
5
|
-
except:
|
6
|
-
import json
|
7
|
-
|
8
|
-
async def workshop_to_dict(msg:str):
|
9
|
-
"""把创意工坊的id,转化为信息字典"""
|
10
|
-
i = await api_get_json(msg)
|
11
|
-
|
12
|
-
# 处理是否是多地图文件
|
13
|
-
if i['file_url'] == i['preview_url']:
|
14
|
-
return await primary_map(i)
|
15
|
-
else:
|
16
|
-
return await only_map(i)
|
17
|
-
|
18
|
-
|
19
|
-
async def api_get_json(msg:str) ->dict:
|
20
|
-
url_serach = 'https://db.steamworkshopdownloader.io/prod/api/details/file'
|
21
|
-
data = f'[{msg}]'
|
22
|
-
headers = {
|
23
|
-
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
|
24
|
-
}
|
25
|
-
data = httpx.post(url=url_serach,headers= headers,data=data).content.decode('utf-8')
|
26
|
-
logger.info(data)
|
27
|
-
out = {}
|
28
|
-
data = data[1:-1]
|
29
|
-
data = json.loads(data)
|
30
|
-
return data
|
31
|
-
|
32
|
-
|
33
|
-
async def only_map(i:dict):
|
34
|
-
"""单地图下载"""
|
35
|
-
out = {}
|
36
|
-
out['名字'] = i['title']
|
37
|
-
out['游戏'] = i['app_name']
|
38
|
-
out['下载地址'] = i['file_url']
|
39
|
-
out['图片地址'] = i['preview_url']
|
40
|
-
out['细节'] = i['file_description']
|
41
|
-
return out
|
42
|
-
|
43
|
-
async def primary_map(i):
|
44
|
-
"""主地图返回多地图参数"""
|
45
|
-
map_list = []
|
46
|
-
map_list.append(i)
|
47
|
-
for one in i['children']:
|
48
|
-
map_list.append(await api_get_json(one['publishedfileid']))
|
49
|
-
return map_list
|
50
|
-
|
1
|
+
import httpx
|
2
|
+
from nonebot.log import logger
|
3
|
+
try:
|
4
|
+
import ujson as json
|
5
|
+
except:
|
6
|
+
import json
|
7
|
+
|
8
|
+
async def workshop_to_dict(msg:str):
|
9
|
+
"""把创意工坊的id,转化为信息字典"""
|
10
|
+
i = await api_get_json(msg)
|
11
|
+
|
12
|
+
# 处理是否是多地图文件
|
13
|
+
if i['file_url'] == i['preview_url']:
|
14
|
+
return await primary_map(i)
|
15
|
+
else:
|
16
|
+
return await only_map(i)
|
17
|
+
|
18
|
+
|
19
|
+
async def api_get_json(msg:str) ->dict:
|
20
|
+
url_serach = 'https://db.steamworkshopdownloader.io/prod/api/details/file'
|
21
|
+
data = f'[{msg}]'
|
22
|
+
headers = {
|
23
|
+
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0'
|
24
|
+
}
|
25
|
+
data = httpx.post(url=url_serach,headers= headers,data=data).content.decode('utf-8')
|
26
|
+
logger.info(data)
|
27
|
+
out = {}
|
28
|
+
data = data[1:-1]
|
29
|
+
data = json.loads(data)
|
30
|
+
return data
|
31
|
+
|
32
|
+
|
33
|
+
async def only_map(i:dict):
|
34
|
+
"""单地图下载"""
|
35
|
+
out = {}
|
36
|
+
out['名字'] = i['title']
|
37
|
+
out['游戏'] = i['app_name']
|
38
|
+
out['下载地址'] = i['file_url']
|
39
|
+
out['图片地址'] = i['preview_url']
|
40
|
+
out['细节'] = i['file_description']
|
41
|
+
return out
|
42
|
+
|
43
|
+
async def primary_map(i):
|
44
|
+
"""主地图返回多地图参数"""
|
45
|
+
map_list = []
|
46
|
+
map_list.append(i)
|
47
|
+
for one in i['children']:
|
48
|
+
map_list.append(await api_get_json(one['publishedfileid']))
|
49
|
+
return map_list
|
50
|
+
|
@@ -0,0 +1,143 @@
|
|
1
|
+
from typing import Any, Tuple
|
2
|
+
|
3
|
+
from nonebot.log import logger
|
4
|
+
from nonebot.matcher import Matcher
|
5
|
+
from nonebot.params import RegexGroup
|
6
|
+
from nonebot.permission import SUPERUSER
|
7
|
+
from nonebot import get_bot, on_regex, get_driver, on_command
|
8
|
+
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, MessageSegment
|
9
|
+
|
10
|
+
from ..utils import register_menu
|
11
|
+
from ..rule import FullCommand
|
12
|
+
from .draw_update_log import draw_update_log_img
|
13
|
+
from .restart import restart_message, restart_genshinuid
|
14
|
+
|
15
|
+
l4d_restart = on_command('l4重启', rule=FullCommand())
|
16
|
+
get_update_log = on_command('更新记录', rule=FullCommand())
|
17
|
+
l4d_update = on_regex(
|
18
|
+
r'^(l4d)(强行)?(强制)?(更新)$',
|
19
|
+
block=True,
|
20
|
+
)
|
21
|
+
|
22
|
+
|
23
|
+
driver = get_driver()
|
24
|
+
|
25
|
+
|
26
|
+
@driver.on_bot_connect
|
27
|
+
async def _():
|
28
|
+
logger.info('检查遗留信息...')
|
29
|
+
bot = get_bot()
|
30
|
+
update_log = await restart_message()
|
31
|
+
if update_log == {}:
|
32
|
+
return
|
33
|
+
if update_log['send_type'] == 'group':
|
34
|
+
await bot.call_api(
|
35
|
+
api='send_group_msg',
|
36
|
+
group_id=update_log['send_to'],
|
37
|
+
message=update_log['msg'],
|
38
|
+
)
|
39
|
+
else:
|
40
|
+
await bot.call_api(
|
41
|
+
api='send_private_msg',
|
42
|
+
user_id=update_log['send_to'],
|
43
|
+
message=update_log['msg'],
|
44
|
+
)
|
45
|
+
logger.info('遗留信息检查完毕!')
|
46
|
+
|
47
|
+
|
48
|
+
@get_update_log.handle()
|
49
|
+
@register_menu(
|
50
|
+
'更新记录',
|
51
|
+
'更新记录',
|
52
|
+
'查看插件最近的更新记录',
|
53
|
+
detail_des=(
|
54
|
+
'介绍:\n'
|
55
|
+
'查看插件最近的有效Git更新记录\n'
|
56
|
+
' \n'
|
57
|
+
'指令:\n'
|
58
|
+
'- <ft color=(238,120,0)>更新记录</ft>'
|
59
|
+
),
|
60
|
+
)
|
61
|
+
async def send_updatelog_msg(
|
62
|
+
matcher: Matcher,
|
63
|
+
):
|
64
|
+
im = await draw_update_log_img(is_update=False)
|
65
|
+
logger.info('正在执行[更新记录]...')
|
66
|
+
if isinstance(im, str):
|
67
|
+
await matcher.finish(im)
|
68
|
+
elif isinstance(im, bytes):
|
69
|
+
await matcher.finish(MessageSegment.image(im))
|
70
|
+
else:
|
71
|
+
await matcher.finish('发生了未知错误,请联系管理员检查后台输出!')
|
72
|
+
|
73
|
+
|
74
|
+
@l4d_restart.handle()
|
75
|
+
@register_menu(
|
76
|
+
'重启Bot',
|
77
|
+
'l4重启',
|
78
|
+
'重启Bot框架',
|
79
|
+
trigger_method='超级用户指令',
|
80
|
+
detail_des=(
|
81
|
+
'介绍:\n' '重启Bot框架\n' ' \n' '指令:\n' '- <ft color=(238,120,0)>l4重启</ft>'
|
82
|
+
),
|
83
|
+
)
|
84
|
+
async def send_restart_msg(
|
85
|
+
bot: Bot,
|
86
|
+
event: MessageEvent,
|
87
|
+
matcher: Matcher,
|
88
|
+
):
|
89
|
+
if not await SUPERUSER(bot, event):
|
90
|
+
return
|
91
|
+
logger.warning('开始执行[重启]')
|
92
|
+
qid = event.user_id
|
93
|
+
if len(event.get_session_id().split('_')) == 3:
|
94
|
+
send_id = event.get_session_id().split('_')[1]
|
95
|
+
send_type = 'group'
|
96
|
+
else:
|
97
|
+
send_id = qid
|
98
|
+
send_type = 'private'
|
99
|
+
await matcher.send('正在执行[l4重启]...')
|
100
|
+
await restart_genshinuid(send_type, str(send_id))
|
101
|
+
|
102
|
+
|
103
|
+
@l4d_update.handle()
|
104
|
+
@register_menu(
|
105
|
+
'更新插件',
|
106
|
+
'l4更新',
|
107
|
+
'手动更新插件',
|
108
|
+
detail_des=(
|
109
|
+
'介绍:\n'
|
110
|
+
'手动更新插件(执行 git pull)\n'
|
111
|
+
'每加上一个可选参数,执行等级加1\n'
|
112
|
+
'当执行等级≥1时会还原上次更改,等级≥2时会清空暂存\n'
|
113
|
+
' \n'
|
114
|
+
'指令:\n'
|
115
|
+
'- <ft color=(238,120,0)>l4d</ft>'
|
116
|
+
'<ft color=(125,125,125)>(强行)(强制)</ft>'
|
117
|
+
'<ft color=(238,120,0)>更新</ft>'
|
118
|
+
),
|
119
|
+
)
|
120
|
+
async def send_update_msg(
|
121
|
+
bot: Bot,
|
122
|
+
event: MessageEvent,
|
123
|
+
matcher: Matcher,
|
124
|
+
args: Tuple[Any, ...] = RegexGroup(),
|
125
|
+
):
|
126
|
+
if not await SUPERUSER(bot, event):
|
127
|
+
return
|
128
|
+
|
129
|
+
logger.info('[l4d更新] 正在执行 ...')
|
130
|
+
level = 2
|
131
|
+
if args[1] is None:
|
132
|
+
level -= 1
|
133
|
+
if args[2] is None:
|
134
|
+
level -= 1
|
135
|
+
logger.info(f'[l4d更新] 更新等级为{level}')
|
136
|
+
await matcher.send(f'开始执行[l4d更新], 执行等级为{level}')
|
137
|
+
im = await draw_update_log_img(level)
|
138
|
+
if isinstance(im, str):
|
139
|
+
await matcher.finish(im)
|
140
|
+
elif isinstance(im, bytes):
|
141
|
+
await matcher.finish(MessageSegment.image(im))
|
142
|
+
else:
|
143
|
+
await matcher.finish('发生了未知错误,请联系管理员检查后台输出!')
|
@@ -0,0 +1,41 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
from typing import Union
|
3
|
+
|
4
|
+
# from PIL import Image, ImageDraw
|
5
|
+
|
6
|
+
from .update import update_from_git
|
7
|
+
# from ..l4d2_image.image import convert_img
|
8
|
+
# from ..l4d2_image.image import get_color_bg
|
9
|
+
# from ..utils.genshin_fonts.genshin_fonts import genshin_font_origin
|
10
|
+
|
11
|
+
R_PATH = Path(__file__).parent
|
12
|
+
TEXT_PATH = R_PATH / 'texture2d'
|
13
|
+
|
14
|
+
# gs_font_30 = genshin_font_origin(30)
|
15
|
+
black_color = (24, 24, 24)
|
16
|
+
|
17
|
+
log_config = {
|
18
|
+
'key': '✨🐛🎨⚡🍱♻️',
|
19
|
+
'num': 18,
|
20
|
+
}
|
21
|
+
|
22
|
+
log_map = {'✨': 'feat', '🐛': 'bug', '🍱': 'bento', '⚡️': 'zap', '🎨': 'art'}
|
23
|
+
|
24
|
+
|
25
|
+
async def draw_update_log_img(
|
26
|
+
level: int = 0,
|
27
|
+
repo_path: Union[str, Path, None] = None,
|
28
|
+
is_update: bool = True,
|
29
|
+
) -> Union[bytes, str]:
|
30
|
+
log_list = await update_from_git(level, repo_path, log_config, is_update)
|
31
|
+
if len(log_list) == 0:
|
32
|
+
return '更新失败!更多错误信息请查看控制台...\n' \
|
33
|
+
'>> 可以尝试使用\n' \
|
34
|
+
'>> [gs强制更新](危险)\n' \
|
35
|
+
'>> [gs强行强制更新](超级危险)!'
|
36
|
+
|
37
|
+
result = 'L4D2Bot 更新记录\n\n'
|
38
|
+
for log in log_list:
|
39
|
+
result += f'- {log[2:]}\n'
|
40
|
+
|
41
|
+
return result
|
@@ -0,0 +1,67 @@
|
|
1
|
+
import os
|
2
|
+
import sys
|
3
|
+
import json
|
4
|
+
import time
|
5
|
+
import platform
|
6
|
+
import subprocess
|
7
|
+
from pathlib import Path
|
8
|
+
|
9
|
+
# from ..utils.db_operation.db_operation import config_check
|
10
|
+
|
11
|
+
bot_start = Path().cwd() / 'bot.py'
|
12
|
+
restart_sh_path = Path().cwd() / 'gs_restart.sh'
|
13
|
+
update_log_path = Path(__file__).parent / 'update_log.json'
|
14
|
+
|
15
|
+
_restart_sh = '''#!/bin/bash
|
16
|
+
kill -9 {}
|
17
|
+
{} &'''
|
18
|
+
|
19
|
+
|
20
|
+
async def get_restart_sh(extra: str) -> str:
|
21
|
+
args = f'{extra} {str(bot_start.absolute())}'
|
22
|
+
return _restart_sh.format(str(bot_start.absolute()), args)
|
23
|
+
|
24
|
+
|
25
|
+
async def restart_genshinuid(send_type: str, send_id: str) -> None:
|
26
|
+
# extra = ''
|
27
|
+
# if await config_check('UsePoetry'):
|
28
|
+
# extra = 'poetry run '
|
29
|
+
extra = sys.executable
|
30
|
+
restart_sh = await get_restart_sh(extra)
|
31
|
+
if not restart_sh_path.exists():
|
32
|
+
with open(restart_sh_path, "w", encoding="utf8") as f:
|
33
|
+
f.write(restart_sh)
|
34
|
+
if platform.system() == 'Linux':
|
35
|
+
os.system(f'chmod +x {str(restart_sh_path)}')
|
36
|
+
os.system(f'chmod +x {str(bot_start)}')
|
37
|
+
now_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
|
38
|
+
update_log = {
|
39
|
+
'type': 'restart',
|
40
|
+
'msg': '重启完成!',
|
41
|
+
'send_type': send_type,
|
42
|
+
'send_to': send_id,
|
43
|
+
'time': now_time,
|
44
|
+
}
|
45
|
+
with open(str(update_log_path), 'w', encoding='utf-8') as f:
|
46
|
+
json.dump(update_log, f)
|
47
|
+
if platform.system() == 'Linux':
|
48
|
+
os.execl(str(restart_sh_path), ' ')
|
49
|
+
else:
|
50
|
+
pid = os.getpid()
|
51
|
+
subprocess.Popen(
|
52
|
+
f'taskkill /F /PID {pid} & {extra} {bot_start}',
|
53
|
+
shell=True,
|
54
|
+
)
|
55
|
+
|
56
|
+
|
57
|
+
async def restart_message() -> dict:
|
58
|
+
if update_log_path.exists():
|
59
|
+
with open(update_log_path, 'r', encoding='utf-8') as f:
|
60
|
+
update_log = json.load(f)
|
61
|
+
msg = f'{update_log["msg"]}\n重启时间:{update_log["time"]}'
|
62
|
+
update_log['msg'] = msg
|
63
|
+
os.remove(update_log_path)
|
64
|
+
os.remove(restart_sh_path)
|
65
|
+
return update_log
|
66
|
+
else:
|
67
|
+
return {}
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,65 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
from typing import List, Union
|
3
|
+
|
4
|
+
import git
|
5
|
+
from nonebot.log import logger
|
6
|
+
from git.exc import GitCommandError
|
7
|
+
|
8
|
+
|
9
|
+
async def update_from_git(
|
10
|
+
level: int = 0,
|
11
|
+
repo_path: Union[str, Path, None] = None,
|
12
|
+
log_config: dict = {
|
13
|
+
'key': '✨🐛',
|
14
|
+
'num': 7,
|
15
|
+
},
|
16
|
+
is_update: bool = True,
|
17
|
+
) -> List[str]:
|
18
|
+
if repo_path is None:
|
19
|
+
repo_path = Path(__file__).parents[2]
|
20
|
+
repo = git.Repo(repo_path) # type: ignore
|
21
|
+
o = repo.remotes.origin
|
22
|
+
|
23
|
+
if is_update:
|
24
|
+
# 清空暂存
|
25
|
+
if level >= 2:
|
26
|
+
logger.warning('[gs更新] 正在执行 git clean --xdf')
|
27
|
+
repo.git.clean('-xdf')
|
28
|
+
# 还原上次更改
|
29
|
+
if level >= 1:
|
30
|
+
logger.warning('[gs更新] 正在执行 git reset --hard')
|
31
|
+
repo.git.reset('--hard')
|
32
|
+
|
33
|
+
try:
|
34
|
+
pull_log = o.pull()
|
35
|
+
logger.info(f'[gs更新] {pull_log}')
|
36
|
+
except GitCommandError as e:
|
37
|
+
logger.warning(e)
|
38
|
+
return []
|
39
|
+
|
40
|
+
commits = list(repo.iter_commits(max_count=40))
|
41
|
+
log_list = []
|
42
|
+
for commit in commits:
|
43
|
+
if isinstance(commit.message, str):
|
44
|
+
for key in log_config['key']:
|
45
|
+
if key in commit.message:
|
46
|
+
log_list.append(commit.message.replace('\n', ''))
|
47
|
+
if len(log_list) >= log_config['num']:
|
48
|
+
break
|
49
|
+
return log_list
|
50
|
+
|
51
|
+
|
52
|
+
async def update_genshinuid(
|
53
|
+
level: int = 0, repo_path: Union[str, Path, None] = None
|
54
|
+
) -> str:
|
55
|
+
log_list = await update_from_git(level, repo_path)
|
56
|
+
if len(log_list) == 0:
|
57
|
+
return (
|
58
|
+
'更新失败!更多错误信息请查看控制台...\n '
|
59
|
+
'>> 可以尝试使用\n '
|
60
|
+
'>> [gs强制更新](危险)\n '
|
61
|
+
'>> [gs强行强制更新](超级危险)!'
|
62
|
+
)
|
63
|
+
log = '\n'.join(log_list)
|
64
|
+
logger.info(f'[gs更新]\n{log}')
|
65
|
+
return f'更新成功!\n >> 最近有效更新为:\n{log}'
|