hln-a/hlna.py
xpamych cbecbcecda Revert "change if else and fix function servers"
This reverts commit d4eece79e3a7f904a5424a98c68b626c8075ec1a.
2023-05-10 12:23:31 +03:00

535 lines
19 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
import os
import datetime
import yaml
import click
import colorama
from pathlib import Path
from rcon.source import Client
home_dir = Path.home()
dir_server = f"{home_dir}/Servers/"
dir_server_ark = f"{dir_server}/ARK/"
server_dir = f"{dir_server_ark}ShooterGame/Binaries/Linux/"
dir_unit = f"{home_dir}/.config/systemd/user/"
dir_config = f"{home_dir}/.config/hlna/"
dir_logs = f"{dir_config}logs/"
dir_maps = f"{dir_config}maps/"
dir_deactivated = f"{dir_maps}deactivated/"
mods_id = ""
now = datetime.datetime.now()
date = now.strftime("%Y-%m-%d")
time = now.strftime("%H:%M:%S")
@click.group()
def hlna():
pass
def create_dir(directory):
"""Проверка и создание директории"""
if not os.path.exists(directory):
os.mkdir(directory)
create_dir(dir_server)
create_dir(dir_server_ark)
create_dir(dir_unit)
create_dir(dir_config)
create_dir(dir_logs)
create_dir(dir_maps)
def find_file(path):
"""Находим все конфиги в зависимости от пути"""
arr = next(os.walk(path), (None, None, []))[2] # [] if no file
x = arr.count('.directory')
y = arr.count('logs')
if x > 0:
arr.remove('.directory')
if y > 0:
arr.remove('logs')
return arr
list_config = find_file(dir_maps)
delist_config = find_file(dir_deactivated)
def print_line(text):
"""Добавление тире вокруг текста, покраска"""
print(colorama.Fore.YELLOW + "-" * 30)
print(f"{colorama.Fore.GREEN} + {text}")
print(colorama.Fore.YELLOW + "-" * 30 + colorama.Style.RESET_ALL)
def check_int(number=""):
"""Проверка на ввод числа"""
while True:
try:
x = input(number)
if x == "":
return 0
x = int(x)
return x
except ValueError:
print_line("Введите число")
@hlna.command(help='Сбор настроек для сервера или кластера')
def config():
while True:
count_server = check_int("""Выберите игру для конфигурирования
1. ARK Survival Evolved
: """)
if count_server == 1:
config_ark()
break
else:
print_line("Пока есть только ARK xD")
def config_ark(list_config=list_config):
"""Сбор данных для конфига"""
data = {}
port_s = []
rcon_p = []
query_p = []
cluster_id = ""
cluster_dir_override = ""
count_cluster = check_int("""Укажите требуется ли кластер?
1. Да
2. Нет
: """)
if count_cluster == 1:
cluster_server = True
cluster_id = input("Укажите id для кластера, любое сочетание символов: \n")
create_dir(dir_server + cluster_id)
cluster_dir_override = (dir_server + cluster_id)
else:
cluster_server = False
if list_config:
print("Уже установленные карты: ")
for i in list_config:
data = read_yaml(i)
print(f"{i} : {data['map']}")
count_maps = check_int("Укажите количество карт: \n")
if count_maps == 0: # 0 возвращает check_int когда, ничего не было введено
count_maps = 1
for i in range(count_maps):
while True:
"Проверка на выбор карты из списка"
amount_map = check_int("""Выберите карту из списка указав номер
1. The Island
2. The Center
3. Scorched Earth
4. Ragnarok
5. Aberration
6. Extinction
7. Valguero
8. Genesis: Part 1
9. Crystal Isles
10. Genesis: Part 2
11. Lost Island
12. Fjordur
: """)
if amount_map == 0: # 0 возвращает check_int когда, ничего не было введено
amount_map = i + 1
if 0 < amount_map <= 12:
break
if list_config:
for i in list_config:
data = read_yaml(i)
port_s.append(data['Port'])
rcon_p.append(data['RCONPort'])
query_p.append(data['QueryPort'])
if amount_map == 1:
map_s = "TheIsland"
elif amount_map == 2:
map_s = "TheCenter"
elif amount_map == 3:
map_s = "ScorchedEarth_P"
elif amount_map == 4:
map_s = "Ragnarok"
elif amount_map == 5:
map_s = "Aberration_P"
elif amount_map == 6:
map_s = "Extinction"
elif amount_map == 7:
map_s = "Valguero_P"
elif amount_map == 8:
map_s = "Genesis"
elif amount_map == 9:
map_s = "CrystalIsles"
elif amount_map == 10:
map_s = "Gen2"
elif amount_map == 11:
map_s = "LostIsland"
elif amount_map == 12:
map_s = "Fjordur"
else:
# Если вдруг каким-то боком проверка не отработает и не будет нужной цифры
map_s = 'TheIsland'
def ports(ports_arr):
while True:
port = check_int("")
if port == 0:
if not ports_arr:
print("Значение по умолчаню")
else:
port = max(ports_arr) + 2
if port in ports_arr:
print("Порт уже занят")
else:
return port
if list_config:
data = read_yaml(list_config[-1])
while True:
name_server = input("Укажите название Сервера: \n")
if name_server == "":
if map_s in list_config:
count = 1
new_name = map_s
while new_name in list_config:
new_name = f"{map_s}{str(count)}"
count += 1
list_config.append(new_name)
print(list_config)
break
else:
list_config.append(map_s)
break
else:
if name_server in list_config:
print_line("Имя занято")
else:
list_config.append(name_server) # если enter, то ставим последним элементом карту
break
print("Укажите порт сервера:\n")
port_server = ports(port_s)
print("Укажите query порт сервера:\n")
query_port = ports(query_p)
if port_server == 0:
port_server = 7777
if query_port == 0:
query_port = 27015
print("Порт Сервера=", port_server)
print("Query Port=", query_port)
rcon_enabled = True
if rcon_p == []:
rcon_port = 27020
else:
rcon_port = max(rcon_p) + 1
password_server = input("Укажите пароль Сервера: \n")
adminpassword_server = 123
max_players = check_int("Укажите максимальное количество игроков: \n")
if max_players == 0:
max_players = 70
print("Передавать сервер в глобальный список серверов steam?")
listen_server_amount = check_int("""\n
1. Да
2. Нет
:""")
if listen_server_amount == 1:
listen_server = True
elif listen_server_amount == 2:
listen_server = False
else:
listen_server = True
yaml_create(cluster_server, map_s, list_config[-1], port_server, query_port, rcon_enabled, rcon_port,
adminpassword_server, password_server, max_players, cluster_id, cluster_dir_override, listen_server)
def yaml_create(cluster_server, map_s, name_server, port_server, query_port, rcon_enabled, rcon_port,
adminpassword_server, password_server, max_players, cluster_id, cluster_dir_override, listen_server):
settings_hlna = [
{
'map': map_s,
'Cluster': cluster_server,
'SessionName': name_server,
'Port': port_server,
'QueryPort': query_port,
'RCONEnabled': rcon_enabled,
'RCONPort': rcon_port,
'ServerAdminPassword': adminpassword_server,
'ServerPassword': password_server,
'MaxPlayers': max_players,
'ModsId': mods_id,
'Listen': listen_server,
'ServerPath': dir_server,
'clusterid': cluster_id,
'clusterdir': cluster_dir_override
}
]
with open(dir_maps + f"{name_server}", 'w') as yamlfile:
yaml.dump(settings_hlna, yamlfile)
print(colorama.Fore.GREEN + "Конфиг создан" + colorama.Style.RESET_ALL)
systemd_unit_create()
def systemd_unit_create(name_server=list_config):
for i in name_server:
data = read_yaml(i)
if not data['Cluster']:
ntff = ""
else:
ntff = "-NoTransferFromFiltering"
unit_file = f"{dir_unit}ARK_{data['SessionName']}.service"
unit_text = f'''[Unit]
Description=ARK: Survival Evolved dedicated server - {data['map']}
Wants=network-online.target
After=syslog.target network.target nss-lookup.target network-online.target
[Service]
ExecStartPre=/usr/bin/steamcmd +force_install_dir {dir_server} +login anonymous +app_update 376030 +quit
TimeoutStartSec=1200
ExecStart={dir_server_ark}ShooterGameServer {data['map']}?listen={data['Listen']}?SessionName={data['SessionName']}?Port={data['Port']}?QueryPort={data['QueryPort']}?RCONEnabled={data['RCONEnabled']}?RCONPort={data['RCONPort']}?ServerAdminPassword={data['ServerAdminPassword']}?MaxPlayers={data['MaxPlayers']} -clusterid={data['clusterid']} -ClusterDirOverride={data['clusterdir']} {ntff}
LimitNOFILE=100000
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s INT $MAINPID
[Install]
WantedBy=default.target
'''
with open(unit_file, 'w') as systemd_unit:
systemd_unit.write(unit_text)
os.system(f"systemctl --user unmask ARK_{data['SessionName']}.service")
os.system(f"systemctl --user enable ARK_{data['SessionName']}.service")
os.system('systemctl --user daemon-reload')
def test_mod_install():
pathTest = f"{dir_server}ShooterGame/Saved/Config/LinuxServer/"
if os.path.exists(pathTest):
os.chdir(pathTest)
# "Добавить файл в Game.ini, если модов несколько добавляем еще строку ModIDS=<ModId> [ModInstaller] ModIDS=<ModID>"
# c этим не разобрался
os.system("echo ActiveMods=2943454417 >> GameUserSettings.ini")
else:
print_line("Сервер не установлен")
test_mod_install()
@hlna.command()
@click.option("-m", required=True, help="Название Сервера")
@click.option("-e/-d", default=True, help="-e активировать карты, -d деактивировать")
def enablemap(m, e):
"""Включение/выключение карт"""
m = m.split(",")
if not os.path.isdir(dir_deactivated):
create_dir(dir_deactivated)
if e == True:
port_s = []
query_p = []
for k in list_config:
data = read_yaml(k)
port_s.append(data['Port'])
query_p.append(data['QueryPort'])
for i in m:
try:
if i in list_config:
print(f"Карта {i} уже есть в активных")
continue
data = read_yaml(i)
if data['Port'] in port_s:
print("Предлагаем заменить")
continue
if data['QueryPort'] in query_p:
print("Заменить query port?")
continue
x = os.system(f"mv {dir_deactivated}{i} {dir_maps} >> {dir_logs}{date} 2>&1") # Добавить текущее время
with open(f"{dir_logs}{date}.log", "a") as f:
f.write(f"[{time}] File {i} has been moved to {dir_maps}\n")
if x == 0:
print(f"Карта активирована - {i}")
else:
print(f"{i} либо уже активирована, либо такой карты нет")
finally:
pass
# except:
# print("ошибка при активации карты")
# pass
else:
for i in m:
try:
if i in delist_config:
print(f"Карта {i} уже есть в деактивированных")
continue
x = os.system(
f"mv {dir_maps}{i} {dir_deactivated} >> {dir_logs}{date} 2>&1") # Добавить текущее время
with open(f"{dir_logs}{date}.log", "a") as f:
f.write(f"[{time}] File {i} has been moved to {dir_deactivated}\n")
if x == 0:
print(f"Карта деактивирована - {i}")
else:
print(f"{i} либо деактивирована, либо такой карты нет")
except:
pass
@hlna.command()
def servers(map_server=list_config):
# Добавить сортивку по кластерам и вывод несколько столбиков
if map_server == [] and delist_config == []:
print("Сервера не установлены")
else:
for i in map_server:
data = read_yaml(i)
x = os.system(f"lsof -w -i :{data['Port']}")
if x == 0:
print(colorama.Fore.GREEN + "Сервер запущен" + colorama.Style.RESET_ALL)
else:
print(colorama.Fore.RED + "Сервер не запущен" + colorama.Style.RESET_ALL)
print(f"""
Имя сервера: {i}
Карта: {data['map']}
Моды: {data['ModsId']}
Пароль: {data['ServerPassword']}
Кластер: {data['Cluster']}
Кластер id: {data['clusterid']}
Query порт: {data['QueryPort']}
Порт сервера: {data['Port']}
Rcon включен: {data['RCONEnabled']}
Rcon порт : {data['RCONPort']}
Максимальное кол-во игроков: {data['MaxPlayers']}""")
print("-" * 40)
if delist_config != []:
x = input("Есть неактивные сервера, показать Y/n: ")
if x != "n":
for i in delist_config:
data = read_yaml(i, False)
print(f"""
Имя сервера: {i}
Карта: {data['map']}
Моды: {data['ModsId']}
Пароль: {data['ServerPassword']}
Кластер: {data['Cluster']}
Кластер id: {data['clusterid']}
Query порт: {data['QueryPort']}
Порт сервера: {data['Port']}
Rcon включен: {data['RCONEnabled']}
Rcon порт : {data['RCONPort']}
Максимальное кол-во игроков: {data['MaxPlayers']}""")
print("-" * 40)
@hlna.command(help='Для запуска, сконфигурированного сервера или кластера')
@click.option('-m', default='all', help="Название карты для запуска или all для запуска все карт")
@click.option('-b', default='', help="")
def start(m, b, name_server=list_config):
dict_mapname = {}
dict_allmapname = []
for i in name_server:
data = read_yaml(i)
print_line(f"Название сервера: {i} | Карта: {data['map']} | Кластер: {data['clusterid']}")
dict_mapname[data['SessionName']] = data['map']
dict_allmapname.append(data['SessionName'])
print_line(f"Словарь названия сервера и карты {dict_mapname}")
names_serverstart = []
for ns, v in dict_mapname.items():
print_line(f"переменные v и m {v} & {m}")
if v in m:
names_serverstart.append(ns)
print_line(f"Карта которая запускается {ns}")
if name_server != []:
if b == '':
if m == "all":
names_serverstart = dict_allmapname
print(f"Запускаем все активные карты {names_serverstart}")
else:
names_serverstart = choose_map(names_serverstart)
for i in names_serverstart:
data = read_yaml(i)
os.system(f"systemctl --user start ARK_{data['SessionName']}.service")
else:
print("Ни одной карты не установлено")
def read_yaml(list_config, flag=True):
# Читаем конфиги активных или неактивных карт в зависимости от флага
if flag:
dirs = f"{dir_maps}{list_config}"
else:
dirs = f"{dir_deactivated}{list_config}"
with open(dirs, "r") as yamlfile:
data = yaml.load(yamlfile, Loader=yaml.FullLoader)
return data[0] # возвращаем словарь со всеми значениями
def choose_map(arr):
new_arr = []
arr = sorted(arr)
print('Найдены сервера с этой картой')
for i, map in enumerate(arr):
print(f"{i + 1}) {map}")
while True:
try:
x = input("Выберите сервер из списка, либо несколько через запятую: ").split(',')
x = [int(i) for i in x]
break
except:
print("Неправильный ввод")
for i in x:
new_arr.append(arr[i - 1])
print('Выбранные сервера:', new_arr)
return new_arr
@hlna.command()
@click.argument('c', nargs=1)
@click.option('-m', required=True, help="Название карты для применения rcon команды")
def rcon(m, c):
print_line("Команда: ", c)
print_line("Карты: ", m)
dict_mapname = {}
dict_adminpwd = {}
for i in list_config:
data = read_yaml(i)
dict_mapname[data['RCONPort']] = data['map']
dict_adminpwd[data['RCONPort']] = data['ServerAdminPassword']
rcon_ports = []
for ns, v in dict_mapname.items():
print_line(f"переменные v и m {v} & {m}") # обьединить с таким же блоком в start()
if v in m:
rcon_ports.append(ns)
print_line(f"Карта которая запускается {ns}")
for port in rcon_ports:
print(port)
passwd = dict_adminpwd[port]
with Client('127.0.0.1', port, passwd=str(passwd)) as client:
response = client.run(c)
print(response)
def zero(x=""):
return ""
if __name__ == '__main__':
hlna()