diff --git a/src/core/__init__.py b/src/core/__init__.py
index 35dc9bc..0257735 100644
--- a/src/core/__init__.py
+++ b/src/core/__init__.py
@@ -1,7 +1,7 @@
# Developed by KuiToi Dev
# File core.__init__.py
# Written by: SantaSpeen
-# Version 1.1
+# Version 1.2
# Licence: FPA
# (c) kuitoi.su 2023
# Special thanks to: AI Sage(https://poe.com/Sage), AI falcon-40b-v7(https://OpenBuddy.ai)
@@ -28,7 +28,7 @@ import builtins
import os
import webbrowser
-from prompt_toolkit.shortcuts import input_dialog, yes_no_dialog
+import prompt_toolkit.shortcuts as shortcuts
from .utils import get_logger
from modules import ConfigProvider, EventsSystem, PluginsLoader
@@ -46,13 +46,12 @@ if args.config:
config_path = args.config
config_provider = ConfigProvider(config_path)
config = config_provider.open_config()
-log.info("Use %s for config." % config_path)
if config.Server['debug'] is True:
utils.set_debug_status()
- log.info("Getting new logging with DEBUG level!")
+ log.info("Debug enabled!")
log = get_logger("init")
log.debug("Debug mode enabled!")
- log.debug("Use %s for config." % config)
+ log.debug(f"Server config: {config}")
# i18n init
log.debug("Initializing i18n...")
@@ -60,28 +59,44 @@ ml = MultiLanguage()
ml.set_language(args.language)
ml.builtins_hook()
-log.info(i18n.hello)
-
+log.debug("Initializing EventsSystem...")
ev = EventsSystem()
ev.builtins_hook()
-# Key handler..
-if not config.Auth['key']:
- log.warn("Key needed for starting the server!")
- url = "https://beammp.com/k/keys"
- if yes_no_dialog(
- title='BEAMP Server Key',
- text='Key needed for starting the server!\n'
- 'Do you need to open the web link to obtain the key?').run():
- webbrowser.open(url, new=2)
+log.info(i18n.hello)
+log.info(i18n.config_path.format(config_path))
- config.Auth['key'] = input_dialog(
+log.debug("Initializing BEAMP Server system...")
+# Key handler..
+private = ((config.Auth['key'] is None or config.Auth['key'] == "") and config.Auth['private'])
+if not private:
+ log.warn(i18n.auth_need_key)
+ url = "https://beammp.com/k/keys"
+ if shortcuts.yes_no_dialog(
+ title='BEAMP Server Key',
+ text=i18n.GUI_need_key_message,
+ yes_text=i18n.GUI_yes,
+ no_text=i18n.GUI_no).run():
+ try:
+ log.debug("Opening browser...")
+ webbrowser.open(url, new=2)
+ except Exception as e:
+ log.error(i18n.auth_cannot_open_browser.format(e))
+ log.info(i18n.auth_use_link.format(url))
+ shortcuts.message_dialog(
+ title='BEAMP Server Key',
+ text=i18n.GUI_cannot_open_browser.format(url),
+ ok_text=i18n.GUI_ok).run()
+
+ config.Auth['key'] = shortcuts.input_dialog(
title='BEAMP Server Key',
- text='Please type your key:').run()
+ text=i18n.GUI_enter_key_message,
+ ok_text=i18n.GUI_ok,
+ cancel_text=i18n.GUI_cancel).run()
config_provider.save_config()
-if not config.Auth['key']:
- log.error("Key is empty!")
- log.error("Server stopped!")
+if not private:
+ log.error(i18n.auth_empty_key)
+ log.info(i18n.stop)
exit(1)
builtins.config = config
@@ -90,14 +105,16 @@ log.debug("Initializing console...")
console = Console()
console.builtins_hook()
# console.logger_hook()
-console.add_command("stop", console.stop, "stop - Just shutting down the server.\nUsage: stop", "Server shutdown.")
-console.add_command("exit", console.stop, "stop - Just shutting down the server.\nUsage: stop", "Server shutdown.")
+console.add_command("stop", console.stop, i18n.man_message_stop, i18n.help_message_stop)
+console.add_command("exit", console.stop, i18n.man_message_exit, i18n.help_message_exit)
if not os.path.exists("mods"):
os.mkdir("mods")
+
+
+log.debug("Initializing PluginsLoader...")
if not os.path.exists("plugins"):
os.mkdir("plugins")
-
pl = PluginsLoader("plugins")
pl.load_plugins()
@@ -107,4 +124,4 @@ builtins.MB = KB * 1024
builtins.GB = MB * 1024
builtins.TB = GB * 1024
-log.info(i18n.init)
+log.info(i18n.init_ok)
diff --git a/src/core/core.py b/src/core/core.py
index 03f02c7..b352ac6 100644
--- a/src/core/core.py
+++ b/src/core/core.py
@@ -14,12 +14,13 @@ from .udp_server import UDPServer
class Client:
- def __init__(self, reader, writer):
+ def __init__(self, reader, writer, core):
self.reader = reader
self.writer = writer
self.log = utils.get_logger("client(None:0)")
self.addr = writer.get_extra_info("sockname")
self.loop = asyncio.get_event_loop()
+ self.Core = core
self.cid = 0
self.key = None
self.nick = None
@@ -137,11 +138,11 @@ class Core:
def __init__(self):
self.log = utils.get_logger("core")
+ self.loop = asyncio.get_event_loop()
self.clients = {}
self.clients_counter = 0
self.server_ip = config.Server["server_ip"]
self.server_port = config.Server["server_port"]
- self.loop = asyncio.get_event_loop()
self.tcp = TCPServer
self.udp = UDPServer
@@ -152,14 +153,16 @@ class Core:
return self.clients.get(sock.getsockname())
def insert_client(self, client):
+ self.log.debug(f"Inserting client: {client.cid}")
self.clients.update({client.cid: client, client.nick: client})
def create_client(self, *args, **kwargs):
- cl = Client(*args, **kwargs)
- self.clients_counter = self.clients_counter + 1
- cl.id = self.clients_counter
- cl._update_logger()
- return cl
+ client = Client(*args, **kwargs)
+ self.clients_counter += 1
+ client.id = self.clients_counter
+ client._update_logger()
+ self.log.debug(f"Create client: {client.cid}; clients_counter: {self.clients_counter}")
+ return client
async def check_alive(self):
await asyncio.sleep(5)
@@ -174,7 +177,8 @@ class Core:
self.udp = self.udp(self, self.server_ip, self.server_port)
tasks = [self.tcp.start(), self.udp.start(), console.start()] # self.check_alive()
t = asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION)
- self.log.info(i18n.ready)
+ self.log.info(i18n.start)
+ # TODO: Server auth
ev.call_event("on_started")
await t
# while True:
@@ -193,5 +197,5 @@ class Core:
asyncio.run(self.main())
def stop(self):
- self.log.info("Goodbye!")
+ self.log.info(i18n.stop)
exit(0)
diff --git a/src/core/core.pyi b/src/core/core.pyi
index 3ee28cc..17cf740 100644
--- a/src/core/core.pyi
+++ b/src/core/core.pyi
@@ -5,21 +5,22 @@
# Licence: FPA
# (c) kuitoi.su 2023
import asyncio
-import socket
-from asyncio import StreamWriter, AbstractEventLoop, StreamReader
-from asyncio.trsock import TransportSocket
+from asyncio import StreamWriter, StreamReader
from core import utils
from .tcp_server import TCPServer
from .udp_server import UDPServer
+
+
class Client:
- def __init__(self, reader: StreamReader, writer: StreamWriter):
+ def __init__(self, reader: StreamReader, writer: StreamWriter, core: Core) -> "Client":
self.reader = reader
self.writer = writer
self.log = utils.get_logger("client(id: )")
self.addr = writer.get_extra_info("sockname")
self.loop = asyncio.get_event_loop()
+ self.Core = core
self.cid = 0
self.key: str = None
self.nick: str = None
@@ -32,6 +33,7 @@ class Client:
async def sync_resources(self) -> None: ...
async def recv(self) -> bytes: ...
async def last_handle(self) -> bytes: ...
+ def _update_logger(self) -> None: ...
class Core:
diff --git a/src/modules/ConfigProvider/config_provider.py b/src/modules/ConfigProvider/config_provider.py
index be004aa..c0ec705 100644
--- a/src/modules/ConfigProvider/config_provider.py
+++ b/src/modules/ConfigProvider/config_provider.py
@@ -25,16 +25,16 @@ class Config:
class ConfigProvider:
- def __init__(self, config_patch):
- self.config_patch = config_patch
+ def __init__(self, config_path):
+ self.config_path = config_path
self.config = Config()
def open_config(self):
- if not os.path.exists(self.config_patch):
- with open(self.config_patch, "w", encoding="utf-8") as f:
+ if not os.path.exists(self.config_path):
+ with open(self.config_path, "w", encoding="utf-8") as f:
yaml.dump(self.config, f)
try:
- with open(self.config_patch, "r", encoding="utf-8") as f:
+ with open(self.config_path, "r", encoding="utf-8") as f:
self.config = yaml.load(f.read(), yaml.Loader)
except yaml.YAMLError:
print("You have errors in the YAML syntax.")
@@ -44,5 +44,5 @@ class ConfigProvider:
return self.config
def save_config(self):
- with open(self.config_patch, "w", encoding="utf-8") as f:
+ with open(self.config_path, "w", encoding="utf-8") as f:
yaml.dump(self.config, f)
diff --git a/src/modules/ConsoleSystem/console_system.py b/src/modules/ConsoleSystem/console_system.py
index 3b9e9b8..a121efb 100644
--- a/src/modules/ConsoleSystem/console_system.py
+++ b/src/modules/ConsoleSystem/console_system.py
@@ -6,7 +6,6 @@
# Version 1.1
# Licence: FPA
# (c) kuitoi.su 2023
-import asyncio
import builtins
import logging
from typing import AnyStr
@@ -37,14 +36,9 @@ class Console:
self.__man = dict()
self.__desc = dict()
self.__print_logger = get_logger("print")
- self.add_command("man", self.__create_man_message, "man - display the manual page.\n"
- "Usage: man COMMAND", "Display the manual page",
+ self.add_command("man", self.__create_man_message, i18n.man_message_man, i18n.help_message_man,
custom_completer={"man": {}})
- self.add_command("help", self.__create_help_message,
- "help - display names and brief descriptions of available commands.\n"
- "Usage: help [--raw]\n"
- "The `help` command displays a list of all available commands along with a brief description "
- "of each command.", "Display names and brief descriptions of available commands.",
+ self.add_command("help", self.__create_help_message, i18n.man_message_help, i18n.help_message_help,
custom_completer={"help": {"--raw": None}})
self.completer = NestedCompleter.from_nested_dict(self.__alias)
@@ -68,16 +62,19 @@ class Console:
return i
def __create_man_message(self, argv: list) -> AnyStr:
+ if len(argv) == 0:
+ return self.__man.get("man")
x = argv[0]
- if x in ['']:
- return "man COMMAND"
+ if self.__alias.get(x) is None:
+ return i18n.man_command_not_found.format(x)
+
man_message = self.__man.get(x)
- if man_message is None:
- return "man: Manual message not found."
if man_message:
return man_message
- return f'man: command "{x}" not found'
+ else:
+ return i18n.man_message_not_found
+ # noinspection PyStringFormat
def __create_help_message(self, argv: list) -> AnyStr:
self.__debug("creating help message")
raw = False
@@ -95,7 +92,7 @@ class Console:
if raw:
message += f"%-{max_len}s; %-{max_len_v}s; %s\n" % ("Key", "Function", "Description")
else:
- message += f" %-{max_len}s : %s\n" % ("Command", "Help message")
+ message += f" %-{max_len}s : %s\n" % (i18n.help_command, i18n.help_message)
for k, v in self.__func.items():
doc = self.__desc.get(k)
@@ -105,7 +102,7 @@ class Console:
else:
if doc is None:
- doc = "No help message found"
+ doc = i18n.help_message_not_found
message += f" %-{max_len}s : %s\n" % (k, doc)
return message
@@ -122,7 +119,7 @@ class Console:
self.__alias.update(custom_completer or {key: None})
self.__alias["man"].update({key: None})
self.__func.update({key: {"f": func}})
- self.__man.update({key: f'htmlManual for command {key}\n{man}' if man else None})
+ self.__man.update({key: f'html{i18n.man_for} {key}\n{man}' if man else None})
self.__desc.update({key: desc})
self.__update_completer()
return self.__alias.copy()
diff --git a/src/modules/i18n/files/en.json b/src/modules/i18n/files/en.json
index 0270ee8..7447b66 100644
--- a/src/modules/i18n/files/en.json
+++ b/src/modules/i18n/files/en.json
@@ -1,8 +1,45 @@
{
+ "": "Basic phases",
"hello": "Hello from KuiToi-Server!",
- "config_file": "Use %s for config.",
- "debug": "Getting new logging with DEBUG level!",
- "config_info": "Server config: %s",
- "init": "Initializing ready.",
- "ready": "Server started!"
+ "config_path": "Use {} for config.",
+ "init_ok": "Initializing ready.",
+ "start": "Server started!",
+ "stop": "Goodbye!",
+
+ "": "Server auth",
+ "auth_need_key": "BEAM key needed for starting the server!",
+ "auth_empty_key": "Key is empty!",
+ "auth_cannot_open_browser": "Cannot open browser: {}",
+ "auth_use_link": "Use this link: {}",
+
+ "": "GUI phases",
+ "GUI_yes": "Yes",
+ "GUI_no": "No",
+ "GUI_ok": "Ok",
+ "GUI_cancel": "Cancel",
+ "GUI_need_key_message": "BEAM key needed for starting the server!\nDo you need to open the web link to obtain the key?",
+ "GUI_enter_key_message": "Please type your key:",
+ "GUI_cannot_open_browser": "Cannot open browser.\nUse this link: {}",
+
+ "": "Command: man",
+ "man_message_man": "man - display the manual page for COMMAND.\nUsage: man COMMAND",
+ "help_message_man": "Display the manual page for COMMAND.",
+ "man_for": "Manual for command",
+ "man_message_not_found": "man: Manual message not found.",
+ "man_command_not_found": "man: command \"{}\" not found!",
+
+ "": "Command: help",
+ "man_message_help": "help - display names and brief descriptions of available commands.\nUsage: help [--raw]\nThe `help` command displays a list of all available commands along with a brief description of each command.",
+ "help_message_help": "Display names and brief descriptions of available commands",
+ "help_command": "Command",
+ "help_message": "Help message",
+ "help_message_not_found": "No help message found",
+
+ "": "Command: stop",
+ "man_message_stop": "stop - Just shutting down the server.\nUsage: stop",
+ "help_message_stop": "Server shutdown.",
+
+ "": "Command: exit",
+ "man_message_exit": "exit - Just shutting down the server.\nUsage: stop",
+ "help_message_exit": "Server shutdown."
}
\ No newline at end of file
diff --git a/src/modules/i18n/i18n-builtins.pyi b/src/modules/i18n/i18n-builtins.pyi
index da8744e..86acae2 100644
--- a/src/modules/i18n/i18n-builtins.pyi
+++ b/src/modules/i18n/i18n-builtins.pyi
@@ -1,10 +1,90 @@
class i18n:
- hello: str = "Hello from KuiToi-Server!"
- config_file: str = "Use kuitoi.yml for config."
- debug: str = "Getting new logging with DEBUG level!"
- config_info: str = "Server config: %s"
- init: str = "Initializing ready."
- ready: str = "Server started!"
-i18n_data = {"hello":"Hello from KuiToi-Server!","config_file":"Use kuitoi.yml for config.",
- "debug":"Getting new logging with DEBUG level!","config_info":"Server config: %s",
- "init":"Initializing ready.","ready":"Server started!"}
+ # Basic phases
+ hello: str = data["hello"]
+ config_path: str = data["config_path"]
+ init_ok: str = data["init_ok"]
+ start: str = data["start"]
+ stop: str = data["stop"]
+
+ # Server auth
+ auth_need_key: str = data["auth_need_key"]
+ auth_empty_key: str = data["auth_empty_key"]
+ auth_cannot_open_browser: str = data["auth_cannot_open_browser"]
+ auth_use_link: str = data["auth_use_link"]
+
+ # GUI phases
+ GUI_yes: str = data["GUI_yes"]
+ GUI_no: str = data["GUI_no"]
+ GUI_ok: str = data["GUI_ok"]
+ GUI_cancel: str = data["GUI_cancel"]
+ GUI_need_key_message: str = data["GUI_need_key_message"]
+ GUI_enter_key_message: str = data["GUI_enter_key_message"]
+ GUI_cannot_open_browser: str = data["GUI_cannot_open_browser"]
+
+ # Command: man
+ man_message_man: str = data["man_message_man"]
+ help_message_man: str = data["help_message_man"]
+ man_for: str = data["man_for"]
+ man_message_not_found: str = data["man_message_not_found"]
+ man_command_not_found: str = data["man_command_not_found"]
+
+ # Command: help
+ man_message_help: str = data["man_message_help"]
+ help_message_help: str = data["help_message_help"]
+ help_command: str = data["help_command"]
+ help_message: str = data["help_message"]
+ help_message_not_found: str = data["help_message_not_found"]
+
+ # Command: stop
+ man_message_stop: str = data["man_message_stop"]
+ help_message_stop: str = data["help_message_stop"]
+
+ # Command: exit
+ man_message_exit: str = data["man_message_exit"]
+ help_message_exit: str = data["help_message_exit"]
+
+ data = {
+ "": "Basic phases",
+ "hello": "Hello from KuiToi-Server!",
+ "config_path": "Use {} for config.",
+ "init_ok": "Initializing ready.",
+ "start": "Server started!",
+ "stop": "Goodbye!",
+
+ "": "Server auth",
+ "auth_need_key": "BEAM key needed for starting the server!",
+ "auth_empty_key": "Key is empty!",
+ "auth_cannot_open_browser": "Cannot open browser: {}",
+ "auth_use_link": "Use this link: {}",
+
+ "": "GUI phases",
+ "GUI_yes": "Yes",
+ "GUI_no": "No",
+ "GUI_ok": "Ok",
+ "GUI_cancel": "Cancel",
+ "GUI_need_key_message": "BEAM key needed for starting the server!\nDo you need to open the web link to obtain the key?",
+ "GUI_enter_key_message": "Please type your key:",
+ "GUI_cannot_open_browser": "Cannot open browser.\nUse this link: {}",
+
+ "": "Command: man",
+ "man_message_man": "man - display the manual page for COMMAND.\nUsage: man COMMAND",
+ "help_message_man": "Display the manual page for COMMAND.",
+ "man_for": "Manual for command",
+ "man_message_not_found": "man: Manual message not found.",
+ "man_command_not_found": "man: command \"{}\" not found!",
+
+ "": "Command: help",
+ "man_message_help": "help - display names and brief descriptions of available commands.\nUsage: help [--raw]\nThe `help` command displays a list of all available commands along with a brief description of each command.",
+ "help_message_help": "Display names and brief descriptions of available commands",
+ "help_command": "Command",
+ "help_message": "Help message",
+ "help_message_not_found": "No help message found",
+
+ "": "Command: stop",
+ "man_message_stop": "stop - Just shutting down the server.\nUsage: stop",
+ "help_message_stop": "Server shutdown.",
+
+ "": "Command: exit",
+ "man_message_exit": "exit - Just shutting down the server.\nUsage: stop",
+ "help_message_exit": "Server shutdown."
+}
diff --git a/src/modules/i18n/i18n.py b/src/modules/i18n/i18n.py
index 477fb77..4f216cc 100644
--- a/src/modules/i18n/i18n.py
+++ b/src/modules/i18n/i18n.py
@@ -16,12 +16,51 @@ from core.utils import get_logger
class i18n:
def __init__(self, data):
+ # Basic phases
self.hello: str = data["hello"]
- self.config_file: str = data["config_file"]
- self.debug: str = data["debug"]
- self.config_info: str = data["config_info"]
- self.init: str = data["init"]
- self.ready: str = data["ready"]
+ self.config_path: str = data["config_path"]
+ self.init_ok: str = data["init_ok"]
+ self.start: str = data["start"]
+ self.stop: str = data["stop"]
+
+ # Server auth
+ self.auth_need_key: str = data["auth_need_key"]
+ self.auth_empty_key: str = data["auth_empty_key"]
+ self.auth_cannot_open_browser: str = data["auth_cannot_open_browser"]
+ self.auth_use_link: str = data["auth_use_link"]
+
+ # GUI phases
+ self.GUI_yes: str = data["GUI_yes"]
+ self.GUI_no: str = data["GUI_no"]
+ self.GUI_ok: str = data["GUI_ok"]
+ self.GUI_cancel: str = data["GUI_cancel"]
+ self.GUI_need_key_message: str = data["GUI_need_key_message"]
+ self.GUI_enter_key_message: str = data["GUI_enter_key_message"]
+ self.GUI_cannot_open_browser: str = data["GUI_cannot_open_browser"]
+
+ # Command: man
+ self.man_message_man: str = data["man_message_man"]
+ self.help_message_man: str = data["help_message_man"]
+ self.man_for: str = data["man_for"]
+ self.man_message_not_found: str = data["man_message_not_found"]
+ self.man_command_not_found: str = data["man_command_not_found"]
+
+ # Command: help
+ self.man_message_help: str = data["man_message_help"]
+ self.help_message_help: str = data["help_message_help"]
+ self.help_command: str = data["help_command"]
+ self.help_message: str = data["help_message"]
+ self.help_message_not_found: str = data["help_message_not_found"]
+
+ # Command: help
+ self.man_message_stop: str = data["man_message_stop"]
+ self.help_message_stop: str = data["help_message_stop"]
+
+ # Command: exit
+ self.man_message_exit: str = data["man_message_exit"]
+ self.help_message_exit: str = data["help_message_exit"]
+
+ self.data = data
class MultiLanguage:
@@ -45,13 +84,51 @@ class MultiLanguage:
if language != "en":
self.open_file()
else:
+ # noinspection PyDictDuplicateKeys
self.__data = {
+ "": "Basic phases",
"hello": "Hello from KuiToi-Server!",
- "config_file": "Use %s for config.",
- "debug": "Getting new logging with DEBUG level!",
- "config_info": "Server config: %s",
- "init": "Initializing ready.",
- "ready": "Server started!"
+ "config_path": "Use {} for config.",
+ "init_ok": "Initializing ready.",
+ "start": "Server started!",
+ "stop": "Goodbye!",
+
+ "": "Server auth",
+ "auth_need_key": "BEAM key needed for starting the server!",
+ "auth_empty_key": "Key is empty!",
+ "auth_cannot_open_browser": "Cannot open browser: {}",
+ "auth_use_link": "Use this link: {}",
+
+ "": "GUI phases",
+ "GUI_yes": "Yes",
+ "GUI_no": "No",
+ "GUI_ok": "Ok",
+ "GUI_cancel": "Cancel",
+ "GUI_need_key_message": "BEAM key needed for starting the server!\nDo you need to open the web link to obtain the key?",
+ "GUI_enter_key_message": "Please type your key:",
+ "GUI_cannot_open_browser": "Cannot open browser.\nUse this link: {}",
+
+ "": "Command: man",
+ "man_message_man": "man - display the manual page for COMMAND.\nUsage: man COMMAND",
+ "help_message_man": "Display the manual page for COMMAND.",
+ "man_for": "Manual for command",
+ "man_message_not_found": "man: Manual message not found.",
+ "man_command_not_found": "man: command \"{}\" not found!",
+
+ "": "Command: help",
+ "man_message_help": "help - display names and brief descriptions of available commands.\nUsage: help [--raw]\nThe `help` command displays a list of all available commands along with a brief description of each command.",
+ "help_message_help": "Display names and brief descriptions of available commands",
+ "help_command": "Command",
+ "help_message": "Help message",
+ "help_message_not_found": "No help message found",
+
+ "": "Command: stop",
+ "man_message_stop": "stop - Just shutting down the server.\nUsage: stop",
+ "help_message_stop": "Server shutdown.",
+
+ "": "Command: exit",
+ "man_message_exit": "exit - Just shutting down the server.\nUsage: stop",
+ "help_message_exit": "Server shutdown."
}
self.__i18n = i18n(self.__data)
@@ -63,7 +140,8 @@ class MultiLanguage:
self.__data.update(json.load(f))
return
except JSONDecodeError:
- self.log.error(f"Localisation \"{self.language}.json\" have JsonDecodeError. Using default localisation: en.")
+ self.log.error(
+ f"Localisation \"{self.language}.json\" have JsonDecodeError. Using default localisation: en.")
except FileNotFoundError:
self.log.warning(f"Localisation \"{self.language}.json\" not found; Using default localisation: en.")
self.set_language("en")