Add a server switcher and new config

This commit is contained in:
sowgro 2023-09-24 23:26:28 -04:00
parent 6ea80b9c66
commit 36f4406e1d
21 changed files with 741 additions and 726 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
config.yaml
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/
*.py[cod] *.py[cod]

View File

@ -1,5 +1,61 @@
# About this Fork
This fork adds support for multiple servers with a server switching system
```
server [servername]
```
As well as a new config file `config.yaml`
```yaml
Servers:
Srv1:
Connection: local
ServerRootPath: C:/Users/USER/Desktop/server
PluginFolderPath: C:/Users/USER/Desktop/server/plugins
SeperateDownloadPath: false
Srv2:
Connection: sftp
ServerRootPath: /
PluginFolderPath: /plugins
SeperateDownloadPath: /plugins/updated
Server: mc.example.com
Username: joe
Password: pass
Port: 22
Srv3:
Connection: ftp
ServerRootPath: /
PluginFolderPath: /plugins
SeperateDownloadPath: false
Server: mc.example.com
Username: joe
Password: pass
Port: 21
AnotherServerName:
Connection: local
ServerRootPath: /srv/mc
PluginFolderPath: /srv/mc/plugins
SeperateDownloadPath: /srv/mc/plugins/downloaded
# more can be added
```
### Features I plan to add in the future
- Improved CLI with support for one word commands
- Modular plugin and serverjar system / more repos
- Batch actions across multiple servers
<br />
---
<br />
<br />
<p align="center"> <p align="center">
<picture> <picture>
<source media="(prefers-color-scheme: dark)" srcset="./assets/branding/pluget-logo-white.png"> <source media="(prefers-color-scheme: dark)" srcset="./assets/branding/pluget-logo-white.png">

View File

@ -7,10 +7,11 @@ import argparse
# check if folder 'src' is accessible with all modules needed and if not exit # check if folder 'src' is accessible with all modules needed and if not exit
try: try:
from src.handlers.handle_config import check_config, validate_config from src.handlers.handle_config import check_config, read_config, validate_config
from src.utils.console_output import rename_console_title, clear_console, print_logo, print_console_logo from src.utils.console_output import rename_console_title, clear_console, print_logo, print_console_logo
from src.utils.utilities import check_requirements, api_test_spiget, check_for_pluGET_update from src.utils.utilities import api_test_spiget, check_for_pluGET_update
from src.handlers.handle_input import handle_input from src.handlers.handle_input import handle_input
from src.handlers.handle_server import server_list
except TypeError: except TypeError:
print("Folder 'src' not found in the directory or missing files or broken functions detected! \ print("Folder 'src' not found in the directory or missing files or broken functions detected! \
\nPlease redownload the files from here: https://www.github.com/Neocky/pluGET") \nPlease redownload the files from here: https://www.github.com/Neocky/pluGET")
@ -29,8 +30,9 @@ if __name__ == "__main__":
rename_console_title() rename_console_title()
check_config() check_config()
validate_config() validate_config()
read_config()
api_test_spiget() api_test_spiget()
check_requirements() # check_requirements()
if args["mode"] is not None and args["object"] is not None: if args["mode"] is not None and args["object"] is not None:
# arguments were used so call the handle_input function to get the right function call # arguments were used so call the handle_input function to get the right function call
@ -41,5 +43,5 @@ if __name__ == "__main__":
# no arguments were used so start pluGET console # no arguments were used so start pluGET console
clear_console() clear_console()
print_logo() print_logo()
check_for_pluGET_update() # check_for_pluGET_update()
handle_input() handle_input()

37
src/config-sample.yaml Normal file
View File

@ -0,0 +1,37 @@
Servers:
Srv1:
Connection: local
ServerRootPath: C:/Users/USER/Desktop/server
PluginFolderPath: C:/Users/USER/Desktop/server/plugins
SeperateDownloadPath: false
Srv2:
Connection: sftp
ServerRootPath: /
PluginFolderPath: /plugins
SeperateDownloadPath: /plugins/updated
Server: mc.example.com
Username: joe
Password: pass
Port: 22
Srv3:
Connection: ftp
ServerRootPath: /
PluginFolderPath: /plugins
SeperateDownloadPath: false
Server: mc.example.com
Username: joe
Password: pass
Port: 21
Srv4:
Connection: local
ServerRootPath: /srv/mc
PluginFolderPath: /srv/mc/plugins
SeperateDownloadPath: /srv/mc/plugins/downloaded
# more can be added

View File

@ -5,105 +5,109 @@
import os import os
import sys import sys
import ruamel.yaml import ruamel.yaml
import shutil
from pathlib import Path from pathlib import Path
from rich.console import Console from rich.console import Console
from src.servers.local import local_server
from src.servers.ftp import ftp_server
from src.servers.sftp import sftp_server
from src.handlers.handle_server import server_list
from src.handlers import handle_server
def read_config():
class config_value():
""" """
Class which holds all the available configuration values from the config file and which will be used later in Reads the config file and populates the server handler
the process of updating plugins
If bool in config can't be read it will default to 'False'
""" """
def __init__(self): yaml = ruamel.yaml.YAML()
yaml = ruamel.yaml.YAML() with open("config.yaml", "r") as config_file:
with open("pluGET_config.yaml", "r") as config_file: data = yaml.load(config_file)
data = yaml.load(config_file) for server in data["Servers"]:
self.connection = str(data["Connection"]).lower() data2 = data["Servers"][server]
self.path_to_plugin_folder = Path(data["Local"]["PathToPluginFolder"])
self.local_seperate_download_path = True if data["Local"]["SeperateDownloadPath"] == True else False match data2["Connection"]:
self.local_path_to_seperate_download_path = Path(data["Local"]["PathToSeperateDownloadPath"]) case "local":
self.server = data["Remote"]["Server"] temp = local_server()
self.username = data["Remote"]["Username"] case "ftp":
self.password = data["Remote"]["Password"] temp = ftp_server()
self.sftp_port = int(data["Remote"]["SFTP_Port"]) case "sftp":
self.ftp_port = int(data["Remote"]["FTP_Port"]) temp = sftp_server()
self.remote_seperate_download_path = True if data["Remote"]["SeperateDownloadPath"] == True else False
self.remote_path_to_seperate_download_path = data["Remote"]["PathToSeperateDownloadPath"]
self.remote_plugin_folder_on_server = data["Remote"]["PluginFolderOnServer"]
temp.name = str(server)
temp.connection = data2["Connection"]
temp.root_path = Path(data2["ServerRootPath"])
temp.plugin_path = Path(data2["PluginFolderPath"])
temp.seperate_download_path = data2["SeperateDownloadPath"]
if temp.connection == "sftp" or temp.connection == "ftp":
temp.server = data2["Server"]
temp.username = data2["Username"]
temp.password = data2["Password"]
temp.port = int(data2["Port"])
server_list[str(server)] = temp
handle_server.active_server = server_list[next(iter(server_list))]
def check_config() -> None: def check_config() -> None:
""" """
Check if there is a pluGET_config.yml file in the same folder as pluget.py and if not create a new config Check if there is a pluGET_config.yml file in the same folder as pluget.py and if not create a new config
and exit the programm and exit the programm
""" """
if not os.path.isfile("pluGET_config.yaml"): if not os.path.isfile("config.yaml"):
create_config() create_config()
return None return None
def create_config() -> None: def create_config() -> None:
""" """
Creates the yaml config in the current directory with the filename pluGET_config.yml copies the sample config file into the root folder
""" """
# this is the whole yaml code because of weird formating indention is not possible shutil.copyfile('src/config-sample.yaml', 'config.yaml')
configuration = """\ config_file_path = os.path.abspath("config.yaml")
#
# Configuration File for pluGET
# https://www.github.com/Neocky/pluGET
#
# What should be used for the connection (local, sftp, ftp)
Connection: local
Local:
PathToPluginFolder: C:/Users/USER/Desktop/plugins
# If a different folder should be used to store the updated plugins change to (True/False) and the path below
SeperateDownloadPath : False
PathToSeperateDownloadPath: C:/Users/USER/Desktop/plugins
Remote:
Server: 0.0.0.0
Username: user
Password: password
# If a different Port for SFTP/FTP will be used
SFTP_Port: 22
FTP_Port: 21
# If a different folder should be used to store the updated plugins change to (True/False) and the path below
SeperateDownloadPath : False
PathToSeperateDownloadPath: /plugins/updated
# Change the path below if the plugin folder path is different on the SFTP/FTP server (Change only if you know what you are doing)
PluginFolderOnServer: /plugins
"""
# load ruamel.yaml to get the # commands right in the yaml code
yaml = ruamel.yaml.YAML()
code = yaml.load(configuration)
with open("pluGET_config.yaml", "w") as config_file:
yaml.dump(code, config_file)
config_file_path = os.path.abspath("pluGET_config.yaml")
print(f"Path of config file: {config_file_path}") print(f"Path of config file: {config_file_path}")
print("Config created. Edit config before executing again!") print("Config created. Edit config before executing again!")
input("Press any key + enter to exit...") input("Press any key + enter to exit...")
sys.exit() sys.exit()
def validate_config() -> None: def validate_config() -> None:
""" """
Validates the config variables after config class is loaded and exit if error is detected and print error Check for missing entries in the config
""" """
accepted_values = [ yaml = ruamel.yaml.YAML()
("local", "sftp", "ftp") with open("config.yaml", "r") as config_file:
] data = yaml.load(config_file)
# exit afterwards if there is an error in config
exit_afterwards = False
config = config_value()
# rich console for nice colors
console = Console() console = Console()
if config.connection not in accepted_values[0]: exit_afterwards = False
console.print(f"Error in Config! Accepted values for key 'Connection' are {accepted_values[0]}",
style="bright_red") if "Servers" not in data:
console.print(f"Config file is malformed",style="bright_red",highlight=False)
exit_afterwards = True exit_afterwards = True
if exit_afterwards: else:
for server in data["Servers"]:
temp = data["Servers"][server]
keys = ["Connection","ServerRootPath","PluginFolderPath","SeperateDownloadPath"]
remote_keys = ["Server","Username","Password","port"]
if temp == None:
console.print(f"'{str(server)}' is malformed",style="bright_red",highlight=False)
exit_afterwards = True
else:
for cur in keys:
if cur not in temp:
console.print(f"'{str(server)}' is missing key '{cur}'",style="bright_red",highlight=False)
exit_afterwards = True
if "Connection" in temp:
accepted_values = ("local", "sftp", "ftp")
if temp["Connection"] not in accepted_values:
console.print(f"'{server}' has invalid key 'Connection' Valid options: {accepted_values}",style="bright_red",highlight=False)
exit_afterwards = True
if temp["Connection"] == "sftp" or temp["Connection"] == "ftp":
for cur in remote_keys:
if cur not in temp:
console.print(f"'{str(server)}' is missing key '{cur}'",style="bright_red",highlight=False)
exit_afterwards = True
if exit_afterwards:
sys.exit() sys.exit()

View File

@ -1,187 +0,0 @@
import os
import sys
import ftplib
import re
from src.utils.console_output import rich_print_error
from src.handlers.handle_config import config_value
def ftp_create_connection():
"""
Creates a connection to the ftp server with the given values in the config
:returns: ftp connection type
"""
config_values = config_value()
try:
ftp = ftplib.FTP()
ftp.connect(config_values.server, config_values.ftp_port)
ftp.login(config_values.username, config_values.password)
return ftp
except UnboundLocalError:
rich_print_error("Error: [SFTP]: Check your config file!")
rich_print_error("Exiting program...")
sys.exit()
def ftp_show_plugins(ftp) -> None:
"""
Prints all plugins in the plugin folder
:param ftp: ftp connection
:returns: None
"""
config_values = config_value()
ftp.cwd(config_values.remote_plugin_folder_on_server)
for attr in ftp.dir():
print(attr.filename, attr)
return None
def ftp_upload_file(ftp, path_item) -> None:
"""
Uploads a file to the ftp server
:param ftp: ftp connection
:param path_item: Name of the item which should be uploaded
:returns: None
"""
config_values = config_value()
if config_values.remote_seperate_download_path is True:
path_upload_folder = config_values.remote_path_to_seperate_download_path
else:
path_upload_folder = config_values.remote_plugin_folder_on_server
try:
ftp.cwd(path_upload_folder)
path_item = os.path.relpath(path_item, 'TempSFTPFolder/')
path_item = str(path_item)
current_directory = os.getcwd()
os.chdir('TempSFTPFolder')
with open (path_item, 'rb') as plugin_file:
ftp.storbinary('STOR '+ str(path_item), plugin_file)
except FileNotFoundError:
rich_print_error("Error: [FTP]: The 'plugins' folder couldn't be found on the remote host!")
rich_print_error("Error: [FTP]: Aborting uploading.")
os.chdir(current_directory)
ftp.close()
return None
def ftp_upload_server_jar(ftp, path_item) -> None:
"""
Uploads a serverjar to the root folder of the ftp host
:param ftp: ftp connection
:param path_item: Name of the file which should be uploaded
:returns: None
"""
try:
ftp.cwd('.')
path_item = os.path.relpath(path_item, 'TempSFTPFolder/')
path_item = str(path_item)
current_directory = os.getcwd()
os.chdir('TempSFTPFolder')
with open (path_item, 'rb') as server_jar:
ftp.storbinary('STOR '+ str(path_item), server_jar)
except FileNotFoundError:
rich_print_error("Error: [FTP]: The 'root' folder couldn't be found on the remote host!")
rich_print_error("Error: [FTP]: Aborting uploading.")
os.chdir(current_directory)
ftp.close()
return None
def ftp_list_all(ftp):
"""
Returns a list with all installed plugins in the plugin folder of the ftp host
:param ftp: ftp connection
:returns: List of all plugins in plugin folder
"""
config_values = config_value()
try:
ftp.cwd(config_values.remote_plugin_folder_on_server)
installed_plugins = ftp.nlst()
except FileNotFoundError:
rich_print_error("Error: [FTP]: The 'plugins' folder couldn't be found on the remote host!")
try:
return installed_plugins
except UnboundLocalError:
rich_print_error("Error: [FTP]: No plugins were found.")
def ftp_list_files_in_server_root(ftp):
"""
Returns a list with all files in the root folder of the ftp host
:param ftp: ftp connection
:returns: List of all files in root folder
"""
try:
ftp.cwd('.')
filesInServerRoot = ftp.nlst()
except FileNotFoundError:
rich_print_error("Error: [FTP]: The 'root' folder couldn't be found on the remote host!")
try:
return filesInServerRoot
except UnboundLocalError:
rich_print_error("Error: [FTP]: No Serverjar was found.")
def ftp_download_file(ftp, path_download, file) -> None:
"""
Download a file of the ftp server
:param ftp: ftp connection
:param path_download: Path to save downloaded file to
:param file: File to download
:returns None
"""
config_values = config_value()
ftp.cwd(config_values.remote_plugin_folder_on_server)
filedata = open(path_download,'wb')
ftp.retrbinary('RETR '+file, filedata.write)
filedata.close()
ftp.quit()
return None
def ftp_is_file(ftp, plugin_path) -> bool:
"""
Check if file on ftp host is a file and not a directory
:param ftp: ftp connection
:param plugin_path
:returns: True if file is a file and not a directory
"""
if ftp.nlst(plugin_path) == [plugin_path]:
return True
else:
return False
def ftp_validate_file_attributes(ftp, plugin_path) -> bool:
"""
Check if a file is a legitimate plugin file
:param ftp: ftp connection
:param plugin_path: Path of file to check
:returns: If file is a plugin file or not
"""
if ftp_is_file(ftp, plugin_path) is False:
return False
if re.search(r'.jar$', plugin_path):
return True
else:
return False

View File

@ -8,11 +8,14 @@ from src.plugin.plugin_remover import delete_plugin
from src.plugin.plugin_downloader import get_specific_plugin_spiget, search_specific_plugin_spiget from src.plugin.plugin_downloader import get_specific_plugin_spiget, search_specific_plugin_spiget
from src.plugin.plugin_updatechecker import check_installed_plugins, update_installed_plugins from src.plugin.plugin_updatechecker import check_installed_plugins, update_installed_plugins
from src.serverjar.serverjar_updatechecker import \ from src.serverjar.serverjar_updatechecker import \
check_update_available_installed_server_jar, update_installed_server_jar check_update_available_installed_server_jar, update_installed_server_jar
from src.serverjar.serverjar_paper_velocity_waterfall import serverjar_papermc_update from src.serverjar.serverjar_paper_velocity_waterfall import serverjar_papermc_update
from src.serverjar.serverjar_purpur import serverjar_purpur_update from src.serverjar.serverjar_purpur import serverjar_purpur_update
from src.handlers.handle_server import server_list
from src.handlers import handle_server
# server
# check # check
# update # update
# get # get
@ -53,7 +56,18 @@ def handle_input(
# KeyboardInterrupt was triggered and None was returned so exit # KeyboardInterrupt was triggered and None was returned so exit
return return
match input_command: match input_command:
case "server":
match input_selected_object:
case "is":
print(handle_server.active_server.name)
case _:
try:
handle_server.active_server = server_list[input_selected_object]
print("Set to "+handle_server.active_server.name)
except KeyError:
print("Invalid server name")
case "get": case "get":
match input_selected_object.isdigit(): match input_selected_object.isdigit():
case True: case True:
@ -110,7 +124,7 @@ def get_input() -> str:
:returns: Optional parameter :returns: Optional parameter
""" """
input_command = None input_command = None
print("\n'STRG + C' to exit") # print("\n'STRG + C' to exit")
while True: while True:
try: try:
input_command, input_selected_object, *input_parameter = input("pluGET >> ").split() input_command, input_selected_object, *input_parameter = input("pluGET >> ").split()

View File

@ -0,0 +1,6 @@
"""
Stores variables related to server switching
"""
server_list = {}
active_server = None

View File

@ -1,168 +0,0 @@
import sys
import os
import pysftp
import paramiko
import stat
import re
from src.utils.console_output import rich_print_error
from src.handlers.handle_config import config_value
def sftp_create_connection():
"""
Creates a sftp connection with the given values in the config file
:returns: SFTP connection type
"""
config_values = config_value()
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None # TODO fix this
try:
sftp = pysftp.Connection(config_values.server, username=config_values.username, \
password=config_values.password, port=config_values.sftp_port, cnopts=cnopts)
except paramiko.ssh_exception.AuthenticationException:
rich_print_error("Error: [SFTP]: Wrong Username/Password")
except paramiko.ssh_exception.SSHException:
rich_print_error("Error: [SFTP]: The SFTP server isn't available.")
try:
return sftp
except UnboundLocalError:
rich_print_error("Error: [SFTP]: Check your config file!")
rich_print_error("Exiting program...")
sys.exit()
def sftp_show_plugins(sftp) -> None:
"""
Prints all plugins in the sftp folder
:param sftp: sftp connection
:returns: None
"""
config_values = config_value()
sftp.cd(config_values.remote_plugin_folder_on_server)
for attr in sftp.listdir_attr():
print(attr.filename, attr)
sftp.close()
return None
def sftp_upload_file(sftp, path_item) -> None:
"""
Uploads a file to the set folder from the config file
:param sftp: sftp connection
:param path_item: The upload path with the item name
:returns: None
"""
config_values = config_value()
if config_values.remote_seperate_download_path is True:
path_upload_folder = config_values.remote_path_to_seperate_download_path
else:
path_upload_folder = config_values.remote_plugin_folder_on_server
try:
sftp.chdir(path_upload_folder)
sftp.put(path_item)
except FileNotFoundError:
rich_print_error("Error: [SFTP]: The 'plugins' folder couldn't be found on the remote host!")
rich_print_error("Error: [SFTP]: Aborting uploading.")
sftp.close()
return None
def sftp_upload_server_jar(sftp, path_item) -> None:
"""
Uploads the server jar to the root folder
:param sftp: sftp connection
:param path_item: The upload path with the item name
:returns: None
"""
try:
sftp.chdir('.')
sftp.put(path_item)
except FileNotFoundError:
rich_print_error("Error: [SFTP]: The 'root' folder couldn't be found on the remote host!")
rich_print_error("Error: [SFTP]: Aborting uploading.")
sftp.close()
return None
def sftp_list_all(sftp):
"""
List all plugins in the 'plugins' folder on the sftp host
:param sftp: sftp connection
:return: List of plugins in plugin folder
"""
config_values = config_value()
try:
sftp.chdir(config_values.remote_plugin_folder_on_server)
installed_plugins = sftp.listdir()
except FileNotFoundError:
rich_print_error("Error: [SFTP]: The 'plugins' folder couldn't be found on the remote host!")
try:
return installed_plugins
except UnboundLocalError:
rich_print_error("Error: [SFTP]: No plugins were found.")
def sftp_list_files_in_server_root(sftp):
"""
List all files in the root folder on the sftp host
:param sftp: sftp connection
:returns: List of files in root folder
"""
try:
files_in_server_root = sftp.listdir()
except FileNotFoundError:
rich_print_error("Error: [SFTP]: The 'root' folder couldn't be found on the remote host!")
try:
return files_in_server_root
except UnboundLocalError:
rich_print_error("Error: [SFTP]: No Serverjar was found.")
def sftp_download_file(sftp, file) -> None:
"""
Downloads a plugin file from the sftp host to a temporary folder
:param sftp: sftp connection
:param file: Filename of plugin
:returns: None
"""
config_values = config_value()
sftp.cwd(config_values.remote_plugin_folder_on_server)
current_directory = os.getcwd()
os.chdir('TempSFTPFolder')
sftp.get(file)
sftp.close()
os.chdir(current_directory)
return None
def sftp_validate_file_attributes(sftp, plugin_path) -> bool:
"""
Check if the file is a legitimate plugin file
:param sftp: sftp connection
param plugin_path: Path of the single plugin file
:returns: If file is a plugin file or not
"""
plugin_sftp_attribute = sftp.lstat(plugin_path)
if stat.S_ISDIR(plugin_sftp_attribute.st_mode):
return False
elif re.search(r'.jar$', plugin_path):
return True
else:
return False

View File

@ -13,9 +13,7 @@ from rich.progress import Progress
from src.utils.utilities import convert_file_size_down, remove_temp_plugin_folder, create_temp_plugin_folder from src.utils.utilities import convert_file_size_down, remove_temp_plugin_folder, create_temp_plugin_folder
from src.utils.utilities import api_do_request from src.utils.utilities import api_do_request
from src.utils.console_output import rich_print_error from src.utils.console_output import rich_print_error
from src.handlers.handle_config import config_value from src.handlers import handle_server
from src.handlers.handle_sftp import sftp_create_connection, sftp_upload_file
from src.handlers.handle_ftp import ftp_create_connection, ftp_upload_file
def handle_regex_plugin_name(full_plugin_name) -> str: def handle_regex_plugin_name(full_plugin_name) -> str:
@ -73,31 +71,10 @@ def get_version_name_spiget(plugin_id, plugin_version_id) -> str:
version_name = response["name"] version_name = response["name"]
return version_name return version_name
def get_download_path(config_values) -> str:
"""
Reads the config and gets the path of the plugin folder
"""
match (config_values.connection):
case "local":
match (config_values.local_seperate_download_path):
case True:
return config_values.local_path_to_seperate_download_path
case _:
return config_values.path_to_plugin_folder
case _:
match (config_values.remote_seperate_download_path):
case True:
return config_values.remote_path_to_seperate_download_path
case _:
return config_values.remote_plugin_folder_on_server
def download_specific_plugin_version_spiget(plugin_id, download_path, version_id="latest") -> None: def download_specific_plugin_version_spiget(plugin_id, download_path, version_id="latest") -> None:
""" """
Download a specific plugin Download a specific plugin
""" """
config_values = config_value()
if version_id != "latest" and version_id != None: if version_id != "latest" and version_id != None:
#url = f"https://spigotmc.org/resources/{plugin_id}/download?version={versionID}" #url = f"https://spigotmc.org/resources/{plugin_id}/download?version={versionID}"
rich_print_error("Sorry but specific version downloads aren't supported because of cloudflare protection. :(") rich_print_error("Sorry but specific version downloads aren't supported because of cloudflare protection. :(")
@ -144,12 +121,9 @@ def download_specific_plugin_version_spiget(plugin_id, download_path, version_id
console.print(" [not bold][bright_green]Downloaded[bright_magenta] " + (str(file_size_data)).rjust(9) + \ console.print(" [not bold][bright_green]Downloaded[bright_magenta] " + (str(file_size_data)).rjust(9) + \
f" KB [cyan]→ [white]{download_path}") f" KB [cyan]→ [white]{download_path}")
if config_values.connection == "sftp": handle_server.active_server.create_connection()
sftp_session = sftp_create_connection() handle_server.active_server.upload_plugin(download_path)
sftp_upload_file(sftp_session, download_path)
elif config_values.connection == "ftp":
ftp_session = ftp_create_connection()
ftp_upload_file(ftp_session, download_path)
return None return None
@ -157,12 +131,8 @@ def get_specific_plugin_spiget(plugin_id, plugin_version="latest") -> None:
""" """
Gets the specific plugin and calls the download function Gets the specific plugin and calls the download function
""" """
config_values = config_value()
# use a temporary folder to store plugins until they are uploaded # use a temporary folder to store plugins until they are uploaded
if config_values.connection != "local": download_path = create_temp_plugin_folder()
download_path = create_temp_plugin_folder()
else:
download_path = get_download_path(config_values)
url = f"https://api.spiget.org/v2/resources/{plugin_id}" url = f"https://api.spiget.org/v2/resources/{plugin_id}"
plugin_details = api_do_request(url) plugin_details = api_do_request(url)
@ -188,8 +158,7 @@ def get_specific_plugin_spiget(plugin_id, plugin_version="latest") -> None:
plugin_version_id = None plugin_version_id = None
download_specific_plugin_version_spiget(plugin_id, download_plugin_path, plugin_version_id) download_specific_plugin_version_spiget(plugin_id, download_plugin_path, plugin_version_id)
if config_values.connection != "local": remove_temp_plugin_folder()
remove_temp_plugin_folder()
return None return None

View File

@ -6,11 +6,8 @@ import os
import re import re
from pathlib import Path from pathlib import Path
from rich.console import Console from rich.console import Console
from src.handlers.handle_config import config_value
from src.utils.console_output import rich_print_error from src.utils.console_output import rich_print_error
from src.handlers.handle_sftp import sftp_create_connection, sftp_list_all from src.handlers import handle_server
from src.handlers.handle_ftp import ftp_create_connection, ftp_list_all
def delete_plugin(plugin_name: str) -> None: def delete_plugin(plugin_name: str) -> None:
@ -21,36 +18,18 @@ def delete_plugin(plugin_name: str) -> None:
:returns: None :returns: None
""" """
config_values = config_value()
rich_console = Console() rich_console = Console()
match config_values.connection: handle_server.active_server.create_connection()
case "sftp": plugin_list = handle_server.active_server.list_plugins()
connection = sftp_create_connection()
plugin_list = sftp_list_all()
case "ftp":
connection = ftp_create_connection()
plugin_list = ftp_list_all()
case "local":
plugin_list = os.listdir(config_values.path_to_plugin_folder)
for plugin_file in plugin_list: for plugin_file in plugin_list:
# skip all other plugins # skip all other plugins
if not re.search(plugin_name, plugin_file, re.IGNORECASE): if not re.search(plugin_name, plugin_file, re.IGNORECASE):
continue continue
try: try:
match config_values.connection: handle_server.active_server.delete_plugin(plugin_file)
case "sftp":
plugin_path = f"{config_values.remote_plugin_folder_on_server}/{plugin_file}"
connection = sftp_create_connection()
connection.remove(plugin_path)
case "ftp":
plugin_path = f"{config_values.remote_plugin_folder_on_server}/{plugin_file}"
connection = ftp_create_connection()
connection.delete(plugin_path)
case "local":
pluginPath = Path(f"{config_values.path_to_plugin_folder}/{plugin_file}")
os.remove(pluginPath)
rich_console.print(f"[not bold][bright_green]Successfully removed: [bright_magenta]{plugin_file}") rich_console.print(f"[not bold][bright_green]Successfully removed: [bright_magenta]{plugin_file}")
except: except:
rich_print_error(f"[not bold]Error: Couldn't remove [bright_magenta]{plugin_file}") rich_print_error(f"[not bold]Error: Couldn't remove [bright_magenta]{plugin_file}")
handle_server.active_server.close_connection()
return None return None

View File

@ -13,13 +13,10 @@ from rich.console import Console
from urllib.error import HTTPError from urllib.error import HTTPError
from zipfile import ZipFile from zipfile import ZipFile
from src.handlers.handle_config import config_value from src.plugin.plugin_downloader import get_specific_plugin_spiget
from src.handlers.handle_sftp import sftp_create_connection, sftp_download_file, sftp_validate_file_attributes, sftp_list_all
from src.handlers.handle_ftp import ftp_create_connection, ftp_download_file, ftp_validate_file_attributes, ftp_list_all
from src.plugin.plugin_downloader import get_specific_plugin_spiget, get_download_path
from src.utils.console_output import rich_print_error from src.utils.console_output import rich_print_error
from src.utils.utilities import api_do_request, create_temp_plugin_folder, remove_temp_plugin_folder from src.utils.utilities import api_do_request, create_temp_plugin_folder, remove_temp_plugin_folder
from src.handlers import handle_server
class Plugin(): class Plugin():
""" """
@ -215,21 +212,11 @@ def egg_cracking_jar(plugin_file_name: str) -> str:
:returns: Plugin name in plugin.yml file :returns: Plugin name in plugin.yml file
:returns: Plugin version in plugin.yml file :returns: Plugin version in plugin.yml file
""" """
config_values = config_value() path_temp_plugin_folder = create_temp_plugin_folder()
match config_values.connection: handle_server.active_server.create_connection()
case "sftp": handle_server.active_server.download_plugin(plugin_file_name,path_temp_plugin_folder)
path_temp_plugin_folder = create_temp_plugin_folder() path_plugin_jar = Path(f"{path_temp_plugin_folder}/{plugin_file_name}")
connection = sftp_create_connection()
sftp_download_file(connection, plugin_file_name)
path_plugin_jar = Path(f"{path_temp_plugin_folder}/{plugin_file_name}")
case "ftp":
path_temp_plugin_folder = create_temp_plugin_folder()
connection = ftp_create_connection()
path_plugin_jar = Path(f"{path_temp_plugin_folder}/{plugin_file_name}")
ftp_download_file(connection, path_plugin_jar, plugin_file_name)
case _:
path_plugin_folder = config_values.path_to_plugin_folder
path_plugin_jar = Path(f"{path_plugin_folder}/{plugin_file_name}")
# later used to escape for-loop # later used to escape for-loop
plugin_name = plugin_version = "" plugin_name = plugin_version = ""
@ -255,52 +242,30 @@ def egg_cracking_jar(plugin_file_name: str) -> str:
except zipfile.BadZipFile: except zipfile.BadZipFile:
plugin_name = plugin_version = "" plugin_name = plugin_version = ""
# remove temp plugin folder if plugin was downloaded from sftp/ftp server # remove temp plugin folder
if config_values.connection != "local": remove_temp_plugin_folder()
remove_temp_plugin_folder()
return plugin_name, plugin_version return plugin_name, plugin_version
def check_update_available_installed_plugins(input_selected_object: str, config_values: config_value) -> str: def check_update_available_installed_plugins(input_selected_object: str) -> str:
""" """
Gets installed plugins and checks it against the apis if there are updates for the plugins available Gets installed plugins and checks it against the apis if there are updates for the plugins available
:param input_selected_object: Command line input (default: all) :param input_selected_object: Command line input (default: all)
:param config_values: Config values from config file
:returns: Count of plugins, Count of plugins with available updates :returns: Count of plugins, Count of plugins with available updates
""" """
Plugin.create_plugin_list() Plugin.create_plugin_list()
match config_values.connection: handle_server.active_server.create_connection()
case "sftp": plugin_list = handle_server.active_server.list_plugins()
connection = sftp_create_connection()
plugin_list = sftp_list_all(connection)
case "ftp":
connection = ftp_create_connection()
plugin_list = ftp_list_all(connection)
case _:
plugin_folder_path = config_values.path_to_plugin_folder
plugin_list = os.listdir(plugin_folder_path)
plugin_count = plugins_with_udpates = 0 plugin_count = plugins_with_udpates = 0
# create simple progress bar from rich # create simple progress bar from rich
for plugin_file in track(plugin_list, description="[cyan]Checking...", transient=True, style="bright_yellow"): for plugin_file in track(plugin_list, description="[cyan]Checking...", transient=True, style="bright_yellow"):
plugin_attributes = True
match config_values.connection: plugin_attributes = handle_server.active_server.validate_plugin(plugin_file)
case "sftp":
plugin_attributes = sftp_validate_file_attributes(
connection, f"{config_values.remote_plugin_folder_on_server}/{plugin_file}"
)
case "ftp":
plugin_attributes = ftp_validate_file_attributes(
connection, f"{config_values.remote_plugin_folder_on_server}/{plugin_file}"
)
case _:
if not os.path.isfile(Path(f"{plugin_folder_path}/{plugin_file}")):
plugin_attributes = False
if not re.search(r'.jar$', plugin_file):
plugin_attributes = False
# skip plugin if no attributes were found to skip not valid plugin files # skip plugin if no attributes were found to skip not valid plugin files
if plugin_attributes == False: if plugin_attributes == False:
continue continue
@ -337,8 +302,7 @@ def check_installed_plugins(input_selected_object : str="all", input_parameter :
:returns: None :returns: None
""" """
config_values = config_value() plugin_count, plugins_with_udpates = check_update_available_installed_plugins(input_selected_object)
plugin_count, plugins_with_udpates = check_update_available_installed_plugins(input_selected_object, config_values)
# print rich table of found plugins and result # print rich table of found plugins and result
rich_table = Table(box=None) rich_table = Table(box=None)
@ -384,22 +348,19 @@ def update_installed_plugins(input_selected_object : str="all", no_confirmation
:returns: None :returns: None
""" """
rich_console = Console() rich_console = Console()
config_values = config_value()
match config_values.connection: handle_server.active_server.create_connection()
case "sftp":
connection = sftp_create_connection()
case "ftp":
connection = ftp_create_connection()
# if INSTALLEDPLUGINLIST was not previously filled by 'check' command call the command to fill plugin list # if INSTALLEDPLUGINLIST was not previously filled by 'check' command call the command to fill plugin list
try: try:
if len(INSTALLEDPLUGINLIST) == 0: if len(INSTALLEDPLUGINLIST) == 0:
check_update_available_installed_plugins(input_selected_object, config_values) check_update_available_installed_plugins(input_selected_object)
except NameError: except NameError:
check_update_available_installed_plugins(input_selected_object, config_values) check_update_available_installed_plugins(input_selected_object)
# if argument 'all' was given recheck all plugins to avoid having only a few plugins from previously cached checks # if argument 'all' was given recheck all plugins to avoid having only a few plugins from previously cached checks
if input_selected_object == "all" or input_selected_object == "*": if input_selected_object == "all" or input_selected_object == "*":
check_update_available_installed_plugins(input_selected_object, config_values) check_update_available_installed_plugins(input_selected_object)
# skip confirmation message if pluGET was called with --no-confirmation # skip confirmation message if pluGET was called with --no-confirmation
if no_confirmation == False: if no_confirmation == False:
@ -428,79 +389,32 @@ def update_installed_plugins(input_selected_object : str="all", no_confirmation
) )
plugins_updated += 1 plugins_updated += 1
plugin_path = get_download_path(config_values) match (plugin.plugin_repository):
match config_values.connection: case "spigot":
# local plugin folder try:
case "local": get_specific_plugin_spiget(plugin.plugin_repository_data[0])
match (plugin.plugin_repository): except HTTPError as err:
case "spigot": rich_print_error(f"HTTPError: {err.code} - {err.reason}")
try: plugins_updated -= 1
get_specific_plugin_spiget(plugin.plugin_repository_data[0]) except TypeError:
except HTTPError as err: rich_print_error(
rich_print_error(f"HTTPError: {err.code} - {err.reason}") f"Error: TypeError > Couldn't download new version. Is the file available on spigotmc?"
plugins_updated -= 1 )
except TypeError: plugins_updated -= 1
rich_print_error(
f"Error: TypeError > Couldn't download new version. Is the file available on spigotmc?"
)
plugins_updated -= 1
case _:
rich_print_error("Error: Plugin repository wasn't found")
return None
# don't delete files if they are downloaded to a seperate download path
if config_values.local_seperate_download_path == False:
try:
os.remove(Path(f"{plugin_path}/{plugin.plugin_file_name}"))
rich_console.print(
" [not bold][bright_green]Deleted old plugin file [cyan]→ [white]" +
f"{plugin.plugin_file_name}"
)
except FileNotFoundError:
rich_print_error("Error: Old plugin file couldn't be deleted")
# plugin folder is on sftp or ftp server
case _: case _:
plugin_path = f"{plugin_path}/{plugin.plugin_file_name}" rich_print_error("Error: Plugin repository wasn't found")
match (plugin.plugin_repository): return None
case "spigot": # don't delete old plugin files if they are downloaded to a seperate download path
try: if handle_server.active_server.connection == False:
get_specific_plugin_spiget(plugin.plugin_repository_data[0]) try:
except HTTPError as err: handle_server.active_server.remove(plugin.plugin_file_name)
rich_print_error(f"HTTPError: {err.code} - {err.reason}") rich_console.print(
plugins_updated -= 1 " [not bold][bright_green]Deleted old plugin file [cyan]→ [white]" +
except TypeError: f"{plugin.plugin_file_name}"
rich_print_error( )
f"Error: TypeError > Couldn't download new version. Is the file available on spigotmc?" except FileNotFoundError:
) rich_print_error("Error: Old plugin file couldn't be deleted")
plugins_updated -= 1
case _:
rich_print_error("Error: Plugin repository wasn't found")
return None
# don't delete old plugin files if they are downloaded to a seperate download path
if config_values.remote_seperate_download_path == False:
match config_values.connection:
case "sftp":
try:
connection.remove(plugin_path)
rich_console.print(
" [not bold][bright_green]Deleted old plugin file [cyan]→ [white]" +
f"{plugin.plugin_file_name}"
)
except FileNotFoundError:
rich_print_error("Error: Old plugin file couldn't be deleted")
case "ftp":
try:
connection.delete(plugin_path)
rich_console.print(
" [not bold][bright_green]Deleted old plugin file [cyan]→ [white]" +
f"{plugin.plugin_file_name}"
)
except FileNotFoundError:
rich_print_error("Error: Old plugin file couldn't be deleted")
rich_console.print( rich_console.print(
f"\n[not bold][bright_green]Plugins updated: {plugins_updated}/{(len(INSTALLEDPLUGINLIST) - plugins_skipped)}" f"\n[not bold][bright_green]Plugins updated: {plugins_updated}/{(len(INSTALLEDPLUGINLIST) - plugins_skipped)}"

View File

@ -11,11 +11,12 @@ from pathlib import Path
from rich.table import Table from rich.table import Table
from rich.console import Console from rich.console import Console
from rich.progress import Progress from rich.progress import Progress
from src.handlers import handle_server
from src.handlers.handle_config import config_value # from src.handlers.handle_config import config_value
from src.utils.console_output import rich_print_error from src.utils.console_output import rich_print_error
from src.handlers.handle_sftp import sftp_create_connection, sftp_upload_server_jar # from src.handlers.handle_sftp import sftp_create_connection, sftp_upload_server_jar
from src.handlers.handle_ftp import ftp_create_connection, ftp_upload_server_jar # from src.handlers.handle_ftp import ftp_create_connection, ftp_upload_server_jar
from src.utils.utilities import \ from src.utils.utilities import \
api_do_request, create_temp_plugin_folder, remove_temp_plugin_folder, convert_file_size_down api_do_request, create_temp_plugin_folder, remove_temp_plugin_folder, convert_file_size_down
@ -169,16 +170,8 @@ def serverjar_papermc_update(
:returns: True/False if the serverjar was downloaded successfully :returns: True/False if the serverjar was downloaded successfully
""" """
config_values = config_value()
match config_values.connection: path_server_root = create_temp_plugin_folder()
case "local":
path_server_root = config_values.path_to_plugin_folder
# need help_path or else TypeError will be thrown
help_path = Path('/plugins')
help_path_str = str(help_path)
path_server_root = Path(str(path_server_root).replace(help_path_str, ''))
case _:
path_server_root = create_temp_plugin_folder()
# exit if the mc version can't be found # exit if the mc version can't be found
if file_server_jar_full_name == None and mc_version == None: if file_server_jar_full_name == None and mc_version == None:
@ -264,14 +257,9 @@ def serverjar_papermc_update(
file_size_data = convert_file_size_down(convert_file_size_down(file_size)) file_size_data = convert_file_size_down(convert_file_size_down(file_size))
rich_console.print(" [not bold][bright_green]Downloaded[bright_magenta] " + (str(file_size_data)).rjust(9) + \ rich_console.print(" [not bold][bright_green]Downloaded[bright_magenta] " + (str(file_size_data)).rjust(9) + \
f" MB [cyan]→ [white]{download_path}") f" MB [cyan]→ [white]{download_path}")
if config_values.connection == "sftp": handle_server.active_server.create_connection()
sftp_session = sftp_create_connection() handle_server.active_server.upload_server_jar(download_path)
sftp_upload_server_jar(sftp_session, download_path) remove_temp_plugin_folder()
remove_temp_plugin_folder()
elif config_values.connection == "ftp":
ftp_session = ftp_create_connection()
ftp_upload_server_jar(ftp_session, download_path)
remove_temp_plugin_folder()
return True return True

View File

@ -10,10 +10,8 @@ from rich.table import Table
from rich.console import Console from rich.console import Console
from rich.progress import Progress from rich.progress import Progress
from src.handlers.handle_config import config_value
from src.utils.console_output import rich_print_error from src.utils.console_output import rich_print_error
from src.handlers.handle_sftp import sftp_create_connection, sftp_upload_server_jar from src.handlers import handle_server
from src.handlers.handle_ftp import ftp_create_connection, ftp_upload_server_jar
from src.utils.utilities import \ from src.utils.utilities import \
api_do_request, create_temp_plugin_folder, remove_temp_plugin_folder, convert_file_size_down api_do_request, create_temp_plugin_folder, remove_temp_plugin_folder, convert_file_size_down
from src.serverjar.serverjar_paper_velocity_waterfall import \ from src.serverjar.serverjar_paper_velocity_waterfall import \
@ -114,16 +112,8 @@ def serverjar_purpur_update(
:returns: True/False if the serverjar was downloaded successfully :returns: True/False if the serverjar was downloaded successfully
""" """
config_values = config_value()
match config_values.connection: path_server_root = create_temp_plugin_folder()
case "local":
path_server_root = config_values.path_to_plugin_folder
# need help_path or else TypeError will be thrown
help_path = Path('/plugins')
help_path_str = str(help_path)
path_server_root = Path(str(path_server_root).replace(help_path_str, ''))
case _:
path_server_root = create_temp_plugin_folder()
# exit if the mc version can't be found # exit if the mc version can't be found
if file_server_jar_full_name == None and mc_version == None: if file_server_jar_full_name == None and mc_version == None:
@ -196,13 +186,8 @@ def serverjar_purpur_update(
rich_console.print(" [not bold][bright_green]Downloaded[bright_magenta] " + (str(file_size_data)).rjust(9) + \ rich_console.print(" [not bold][bright_green]Downloaded[bright_magenta] " + (str(file_size_data)).rjust(9) + \
f" MB [cyan]→ [white]{download_path}") f" MB [cyan]→ [white]{download_path}")
if config_values.connection == "sftp": handle_server.active_server.create_connection()
sftp_session = sftp_create_connection() handle_server.active_server.upload_server_jar(download_path)
sftp_upload_server_jar(sftp_session, download_path) remove_temp_plugin_folder()
remove_temp_plugin_folder()
elif config_values.connection == "ftp":
ftp_session = ftp_create_connection()
ftp_upload_server_jar(ftp_session, download_path)
remove_temp_plugin_folder()
return True return True

View File

@ -6,15 +6,13 @@ import os
from pathlib import Path from pathlib import Path
from rich.console import Console from rich.console import Console
from src.handlers.handle_config import config_value
from src.utils.console_output import rich_print_error from src.utils.console_output import rich_print_error
from src.handlers.handle_sftp import sftp_create_connection, sftp_list_files_in_server_root
from src.handlers.handle_ftp import ftp_create_connection, ftp_list_files_in_server_root
from src.serverjar.serverjar_paper_velocity_waterfall import serverjar_papermc_check_update, serverjar_papermc_update from src.serverjar.serverjar_paper_velocity_waterfall import serverjar_papermc_check_update, serverjar_papermc_update
from src.serverjar.serverjar_purpur import serverjar_purpur_check_update, serverjar_purpur_update from src.serverjar.serverjar_purpur import serverjar_purpur_check_update, serverjar_purpur_update
from src.handlers import handle_server
def get_installed_server_jar_file(config_values) -> str: def get_installed_server_jar_file() -> str:
""" """
Gets the file name of the installed server jar Gets the file name of the installed server jar
@ -22,16 +20,8 @@ def get_installed_server_jar_file(config_values) -> str:
:returns: Full file name of installed server jar :returns: Full file name of installed server jar
""" """
match config_values.connection:
case "sftp": file_list_server_root = handle_server.active_server.list_server_root()
connection = sftp_create_connection()
file_list_server_root = sftp_list_files_in_server_root(connection)
case "ftp":
connection = ftp_create_connection()
file_list_server_root = ftp_list_files_in_server_root(connection)
case _:
file_list_server_root = os.path.dirname(config_values.path_to_plugin_folder)
file_list_server_root = os.listdir(file_list_server_root)
file_server_jar_full_name = None file_server_jar_full_name = None
try: try:
@ -54,8 +44,7 @@ def check_update_available_installed_server_jar() -> None:
:returns: None :returns: None
""" """
config_values = config_value() file_server_jar_full_name = get_installed_server_jar_file()
file_server_jar_full_name = get_installed_server_jar_file(config_values)
if file_server_jar_full_name == None: if file_server_jar_full_name == None:
# print error and exit function # print error and exit function
rich_print_error("Error: Serverjar couldn't be found") rich_print_error("Error: Serverjar couldn't be found")
@ -84,24 +73,14 @@ def update_installed_server_jar(server_jar_version: str="latest") -> None:
:returns: None :returns: None
""" """
config_values = config_value() file_server_jar_full_name = get_installed_server_jar_file()
file_server_jar_full_name = get_installed_server_jar_file(config_values)
if file_server_jar_full_name == None: if file_server_jar_full_name == None:
# print error and exit function # print error and exit function
rich_print_error("Error: Serverjar couldn't be found") rich_print_error("Error: Serverjar couldn't be found")
return None return None
# finding path which is used for deleting old server jar # finding path which is used for deleting old server jar
match config_values.connection: path_server_root = handle_server.active_server.root_path
case "local":
path_server_root = config_values.path_to_plugin_folder
# need help_path or else TypeError will be thrown
help_path = Path('/plugins')
help_path_str = str(help_path)
path_server_root = Path(str(path_server_root).replace(help_path_str, ''))
case _:
path_server_root = config_values.remote_plugin_folder_on_server
path_server_root = str(path_server_root).replace(r'/plugins', '')
server_jar_path = f"{path_server_root}/{file_server_jar_full_name}" server_jar_path = f"{path_server_root}/{file_server_jar_full_name}"
rich_console = Console() rich_console = Console()
@ -122,15 +101,7 @@ def update_installed_server_jar(server_jar_version: str="latest") -> None:
# remove old serverjar when the serverjar was sucessfully updated # remove old serverjar when the serverjar was sucessfully updated
if download_successfull is True: if download_successfull is True:
match config_values.connection: handle_server.active_server.delete_server_jar(server_jar_path)
case "local":
os.remove(Path(server_jar_path))
case "sftp":
connection = sftp_create_connection()
connection.remove(server_jar_path)
case "ftp":
connection = ftp_create_connection()
connection.delete(server_jar_path)
rich_console.print( rich_console.print(
" [not bold][bright_green]Deleted old server file [cyan]→ [white]" + " [not bold][bright_green]Deleted old server file [cyan]→ [white]" +
f"{file_server_jar_full_name}" f"{file_server_jar_full_name}"

148
src/servers/ftp.py Normal file
View File

@ -0,0 +1,148 @@
import os
import sys
import ftplib
import re
from pathlib import Path
from src.utils.console_output import rich_print_error
class ftp_server():
def create_connection(self):
"""
Creates a connection to the ftp server with the given values in the config
"""
try:
ftp = ftplib.FTP()
ftp.connect(self.server, self.port)
ftp.login(self.username, self.password)
self.ftp = ftp
except UnboundLocalError:
rich_print_error("Error: [SFTP]: Check your config file!")
rich_print_error("Exiting program...")
sys.exit()
def close_connection(self):
"""
Closes the ftp connection
"""
self.ftp.close()
def upload_plugin(self, path_item) -> None:
"""
Uploads a plugin to the plugins folder or seperate download folder
:param path_item: Name of the item which should be uploaded
:returns: None
"""
if self.seperate_download_path is not False:
path_upload_folder = self.seperate_download_path
else:
path_upload_folder = self.plugin_path
try:
self.ftp.cwd(path_upload_folder)
with open (path_item, 'rb') as plugin_file:
self.ftp.storbinary('STOR '+ str(path_item), plugin_file)
except FileNotFoundError:
rich_print_error("Error: [FTP]: The 'plugins' folder couldn't be found on the remote host!")
rich_print_error("Error: [FTP]: Aborting uploading.")
return None
def upload_server_jar(self, path_item) -> None:
"""
Uploads a serverjar to the root folder of the ftp host
:param path_item: Name of the file which should be uploaded
:returns: None
"""
try:
self.ftp.cwd(self.root_path)
with open (path_item, 'rb') as server_jar:
self.ftp.storbinary('STOR '+ str(path_item), server_jar)
except FileNotFoundError:
rich_print_error("Error: [FTP]: The 'root' folder couldn't be found on the remote host!")
rich_print_error("Error: [FTP]: Aborting uploading.")
return None
def list_plugins(self):
"""
Returns a list with all installed plugins in the plugin folder of the ftp host
:returns: List of all plugins in plugin folder
"""
try:
self.ftp.cwd(self.plugin_path)
installed_plugins = self.ftp.nlst()
except FileNotFoundError:
rich_print_error("Error: [FTP]: The 'plugins' folder couldn't be found on the remote host!")
try:
return installed_plugins
except UnboundLocalError:
rich_print_error("Error: [FTP]: No plugins were found.")
def list_server_root(self):
"""
Returns a list with all files in the root folder of the ftp host
:returns: List of all files in root folder
"""
try:
self.ftp.cwd(self.server_root)
filesInServerRoot = self.ftp.nlst()
except FileNotFoundError:
rich_print_error("Error: [FTP]: The 'root' folder couldn't be found on the remote host!")
try:
return filesInServerRoot
except UnboundLocalError:
rich_print_error("Error: [FTP]: No Serverjar was found.")
def download_plugin(self, file, dest) -> None:
"""
Downloads a plugin file from the sftp host to the dest folder
:param file: name of the plugin file
:param dest: destination (on this system)
:returns None
"""
self.ftp.cwd(self.plugin_path)
filedata = open(dest,'wb')
self.ftp.retrbinary('RETR '+file, filedata.write)
filedata.close()
self.ftp.quit()
return None
def validate_file_attributes(self, file) -> bool:
"""
Check if a file is a legitimate plugin file
:param ftp: ftp connection
:param plugin_path: Path of file to check
:returns: If file is a plugin file or not
"""
plugin_path = f"{self.plugin_path}/{file}"
if self.ftp.nlst(plugin_path) == [plugin_path] is False:
return False
if re.search(r'.jar$', plugin_path):
return True
else:
return False
def delete_plugin(self, file):
"""
Deletes a plugin from the plugins folder
:param file: The name of the file to delete
"""
self.ftp.delete(f"{self.plugin_path}/{file}")
def delete_server_jar(self, file):
"""
Deletes a plugin from the server root
:param file: The name of the file to delete
"""
self.ftp.delete(f"{self.root_path}/{file}")

100
src/servers/local.py Normal file
View File

@ -0,0 +1,100 @@
import os
import shutil
import re
from pathlib import Path
class local_server():
def create_connection(self):
"""
Does not do anything, placeholder for if this were a remote connection
"""
pass
def close_connection(self):
"""
Does not do anything, placeholder for if this were a remote connection
"""
pass
def upload_plugin(self, file):
"""
Moves a plugin to the plugins folder or seperate download folder
:param path_item: Name of the item which should be moved
:returns: None
"""
if self.seperate_download_path is not False:
path_upload_folder = self.seperate_download_path
else:
path_upload_folder = self.plugin_path
shutil.copy(file, path_upload_folder)
def upload_server_jar(self, file):
"""
Moves a serverjar to the root folder of the server
:param path_item: Name of the file which should be moved
:returns: None
"""
shutil.copy(file, self.root_path)
def list_plugins(self):
"""
Returns a list with all installed plugins in the plugin folder
:returns: List of all plugins in plugin folder
"""
return os.listdir(self.plugin_path)
def list_server_root(self):
"""
Returns a list with all files in the root folder of the server
:returns: List of all files in root folder
"""
return os.listdir(self.root_path)
def download_plugin(self, file, dest):
"""
Moves a plugin file from the plugins folder to the dest folder
:param file: name of the plugin file
:param dest: destination
:returns None
"""
shutil.copy(f"{self.plugin_path}/{file}", dest)
def validate_plugin(self, plugin_file):
"""
Check if a file is a legitimate plugin file
:param ftp: ftp connection
:param plugin_path: Path of file to check
:returns: If file is a plugin file or not
"""
plugin_attributes = True
if not os.path.isfile(Path(f"{self.plugin_path}/{plugin_file}")):
plugin_attributes = False
elif not re.search(r'.jar$', plugin_file):
plugin_attributes = False
return plugin_attributes
def delete_plugin(self, file):
"""
Deletes a plugin from the plugins folder
:param file: The name of the file to delete
"""
os.remove(f"{self.plugin_path}/{file}")
def delete_server_jar(self, file):
"""
Deletes a plugin from the server root
:param file: The name of the file to delete
"""
os.remove(f"{self.root_path}/{file}")

159
src/servers/sftp.py Normal file
View File

@ -0,0 +1,159 @@
import sys
import os
import pysftp
import paramiko
import stat
import re
from pathlib import Path
from src.utils.console_output import rich_print_error
class sftp_server():
def create_connection(self):
"""
Creates a sftp connection with the given values in the config file
"""
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None # TODO fix this
try:
sftp = pysftp.Connection(self.server, username=self.username, \
password=self.password, port=self.port, cnopts=cnopts)
except paramiko.ssh_exception.AuthenticationException:
rich_print_error("Error: [SFTP]: Wrong Username/Password")
except paramiko.ssh_exception.SSHException:
rich_print_error("Error: [SFTP]: The SFTP server isn't available.")
try:
self.sftp = sftp
except UnboundLocalError:
rich_print_error("Error: [SFTP]: Check your config file!")
rich_print_error("Exiting program...")
sys.exit()
def close_connection(self):
"""
Closes the sftp connection
"""
self.sftp.close()
def upload_plugin(self, path_item) -> None:
"""
Uploads a file to the set folder from the config file
:param path_item: The upload path with the item name
:returns: None
"""
if self.seperate_download_path is not False:
path_upload_folder = self.seperate_download_path
else:
path_upload_folder = self.plugin_path
try:
print(path_upload_folder)
self.sftp.chdir(str(path_upload_folder))
self.sftp.put(path_item)
except FileNotFoundError:
rich_print_error("Error: [SFTP]: The 'plugins' folder couldn't be found on the remote host!")
rich_print_error("Error: [SFTP]: Aborting uploading.")
return None
def upload_server_jar(self, path_item) -> None:
"""
Uploads the server jar to the root folder
:param path_item: The upload path with the item name
:returns: None
"""
try:
self.sftp.chdir(self.root_path)
self.sftp.put(path_item)
except FileNotFoundError:
rich_print_error("Error: [SFTP]: The 'root' folder couldn't be found on the remote host!")
rich_print_error("Error: [SFTP]: Aborting uploading.")
self.sftp.close()
return None
def list_plugins(self):
"""
List all plugins in the 'plugins' folder on the sftp host
:return: List of plugins in plugin folder
"""
try:
self.sftp.chdir(str(self.plugin_path))
installed_plugins = self.sftp.listdir()
except FileNotFoundError:
rich_print_error("Error: [SFTP]: The 'plugins' folder couldn't be found on the remote host!")
try:
return installed_plugins
except UnboundLocalError:
rich_print_error("Error: [SFTP]: No plugins were found.")
def list_files_in_server_root(self):
"""
List all files in the root folder on the sftp host
:returns: List of files in root folder
"""
try:
self.sftp.chdir(self.root_path)
files_in_server_root = self.sftp.listdir()
except FileNotFoundError:
rich_print_error("Error: [SFTP]: The 'root' folder couldn't be found on the remote host!")
try:
return files_in_server_root
except UnboundLocalError:
rich_print_error("Error: [SFTP]: No Serverjar was found.")
def download_plugin(self, file, dest) -> None:
"""
Downloads a plugin file from the sftp host to the dest folder
:param file: name of the plugin file
:param dest: destination (on this system)
:returns: None
"""
self.sftp.cwd(str(self.plugin_path))
current_directory = os.getcwd()
os.chdir(dest)
self.sftp.get(file)
self.sftp.close()
os.chdir(current_directory)
return None
def validate_plugin(self, file) -> bool:
"""
Check if the file is a legitimate plugin file
:param sftp: sftp connection
param plugin_path: Path of the single plugin file
:returns: If file is a plugin file or not
"""
self.create_connection()
plugin_path = f"{self.plugin_path}/{file}"
plugin_sftp_attribute = self.sftp.lstat(plugin_path)
if stat.S_ISDIR(plugin_sftp_attribute.st_mode):
return False
elif re.search(r'.jar$', plugin_path):
return True
else:
return False
def delete_plugin(self, file):
"""
Deletes a plugin from the plugins folder
:param file: The name of the file to delete
"""
self.sftp.remove(f"{self.plugin_path}/{file}")
def delete_server_jar(self, file):
"""
Deletes a plugin from the server root
:param file: The name of the file to delete
"""
self.sftp.remove(f"{self.root_path}/{file}")

View File

@ -5,4 +5,4 @@ PLUGETVERSION = current version of pluGET
""" """
# constant values # constant values
PLUGETVERSION = "1.7.2" PLUGETVERSION = "1.7.3"

40
src/tests/all.py Normal file
View File

@ -0,0 +1,40 @@
from src.handlers.handle_server import server_list
class all_servers():
def create_connection(self):
for server in server_list:
server_list[server].create_connection()
def close_connection(self):
for server in server_list:
server_list[server].close_connection
def upload_plugin(self, file):
for server in server_list:
server_list[server].upload_plugin(file)
def upload_server_jar(self, file):
pass
def list_plugins(self):
combined = []
for server in server_list:
combined += server_list[server].list_plugins()
return combined
def list_server_root(self):
pass
def download_plugin(self, file, dest):
for server in server_list:
server_list[server].download_plugin(self, file, dest)
def validate_plugin(self, plugin_file):
pass
def delete_plugin(self, file):
for server in server_list:
server_list[server].delete_plugin(self, file)
def delete_server_jar(self, file):
pass

View File

@ -10,11 +10,8 @@ import re
from pathlib import Path from pathlib import Path
from rich.console import Console from rich.console import Console
from rich.table import Table from rich.table import Table
from src.handlers.handle_sftp import sftp_create_connection
from src.handlers.handle_ftp import ftp_create_connection
from src.utils.console_output import rich_print_error from src.utils.console_output import rich_print_error
from src.handlers.handle_config import config_value
from src.settings import PLUGETVERSION from src.settings import PLUGETVERSION
@ -195,16 +192,15 @@ def check_local_plugin_folder(config_values) -> None:
return None return None
def check_requirements() -> None: # def check_requirements() -> None:
""" # """
Check if the plugin folders are available # Check if the plugin folders are available
""" # """
config_values = config_value() # match config_values.connection:
match config_values.connection: # case "local":
case "local": # check_local_plugin_folder(config_values)
check_local_plugin_folder(config_values) # case "sftp":
case "sftp": # sftp_create_connection()
sftp_create_connection() # case "ftp":
case "ftp": # ftp_create_connection()
ftp_create_connection() # return None
return None