mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2025-01-19 09:45:28 +01:00
Merge branch 'dev' into bugfix/correct-tag-styles
This commit is contained in:
commit
f309107174
@ -15,6 +15,7 @@ import zipfile
|
|||||||
import pathlib
|
import pathlib
|
||||||
import shutil
|
import shutil
|
||||||
from requests import get
|
from requests import get
|
||||||
|
from contextlib import suppress
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from socket import gethostname
|
from socket import gethostname
|
||||||
@ -373,9 +374,10 @@ class Helpers:
|
|||||||
logger.critical("Unable to write to {} directory!".format(self.root_dir))
|
logger.critical("Unable to write to {} directory!".format(self.root_dir))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# ensure the log directory is there
|
# ensure the log directory is there
|
||||||
try:
|
try:
|
||||||
os.makedirs(os.path.join(self.root_dir, 'logs'))
|
with suppress(FileExistsError):
|
||||||
|
os.makedirs(os.path.join(self.root_dir, 'logs'))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
console.error("Failed to make logs directory with error: {} ".format(e))
|
console.error("Failed to make logs directory with error: {} ".format(e))
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ class Controller:
|
|||||||
# download the jar
|
# download the jar
|
||||||
server_jar_obj.download_jar(server, version, full_jar_path, name)
|
server_jar_obj.download_jar(server, version, full_jar_path, name)
|
||||||
|
|
||||||
new_id = self.register_server(name, server_id, server_dir, backup_path, server_command, server_file, server_log_file, server_stop)
|
new_id = self.register_server(name, server_id, server_dir, backup_path, server_command, server_file, server_log_file, server_stop, port)
|
||||||
return new_id
|
return new_id
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -253,6 +253,16 @@ class Controller:
|
|||||||
server_path = helper.get_os_understandable_path(server_path)
|
server_path = helper.get_os_understandable_path(server_path)
|
||||||
dir_util.copy_tree(server_path, new_server_dir)
|
dir_util.copy_tree(server_path, new_server_dir)
|
||||||
|
|
||||||
|
has_properties = False
|
||||||
|
for item in os.listdir(new_server_dir):
|
||||||
|
if str(item) == 'server.properties':
|
||||||
|
has_properties = True
|
||||||
|
if not has_properties:
|
||||||
|
logger.info("No server.properties found on zip file import. Creating one with port selection of {}".format(str(port)))
|
||||||
|
with open(os.path.join(new_server_dir, "server.properties"), "w") as f:
|
||||||
|
f.write("server-port={}".format(port))
|
||||||
|
f.close()
|
||||||
|
|
||||||
full_jar_path = os.path.join(new_server_dir, server_jar)
|
full_jar_path = os.path.join(new_server_dir, server_jar)
|
||||||
server_command = 'java -Xms{}M -Xmx{}M -jar {} nogui'.format(helper.float_to_string(min_mem),
|
server_command = 'java -Xms{}M -Xmx{}M -jar {} nogui'.format(helper.float_to_string(min_mem),
|
||||||
helper.float_to_string(max_mem),
|
helper.float_to_string(max_mem),
|
||||||
@ -317,7 +327,7 @@ class Controller:
|
|||||||
server_log_file, server_stop, port)
|
server_log_file, server_stop, port)
|
||||||
return new_id
|
return new_id
|
||||||
|
|
||||||
def register_server(self, name: str, server_uuid: str, server_dir: str, backup_path: str, server_command: str, server_file: str, server_log_file: str, server_stop: str, server_port=25565):
|
def register_server(self, name: str, server_uuid: str, server_dir: str, backup_path: str, server_command: str, server_file: str, server_log_file: str, server_stop: str, server_port: int):
|
||||||
# put data in the db
|
# put data in the db
|
||||||
new_id = self.servers.create_server(name, server_uuid, server_dir, backup_path, server_command, server_file, server_log_file, server_stop, server_port)
|
new_id = self.servers.create_server(name, server_uuid, server_dir, backup_path, server_command, server_file, server_log_file, server_stop, server_port)
|
||||||
|
|
||||||
|
@ -193,6 +193,33 @@ class Server:
|
|||||||
logger.info("Launching Server {} with command {}".format(self.name, self.server_command))
|
logger.info("Launching Server {} with command {}".format(self.name, self.server_command))
|
||||||
console.info("Launching Server {} with command {}".format(self.name, self.server_command))
|
console.info("Launching Server {} with command {}".format(self.name, self.server_command))
|
||||||
|
|
||||||
|
if helper.check_file_exists(os.path.join(self.settings['path'], 'eula.txt')):
|
||||||
|
f = open(os.path.join(self.settings['path'], 'eula.txt'), 'r')
|
||||||
|
line = f.readline().lower()
|
||||||
|
if line == 'eula=true':
|
||||||
|
e_flag = True
|
||||||
|
|
||||||
|
elif line == 'eula = true':
|
||||||
|
e_flag = True
|
||||||
|
|
||||||
|
elif line == 'eula= true':
|
||||||
|
e_flag = True
|
||||||
|
|
||||||
|
elif line == 'eula =true':
|
||||||
|
e_flag = True
|
||||||
|
|
||||||
|
else:
|
||||||
|
e_flag = False
|
||||||
|
else:
|
||||||
|
e_flag = False
|
||||||
|
|
||||||
|
if e_flag == False:
|
||||||
|
websocket_helper.broadcast('send_eula_bootbox', {
|
||||||
|
'id': self.server_id
|
||||||
|
})
|
||||||
|
return False
|
||||||
|
f.close()
|
||||||
|
|
||||||
if helper.is_os_windows():
|
if helper.is_os_windows():
|
||||||
logger.info("Windows Detected")
|
logger.info("Windows Detected")
|
||||||
creationflags=subprocess.CREATE_NEW_CONSOLE
|
creationflags=subprocess.CREATE_NEW_CONSOLE
|
||||||
@ -346,7 +373,7 @@ class Server:
|
|||||||
if self.settings['crash_detection']:
|
if self.settings['crash_detection']:
|
||||||
logger.warning("The server {} has crashed and will be restarted. Restarting server".format(name))
|
logger.warning("The server {} has crashed and will be restarted. Restarting server".format(name))
|
||||||
console.warning("The server {} has crashed and will be restarted. Restarting server".format(name))
|
console.warning("The server {} has crashed and will be restarted. Restarting server".format(name))
|
||||||
self.run_threaded_server()
|
self.run_threaded_server('en_EN')
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
logger.critical(
|
logger.critical(
|
||||||
@ -420,6 +447,13 @@ class Server:
|
|||||||
console.info("Removing old crash detection watcher thread")
|
console.info("Removing old crash detection watcher thread")
|
||||||
schedule.clear(self.name)
|
schedule.clear(self.name)
|
||||||
|
|
||||||
|
def agree_eula(self, user_lang):
|
||||||
|
file = os.path.join(self.server_path, 'eula.txt')
|
||||||
|
f = open(file, 'w')
|
||||||
|
f.write('eula=true')
|
||||||
|
f.close
|
||||||
|
self.run_threaded_server(user_lang)
|
||||||
|
|
||||||
def is_backup_running(self):
|
def is_backup_running(self):
|
||||||
if self.is_backingup:
|
if self.is_backingup:
|
||||||
return True
|
return True
|
||||||
|
@ -207,6 +207,10 @@ class AjaxHandler(BaseHandler):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Could not find PID for requested termsig. Full error: {}".format(e))
|
logger.error("Could not find PID for requested termsig. Full error: {}".format(e))
|
||||||
return
|
return
|
||||||
|
elif page == "eula":
|
||||||
|
server_id = self.get_argument('id', None)
|
||||||
|
svr = self.controller.get_server_obj(server_id)
|
||||||
|
svr.agree_eula(self.controller.users.get_user_lang_by_id(user_data['user_id']))
|
||||||
|
|
||||||
@tornado.web.authenticated
|
@tornado.web.authenticated
|
||||||
def delete(self, page):
|
def delete(self, page):
|
||||||
|
@ -987,7 +987,10 @@ class PanelHandler(BaseHandler):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
self.set_status(404)
|
self.set_status(404)
|
||||||
|
page_data = []
|
||||||
|
page_data['lang'] = tornado.locale.get("en_EN")
|
||||||
self.render(
|
self.render(
|
||||||
"public/404.html",
|
"public/404.html",
|
||||||
translate=self.translator.translate,
|
translate=self.translator.translate,
|
||||||
|
data=page_data
|
||||||
)
|
)
|
||||||
|
@ -40,6 +40,7 @@ class PublicHandler(BaseHandler):
|
|||||||
def get(self, page=None):
|
def get(self, page=None):
|
||||||
|
|
||||||
error = bleach.clean(self.get_argument('error', "Invalid Login!"))
|
error = bleach.clean(self.get_argument('error', "Invalid Login!"))
|
||||||
|
error_msg = bleach.clean(self.get_argument('error_msg', ''))
|
||||||
|
|
||||||
page_data = {
|
page_data = {
|
||||||
'version': helper.get_version_string(),
|
'version': helper.get_version_string(),
|
||||||
@ -75,6 +76,7 @@ class PublicHandler(BaseHandler):
|
|||||||
template,
|
template,
|
||||||
data=page_data,
|
data=page_data,
|
||||||
translate=self.translator.translate,
|
translate=self.translator.translate,
|
||||||
|
error_msg = error_msg
|
||||||
)
|
)
|
||||||
|
|
||||||
def post(self, page=None):
|
def post(self, page=None):
|
||||||
@ -89,18 +91,18 @@ class PublicHandler(BaseHandler):
|
|||||||
|
|
||||||
# if we don't have a user
|
# if we don't have a user
|
||||||
if not user_data:
|
if not user_data:
|
||||||
next_page = "/public/error?error=Login Failed"
|
error_msg = "Inncorrect username or password. Please try again."
|
||||||
self.clear_cookie("user")
|
self.clear_cookie("user")
|
||||||
self.clear_cookie("user_data")
|
self.clear_cookie("user_data")
|
||||||
self.redirect(next_page)
|
self.redirect('/public/login?error_msg={}'.format(error_msg))
|
||||||
return
|
return
|
||||||
|
|
||||||
# if they are disabled
|
# if they are disabled
|
||||||
if not user_data.enabled:
|
if not user_data.enabled:
|
||||||
next_page = "/public/error?error=Login Failed"
|
error_msg = "User account disabled. Please contact your system administrator for more info."
|
||||||
self.clear_cookie("user")
|
self.clear_cookie("user")
|
||||||
self.clear_cookie("user_data")
|
self.clear_cookie("user_data")
|
||||||
self.redirect(next_page)
|
self.redirect('/public/login?error_msg={}'.format(error_msg))
|
||||||
return
|
return
|
||||||
|
|
||||||
login_result = helper.verify_pass(entered_password, user_data.password)
|
login_result = helper.verify_pass(entered_password, user_data.password)
|
||||||
@ -132,9 +134,10 @@ class PublicHandler(BaseHandler):
|
|||||||
else:
|
else:
|
||||||
self.clear_cookie("user")
|
self.clear_cookie("user")
|
||||||
self.clear_cookie("user_data")
|
self.clear_cookie("user_data")
|
||||||
|
error_msg = "Inncorrect username or password. Please try again."
|
||||||
# log this failed login attempt
|
# log this failed login attempt
|
||||||
self.controller.management.add_to_audit_log(user_data.user_id, "Tried to log in", 0, self.get_remote_ip())
|
self.controller.management.add_to_audit_log(user_data.user_id, "Tried to log in", 0, self.get_remote_ip())
|
||||||
self.redirect('/public/error?error=Login Failed')
|
self.redirect('/public/login?error_msg={}'.format(error_msg))
|
||||||
else:
|
else:
|
||||||
self.redirect("/public/login")
|
self.redirect("/public/login")
|
||||||
|
|
||||||
|
@ -10449,10 +10449,10 @@ pre {
|
|||||||
padding-right: 80px; }
|
padding-right: 80px; }
|
||||||
.sidebar > .nav:not(.sub-menu) > .nav-item:hover:not(.nav-profile):not(.hover-open) > .nav-link:not([aria-expanded="true"]):before {
|
.sidebar > .nav:not(.sub-menu) > .nav-item:hover:not(.nav-profile):not(.hover-open) > .nav-link:not([aria-expanded="true"]):before {
|
||||||
border-color: #0b0b0b; }
|
border-color: #0b0b0b; }
|
||||||
.sidebar > .nav:not(.sub-menu) > .nav-item:hover:not(.nav-profile):not(.hover-open) > .nav-link:not([aria-expanded="true"]) .menu-title {
|
.sidebar > .nav:not(.sub-menu) > .nav-item:hover:not(.nav-profile):not(.hover-open) > .nav-link:not([aria-expanded="true"]) {
|
||||||
|
color: #0b0b0b; }
|
||||||
|
.sidebar > .nav:not(.sub-menu) > .nav-item:hover:not(.nav-profile):not(.hover-open) > .nav-link:not([aria-expanded="true"]) .menu-arrow::before {
|
||||||
color: #0b0b0b; }
|
color: #0b0b0b; }
|
||||||
.sidebar > .nav:not(.sub-menu) > .nav-item:hover:not(.nav-profile):not(.hover-open) > .nav-link:not([aria-expanded="true"]) .menu-arrow:before {
|
|
||||||
color: #b9c0d3; }
|
|
||||||
|
|
||||||
/* style for off-canvas menu*/
|
/* style for off-canvas menu*/
|
||||||
@media screen and (max-width: 991px) {
|
@media screen and (max-width: 991px) {
|
||||||
|
@ -237,6 +237,57 @@ if (webSocket) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (webSocket) {
|
||||||
|
webSocket.on('send_eula_bootbox', function (server_id) {
|
||||||
|
var x = document.querySelector('.bootbox');
|
||||||
|
if(x){
|
||||||
|
x.remove()}
|
||||||
|
var x = document.querySelector('.modal-backdrop');
|
||||||
|
if(x){
|
||||||
|
x.remove()}
|
||||||
|
bootbox.confirm({
|
||||||
|
title: '{% raw translate("error", "eulaTitle", data['lang']) %}',
|
||||||
|
message: '{% raw translate("error", "eulaMsg", data['lang']) %} <br><br><a href="https://account.mojang.com/documents/minecraft_eula" target="_blank">EULA</a><br><br>{% raw translate("error", "eulaAgree", data['lang']) %}',
|
||||||
|
buttons: {
|
||||||
|
confirm: {
|
||||||
|
label: 'Yes',
|
||||||
|
className: 'btn-info'
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
label: 'No',
|
||||||
|
className: 'btn-secondary'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
callback: function (result) {
|
||||||
|
if(result == true){
|
||||||
|
eulaAgree(server_id.id)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
location.reload()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function eulaAgree (server_id, command){
|
||||||
|
<!-- this getCookie function is in base.html-->
|
||||||
|
var token = getCookie("_xsrf");
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
headers: {'X-XSRFToken': token},
|
||||||
|
url: '/ajax/eula?id='+ server_id,
|
||||||
|
success: function(data){
|
||||||
|
console.log("got response:");
|
||||||
|
console.log(data);
|
||||||
|
location.reload();
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function warn(message) {
|
function warn(message) {
|
||||||
var closeEl = document.createElement('span');
|
var closeEl = document.createElement('span');
|
||||||
|
@ -94,7 +94,7 @@
|
|||||||
<br>
|
<br>
|
||||||
<h7>{{ translate('dashboard', 'no-servers', data['lang']) }} {{ translate('dashboard', 'newServer', data['lang']) }}.</h7>
|
<h7>{{ translate('dashboard', 'no-servers', data['lang']) }} {{ translate('dashboard', 'newServer', data['lang']) }}.</h7>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% end %}
|
{% end %}
|
||||||
{% if len(data['servers']) > 0 %}
|
{% if len(data['servers']) > 0 %}
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
@ -180,7 +180,7 @@
|
|||||||
{{ server['stats']['online'] }} / {{ server['stats']['max'] }} {{ translate('dashboard', 'max', data['lang']) }}<br />
|
{{ server['stats']['online'] }} / {{ server['stats']['max'] }} {{ translate('dashboard', 'max', data['lang']) }}<br />
|
||||||
|
|
||||||
{% if server['stats']['desc'] != 'False' %}
|
{% if server['stats']['desc'] != 'False' %}
|
||||||
<span id="input_motd_{{ server['stats']['server_id']['server_id'] }}" class="input_motd">{{ server['stats']['desc'] }}</span> <br />
|
{{ server['stats']['desc'] }} <br />
|
||||||
{% end %}
|
{% end %}
|
||||||
|
|
||||||
{% if server['stats']['version'] != 'False' %}
|
{% if server['stats']['version'] != 'False' %}
|
||||||
@ -221,18 +221,13 @@
|
|||||||
{% end %}
|
{% end %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
<script src="/static/assets/js/motd.js"></script>
|
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
$('[data-toggle="popover"]').popover();
|
$('[data-toggle="popover"]').popover();
|
||||||
if($(window).width() < 1000){
|
if($(window).width() < 1000){
|
||||||
$('.too_small').popover("show");
|
$('.too_small').popover("show");
|
||||||
}
|
}
|
||||||
|
|
||||||
var all_motds = Array.from(document.getElementsByClassName('input_motd'));
|
|
||||||
for (element of all_motds) {
|
|
||||||
initParser(element.id, element.id);
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
$(window).ready(function(){
|
$(window).ready(function(){
|
||||||
$('body').click(function(){
|
$('body').click(function(){
|
||||||
@ -345,7 +340,7 @@ $( document ).ready(function() {
|
|||||||
title: '{% raw translate("dashboard", "killing", data['lang']) %}',
|
title: '{% raw translate("dashboard", "killing", data['lang']) %}',
|
||||||
message: '<p><i class="fa fa-spin fa-spinner"></i> Loading...</p>'
|
message: '<p><i class="fa fa-spin fa-spinner"></i> Loading...</p>'
|
||||||
});
|
});
|
||||||
|
|
||||||
dialog.init(function(){
|
dialog.init(function(){
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
location.reload();
|
location.reload();
|
||||||
|
@ -71,6 +71,11 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<button class="login-input btn btn-primary submit-btn btn-block">{{ translate('login', 'login', data['lang']) }}</button>
|
<button class="login-input btn btn-primary submit-btn btn-block">{{ translate('login', 'login', data['lang']) }}</button>
|
||||||
</div>
|
</div>
|
||||||
|
{% if error_msg is not None %}
|
||||||
|
<fieldset style="color: red; text-align: center;">
|
||||||
|
<span>{{error_msg}}</span>
|
||||||
|
</fieldset>
|
||||||
|
{% end %}
|
||||||
<div class="form-group d-flex justify-content-between">
|
<div class="form-group d-flex justify-content-between">
|
||||||
<div class="form-check form-check-flat mt-0">
|
<div class="form-check form-check-flat mt-0">
|
||||||
|
|
||||||
|
@ -13,7 +13,10 @@
|
|||||||
"error": "Error!",
|
"error": "Error!",
|
||||||
"start-error": "Server {} failed to start with error code: {}",
|
"start-error": "Server {} failed to start with error code: {}",
|
||||||
"closedPort": "We have detected port {} may not be open on the host network or a firewall is blocking it. Remote client connections to the server may be limited.",
|
"closedPort": "We have detected port {} may not be open on the host network or a firewall is blocking it. Remote client connections to the server may be limited.",
|
||||||
"internet": "We have detected the machine running Crafty has no connection to the internet. Client connections to the server may be limited."
|
"internet": "We have detected the machine running Crafty has no connection to the internet. Client connections to the server may be limited.",
|
||||||
|
"eulaTitle": "Agree To EULA",
|
||||||
|
"eulaMsg": "You must agree to the EULA. A copy of the Mojang EULA is linked under this message.",
|
||||||
|
"eulaAgree": "Do you agree?"
|
||||||
},
|
},
|
||||||
"404": {
|
"404": {
|
||||||
"contact": "Contact Crafty Control Support via Discord",
|
"contact": "Contact Crafty Control Support via Discord",
|
||||||
|
@ -13,7 +13,10 @@
|
|||||||
"error": "Virhe!",
|
"error": "Virhe!",
|
||||||
"start-error": "Palvelin {} ei käynnistynyt virhekoodilla: {}",
|
"start-error": "Palvelin {} ei käynnistynyt virhekoodilla: {}",
|
||||||
"closedPort": "Olemme havainneet, että portti {} ei ehkä ole auki isäntäverkossa tai palomuuri estää sen. Etäasiakkaan yhteydet palvelimeen voivat olla rajallisia.",
|
"closedPort": "Olemme havainneet, että portti {} ei ehkä ole auki isäntäverkossa tai palomuuri estää sen. Etäasiakkaan yhteydet palvelimeen voivat olla rajallisia.",
|
||||||
"internet": "Olemme havainneet, että Crafty -koneella ei ole Internet -yhteyttä. Asiakasyhteydet palvelimelle voivat olla rajalliset."
|
"internet": "Olemme havainneet, että Crafty -koneella ei ole Internet -yhteyttä. Asiakasyhteydet palvelimelle voivat olla rajalliset.",
|
||||||
|
"eulaTitle": "Hyväksy EULA",
|
||||||
|
"eulaMsg": "Sinun on hyväksyttävä EULA. Kopio Mojang EULA:sta on linkitetty tämän viestin alla.",
|
||||||
|
"eulaAgree": "Oletko samaa mieltä?"
|
||||||
},
|
},
|
||||||
"404": {
|
"404": {
|
||||||
"contact": "Ota yhteyttä Crafty Control -tukeen Discordin kautta",
|
"contact": "Ota yhteyttä Crafty Control -tukeen Discordin kautta",
|
||||||
|
@ -13,7 +13,10 @@
|
|||||||
"error": "Erreur !",
|
"error": "Erreur !",
|
||||||
"start-error": "Le serveur {} n'a pas pu démarrer avec le code d'erreur : {}",
|
"start-error": "Le serveur {} n'a pas pu démarrer avec le code d'erreur : {}",
|
||||||
"closedPort": "Nous avons détecté que le port {} n'est peut-être pas ouvert sur le réseau hôte ou qu'un pare-feu le bloque. Les connexions des clients distants au serveur peuvent être limitées.",
|
"closedPort": "Nous avons détecté que le port {} n'est peut-être pas ouvert sur le réseau hôte ou qu'un pare-feu le bloque. Les connexions des clients distants au serveur peuvent être limitées.",
|
||||||
"internet": "Nous avons détecté que la machine exécutant Crafty n'a pas de connexion à Internet. Les connexions client au serveur peuvent être limitées."
|
"internet": "Nous avons détecté que la machine exécutant Crafty n'a pas de connexion à Internet. Les connexions client au serveur peuvent être limitées.",
|
||||||
|
"eulaTitle": "Accepter le EULA",
|
||||||
|
"eulaMsg": "Vous devez accepter le EULA. Une copie du CLUF de Mojang est liée sous ce message.",
|
||||||
|
"eulaAgree": "Êtes-vous d'accord?"
|
||||||
},
|
},
|
||||||
"404": {
|
"404": {
|
||||||
"contact": "Contacter le Support de Crafty Control via Discord",
|
"contact": "Contacter le Support de Crafty Control via Discord",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
argon2-cffi~=20.1
|
argon2-cffi~=20.1
|
||||||
bleach~=3.1
|
bleach~=3.1
|
||||||
colorama~=0.4
|
colorama~=0.4
|
||||||
|
cryptography~=3.4
|
||||||
peewee~=3.13
|
peewee~=3.13
|
||||||
pexpect~=4.8
|
pexpect~=4.8
|
||||||
psutil~=5.7
|
psutil~=5.7
|
||||||
|
Loading…
x
Reference in New Issue
Block a user