v1.0
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,3 +1,7 @@
|
||||
server/content
|
||||
server/token.txt
|
||||
updater/mods
|
||||
|
||||
# ---> Python
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 depish
|
||||
Copyright (c) 2025 Leonov Artur <depish.eskry@yandex.ru>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
3
server/config.json
Normal file
3
server/config.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"content": "./content"
|
||||
}
|
||||
2
server/requirments.txt
Normal file
2
server/requirments.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
fastapi
|
||||
uvicorn
|
||||
54
server/server.py
Normal file
54
server/server.py
Normal file
@@ -0,0 +1,54 @@
|
||||
from fastapi import FastAPI, Request, Header, Depends, Response, HTTPException
|
||||
from fastapi.responses import FileResponse
|
||||
import os
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
config_path: Path = Path("./config.json")
|
||||
config: dict = {}
|
||||
with open(config_path, "r") as f:
|
||||
config = json.load(f)
|
||||
|
||||
CONTENT_PATH: Path = Path(config["content"]).resolve()
|
||||
MODS_PATH: Path = CONTENT_PATH / "mods"
|
||||
RESOURCEPACKS_PATH: Path = CONTENT_PATH / "resourcepacks"
|
||||
|
||||
if not CONTENT_PATH.exists():
|
||||
CONTENT_PATH.mkdir(parents=True)
|
||||
MODS_PATH.mkdir()
|
||||
RESOURCEPACKS_PATH.mkdir()
|
||||
|
||||
# Токен для доступа к сервису
|
||||
TOKEN: str = None
|
||||
TOKENFILE = Path(__file__).parent / "token.txt"
|
||||
if not TOKENFILE.exists():
|
||||
TOKEN = os.urandom(48).hex()
|
||||
|
||||
with open(TOKENFILE, "w") as f:
|
||||
f.write(TOKEN)
|
||||
else:
|
||||
with open(TOKENFILE, "r") as f:
|
||||
TOKEN = f.read()
|
||||
|
||||
# Функция для проверки токена
|
||||
def check_token(authorization: str = Header(...)):
|
||||
if authorization != TOKEN:
|
||||
raise HTTPException(status_code=401, detail="Неверный токен")
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@app.get("/mods/files")
|
||||
async def get_files():
|
||||
# Получаем список всех файлов в указанной директории
|
||||
files = os.listdir(str(MODS_PATH))
|
||||
return {"files": files}
|
||||
|
||||
|
||||
@app.get("/mods/download/{filename}")
|
||||
async def download_file(filename: str):
|
||||
file_path: Path = MODS_PATH / filename
|
||||
|
||||
if not file_path.exists():
|
||||
return {"error": f"Файл {filename} не найден"}
|
||||
|
||||
return FileResponse(path=file_path, filename=str(filename), media_type="application/octet-stream")
|
||||
4
server/start-server.sh
Executable file
4
server/start-server.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
source .venv/bin/activate
|
||||
uvicorn main:app --host 0.0.0.0 --port 7779
|
||||
5
updater/config.json
Normal file
5
updater/config.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"minecraft": "./",
|
||||
"server.url": "http://localhost:7779",
|
||||
"token": ""
|
||||
}
|
||||
1
updater/requirments.txt
Normal file
1
updater/requirments.txt
Normal file
@@ -0,0 +1 @@
|
||||
requests
|
||||
21
updater/update.bat
Normal file
21
updater/update.bat
Normal file
@@ -0,0 +1,21 @@
|
||||
@echo off
|
||||
|
||||
:: Если это git репозиторий то автоматически обновляемся
|
||||
IF EXIST .git (
|
||||
git pull
|
||||
)
|
||||
|
||||
:: Проверяем существование виртуального окружения
|
||||
IF EXIST .\venv (
|
||||
:: Активируем виртуальное окружение
|
||||
call .venv\Scripts\activate.bat
|
||||
) ELSE (
|
||||
:: Создаем новое виртуальное окружение
|
||||
python -m venv .venv
|
||||
call .venv\Scripts\activate.bat
|
||||
pip3 install -r requirements.txt
|
||||
)
|
||||
|
||||
|
||||
:: Запускаем скрипт updater.py
|
||||
python .\updater.py
|
||||
15
updater/update.sh
Executable file
15
updater/update.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ -d ".git" ]; then
|
||||
git pull
|
||||
fi
|
||||
|
||||
if [ ! -d ".venv" ]; then
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip3 install -r ./requirments.txt
|
||||
else
|
||||
source .venv/bin/activate
|
||||
fi
|
||||
|
||||
python3 ./updater.py
|
||||
68
updater/updater.py
Normal file
68
updater/updater.py
Normal file
@@ -0,0 +1,68 @@
|
||||
from pathlib import Path
|
||||
import json
|
||||
import os
|
||||
import requests
|
||||
|
||||
CONFIG_FILE: Path = Path(__file__).parent / "config.json"
|
||||
CONFIG: dict = {}
|
||||
with CONFIG_FILE.open() as f:
|
||||
CONFIG = json.load(f)
|
||||
|
||||
TOKEN: str = CONFIG["token"]
|
||||
|
||||
MINECRAFT_FOLDER: Path = Path(CONFIG["minecraft"]).resolve()
|
||||
MODS_FOLDER: Path = MINECRAFT_FOLDER / "mods"
|
||||
|
||||
# Создаем папку модов если ее нет
|
||||
if not MODS_FOLDER.exists():
|
||||
MODS_FOLDER.mkdir(parents=True)
|
||||
|
||||
CURRENT_MODS: list["Path"] = [Path(p).name for p in os.listdir(MODS_FOLDER)]
|
||||
|
||||
def get_mod_list():
|
||||
headers = {'Authorization': TOKEN}
|
||||
response = requests.get(f'{CONFIG["server.url"]}/mods/files', headers=headers)
|
||||
if response.status_code == 200:
|
||||
return response.json().get('files', [])
|
||||
else:
|
||||
print(f'Ошибка при получении списка файлов: {response.text}')
|
||||
return []
|
||||
|
||||
|
||||
def download_file(filename: str, dest: Path):
|
||||
headers = {'Authorization': TOKEN}
|
||||
url = f'{CONFIG["server.url"]}/mods/download/{filename}'
|
||||
response = requests.get(url, headers=headers)
|
||||
if response.status_code == 200:
|
||||
with open(dest, 'wb') as f:
|
||||
f.write(response.content)
|
||||
print(f'Файл {filename} успешно загружен.')
|
||||
else:
|
||||
print(f'Не удалось загрузить файл {filename}: {response.text}')
|
||||
|
||||
|
||||
ACTUAL_MODS: list["str"] = get_mod_list()
|
||||
|
||||
TO_DELETE: list["Path"] = []
|
||||
TO_DOWNLOAD: list["str"] = []
|
||||
|
||||
# Проверяем лишние или старые моды
|
||||
for cur_mod in CURRENT_MODS:
|
||||
# Проверяем лишние или старые моды
|
||||
if cur_mod not in ACTUAL_MODS:
|
||||
TO_DELETE.append(MODS_FOLDER / cur_mod)
|
||||
|
||||
for amod in ACTUAL_MODS:
|
||||
if amod not in CURRENT_MODS:
|
||||
TO_DOWNLOAD.append(amod)
|
||||
|
||||
# Применение действий
|
||||
|
||||
# Удаление лишнего
|
||||
for file in TO_DELETE:
|
||||
print(f"Удаление {amod}")
|
||||
os.remove(str(file))
|
||||
|
||||
# Скачивание нужного
|
||||
for filename in TO_DOWNLOAD:
|
||||
download_file(filename, MODS_FOLDER / filename)
|
||||
Reference in New Issue
Block a user