mirror of
				https://github.com/Neocky/pluGET.git
				synced 2024-04-29 16:12:30 +00:00 
			
		
		
		
	Added plugin downloader capabilities
Added plugin downloader capabilities and added full console argument support. Fixed #46 and added error handling for it
This commit is contained in:
		
							
								
								
									
										19
									
								
								pluGET.py
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								pluGET.py
									
									
									
									
									
								
							| @@ -27,21 +27,14 @@ if __name__ == "__main__": | ||||
| 	#parser.add_argument("-a", "--archive", action="store_true", help="archive mode") | ||||
| 	#parser.add_argument("--exclude", help="files to exclude") | ||||
| 	parser.add_argument("mode", help="Mode (install/update)", nargs='?', default=None) | ||||
| 	parser.add_argument("plugin", help="Plugin Name", nargs='?', default=None) | ||||
| 	parser.add_argument("object", help="Object/Plugin Name", nargs='?', default=None) | ||||
| 	parser.add_argument("version", help="Version", nargs='?', default=None) | ||||
| 	args = vars(parser.parse_args()) | ||||
| 	if args["mode"] is not None and args["plugin"] is not None: | ||||
| 		print("arguments") | ||||
|  | ||||
| 	if args["mode"] is not None and args["object"] is not None: | ||||
| 		# arguments were give and call the handle_input function to get the right function call | ||||
| 		handle_input(args["mode"], args["object"], args["version"], arguments_from_console=True) | ||||
| 	else: | ||||
| 		print("no arguments") | ||||
| 		# no arguments were given so start pluGET console | ||||
| 		clear_console() | ||||
| 		print_logo() | ||||
| 		rich_print_error("test") | ||||
| 		rich_print_error("test2") | ||||
| 		handle_input() | ||||
| 	config = config_value() | ||||
| 	print(config.connection) | ||||
| 	print(config.path_to_plugin_folder) | ||||
| 	print(config.sftp_port) | ||||
| 	print(config.local_seperate_download_path) | ||||
|  | ||||
|   | ||||
| @@ -19,7 +19,7 @@ class config_value(): | ||||
| 		yaml = ruamel.yaml.YAML() | ||||
| 		with open("pluGET_config.yaml", "r") as config_file: | ||||
| 			data = yaml.load(config_file) | ||||
| 		self.connection = data["Connection"] | ||||
| 		self.connection = str(data["Connection"]).lower() | ||||
| 		self.path_to_plugin_folder = Path(data["Local"]["PathToPluginFolder"]) | ||||
| 		self.local_seperate_download_path = True if data["Local"]["SeperateDownloadPath"] == True else False | ||||
| 		self.local_path_to_seperate_download_path = Path(data["Local"]["PathToSeperateDownloadPath"]) | ||||
| @@ -100,7 +100,7 @@ def validate_config() -> None: | ||||
| 	config = config_value() | ||||
| 	# rich console for nice colors | ||||
| 	console = Console() | ||||
| 	if (config.connection).lower() not in accepted_values[0]: | ||||
| 	if config.connection not in accepted_values[0]: | ||||
| 		console.print(f"Error in Config! Accepted values for key 'Connection' are {accepted_values[0]}", | ||||
| 		style="bright_red") | ||||
| 		exit_afterwards = True | ||||
|   | ||||
| @@ -1,8 +1,9 @@ | ||||
| """" | ||||
| 	Handles the input through the pluGET command line | ||||
| Handles the input through the pluGET command line | ||||
| """ | ||||
|  | ||||
| from src.utils.utilities import rich_print_error | ||||
| from src.plugin.plugin_downloader import get_specific_plugin | ||||
|  | ||||
|  | ||||
| # check | ||||
| @@ -16,23 +17,24 @@ from src.utils.utilities import rich_print_error | ||||
| # search ??? | ||||
|  | ||||
|  | ||||
| def handle_input() -> None: | ||||
| def handle_input(input_command=None, input_selected_object=None, input_parameter=None, arguments_from_console=False) -> None: | ||||
| 	""" | ||||
| 		Manages the correct function calling from the given input | ||||
| 	Manages the correct function calling from the given input | ||||
| 	""" | ||||
| 	while True: | ||||
| 		try: | ||||
| 			input_command, input_selected_object, input_parameter = get_input() | ||||
| 		except TypeError: | ||||
| 			# KeyboardInterrupt was triggered and None was returned so exit | ||||
| 			return | ||||
| 		# when arguemnts were not passed from console | ||||
| 		if arguments_from_console is False: | ||||
| 			try: | ||||
| 				input_command, input_selected_object, input_parameter = get_input() | ||||
| 			except TypeError: | ||||
| 				# KeyboardInterrupt was triggered and None was returned so exit | ||||
| 				return | ||||
|  | ||||
| 		match input_command: | ||||
| 			case "get": | ||||
| 				match input_selected_object.isdigit(): | ||||
| 					case True: | ||||
| 						print("get specific package") | ||||
| 						#getSpecificPackage(inputSelectedObject, pluginPath,  inputParams) | ||||
| 						get_specific_plugin(input_selected_object, input_parameter) | ||||
| 					case _: | ||||
| 						print("get search specific package") | ||||
| 						#searchPackage(inputSelectedObject) | ||||
| @@ -67,16 +69,23 @@ def handle_input() -> None: | ||||
| 				# download papermc | ||||
| 				print("download papermc") | ||||
| 				#papermc_downloader(inputSelectedObject, inputParams) | ||||
| 			case "exit": | ||||
| 				return | ||||
| 			case _: | ||||
| 				rich_print_error("Error: Command not found. Please try again. :(") | ||||
| 				rich_print_error("Use: 'help command' to get all available commands") | ||||
|  | ||||
| 		# return to break out of while loop | ||||
| 		if arguments_from_console: | ||||
| 			return None | ||||
|  | ||||
|  | ||||
| def get_input() -> None: | ||||
| 	""" | ||||
| 		Gets command line input and calls the handle input function | ||||
| 	""" | ||||
| 	input_command = None | ||||
| 	print("'STRG + C' to exit") | ||||
| 	while True: | ||||
| 		try: | ||||
| 			input_command, input_selected_object, *input_parameter = input("pluGET >> ").split() | ||||
|   | ||||
							
								
								
									
										161
									
								
								src/plugin/plugin_downloader.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								src/plugin/plugin_downloader.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,161 @@ | ||||
| """ | ||||
| File and functions which handle the download of the specific plugins | ||||
| """ | ||||
|  | ||||
| import re | ||||
| import urllib.request | ||||
| from urllib.error import HTTPError | ||||
| from pathlib import Path | ||||
|  | ||||
| import rich | ||||
|  | ||||
| from src.utils.utilities import rich_print_error, convert_file_size_down, remove_temp_plugin_folder, create_temp_plugin_folder | ||||
| from src.utils.utilities import api_do_request | ||||
| from src.handlers.handle_config import config_value | ||||
|  | ||||
|  | ||||
| def handle_regex_package_name(full_plugin_name) -> str: | ||||
| 	""" | ||||
| 	Return the plugin name after trimming clutter from name with regex operations | ||||
| 	""" | ||||
| 	# trims the part of the package that has for example "[1.1 Off]" in it | ||||
| 	unwanted_plugin_name = re.search(r'(^\[+[a-zA-Z0-9\s\W*\.*\-*\+*\%*\,]*\]+)', full_plugin_name) | ||||
| 	if bool(unwanted_plugin_name): | ||||
| 		unwanted_plugin_name_string = unwanted_plugin_name.group() | ||||
| 		full_plugin_name = full_plugin_name.replace(unwanted_plugin_name_string, '') | ||||
|  | ||||
| 	# gets the real plugin_name "word1 & word2" is not supported only gets word1 | ||||
| 	plugin_name = re.search(r'([a-zA-Z]\d*)+(\s?\-*\_*[a-zA-Z]\d*\+*\-*\'*)+', full_plugin_name) | ||||
| 	try: | ||||
| 		plugin_name_full_string = plugin_name.group() | ||||
| 		found_plugin_name = plugin_name_full_string.replace(' ', '') | ||||
| 	except AttributeError: | ||||
| 		found_plugin_name = unwanted_plugin_name_string | ||||
| 	return found_plugin_name | ||||
|  | ||||
|  | ||||
| def get_version_id(plugin_id, plugin_version) -> str: | ||||
| 	""" | ||||
| 	Returns the version id of the plugin | ||||
| 	""" | ||||
| 	if plugin_version == None or plugin_version == 'latest': | ||||
| 		url = f"https://api.spiget.org/v2/resources/{plugin_id}/versions/latest" | ||||
| 		response = api_do_request(url) | ||||
| 		version_id = response["id"] | ||||
| 		return version_id | ||||
|  | ||||
|  | ||||
| 	url = f"https://api.spiget.org/v2/resources/{plugin_id}/versions?size=100&sort=-name" | ||||
| 	version_list = api_do_request(url) | ||||
| 	for plugins in version_list: | ||||
| 		plugin_update = plugins["name"] | ||||
| 		version_id = plugins["id"] | ||||
| 	if plugin_update == plugin_version: | ||||
| 		return version_id | ||||
| 	return version_list[0]["id"] | ||||
|  | ||||
|  | ||||
| def getVersionName(plugin_id, plugin_version_id) -> str: | ||||
| 	""" | ||||
| 	Returns the name of a specific version | ||||
| 	""" | ||||
| 	url = f"https://api.spiget.org/v2/resources/{plugin_id}/versions/{plugin_version_id}" | ||||
| 	response = api_do_request(url) | ||||
| 	version_name = response["name"] | ||||
| 	return version_name | ||||
|  | ||||
|  | ||||
| def get_download_path() -> str: | ||||
| 	""" | ||||
| 	Reads the config and gets the path of the plugin folder | ||||
| 	""" | ||||
| 	config_values = config_value() | ||||
|  | ||||
| 	if config_values.connection == "local": | ||||
| 		if config_values.local_seperate_download_path is True: | ||||
| 			return config_values.local_path_to_seperate_download_path | ||||
| 		else: | ||||
| 			return config_values.path_to_plugin_folder | ||||
| 	 | ||||
| 	else: | ||||
| 		if config_values.remote_seperate_download_path is True: | ||||
| 			return config_values.remote_path_to_seperate_download_path | ||||
| 		else: | ||||
| 			return config_values.remote_plugin_folder_on_server | ||||
|  | ||||
|  | ||||
| def download_specific_plugin_version(plugin_id, download_path, version_id="latest") -> None: | ||||
| 	""" | ||||
| 	Download a specific plugin | ||||
| 	""" | ||||
| 	#config_values = config_value() | ||||
| 	if version_id != "latest" and version_id != None: | ||||
| 		#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("Reverting to latest version.") | ||||
|  | ||||
| 	#url = f"https://api.spiget.org/v2/resources/{plugin_id}/versions/latest/download" #throws 403 forbidden error...cloudflare :( | ||||
| 	url = f"https://api.spiget.org/v2/resources/{plugin_id}/download" | ||||
|  | ||||
| 	urrlib_opener = urllib.request.build_opener() | ||||
| 	urrlib_opener.addheaders = [('User-agent', 'pluGET/1.0')] | ||||
| 	urllib.request.install_opener(urrlib_opener) | ||||
|  | ||||
| 	remote_file = urllib.request.urlopen(url) | ||||
| 	try: | ||||
| 		file_size = int(remote_file.info()['Content-Length']) | ||||
| 	except TypeError: | ||||
| 		# if api won't return file size set it to 0 to avoid throwing an error | ||||
| 		file_size = 0 | ||||
| 	urllib.request.urlretrieve(url, download_path) | ||||
| 	print("		", end='') | ||||
| 	if file_size >= 1000000 and file_size != 0: | ||||
| 		file_size_data = convert_file_size_down(convert_file_size_down(file_size)) | ||||
| 		print("Downloaded " + (str(file_size_data)).rjust(9) + f" MB here {download_path}") | ||||
| 	elif file_size != 0: | ||||
| 		file_size_data = convert_file_size_down(file_size) | ||||
| 		print("Downloaded " + (str(file_size_data)).rjust(9) + f" KB here {download_path}") | ||||
| 	else: | ||||
| 		print(f"Downloaded         file here {download_path}") | ||||
| 	# TODO add sftp and ftp support | ||||
| 	#if config_values.connection == "sftp": | ||||
| 	#	sftp_session = createSFTPConnection() | ||||
| 	#	sftp_upload_file(sftp_session, download_path) | ||||
| 	#elif config_values.connection == "ftp": | ||||
| 	#	ftp_session = createFTPConnection() | ||||
| 	#	ftp_upload_file(ftp_session, download_path) | ||||
| 	return None | ||||
|  | ||||
|  | ||||
| def get_specific_plugin(plugin_id, plugin_version="latest") -> None: | ||||
| 	""" | ||||
| 	Gets the specific plugin and calls the download function | ||||
| 	""" | ||||
| 	config_values = config_value() | ||||
| 	# use a temporary folder to store plugins until they are uploaded | ||||
| 	if config_values.connection != "local": | ||||
| 		download_path = create_temp_plugin_folder() | ||||
| 	else: | ||||
| 		download_path = get_download_path() | ||||
|  | ||||
| 	url = f"https://api.spiget.org/v2/resources/{plugin_id}" | ||||
| 	plugin_details = api_do_request(url) | ||||
| 	try: | ||||
| 		plugin_name = plugin_details["name"] | ||||
| 	except KeyError: | ||||
| 		# exit if plugin id coudn't be found | ||||
| 		rich_print_error("Error: Plugin ID couldn't be found") | ||||
| 		return None | ||||
| 	plugin_name = handle_regex_package_name(plugin_name) | ||||
| 	plugin_version_id = get_version_id(plugin_id, plugin_version) | ||||
| 	plugin_version_name = getVersionName(plugin_id, plugin_version_id) | ||||
| 	plugin_download_name = f"{plugin_name}-{plugin_version_name}.jar" | ||||
| 	download_plugin_path = Path(f"{download_path}/{plugin_download_name}") | ||||
| 	# set the plugin_version_id to None if a specific version wasn't given as parameter | ||||
| 	if plugin_version == "latest" or plugin_version is None: | ||||
| 		plugin_version_id = None | ||||
| 	download_specific_plugin_version(plugin_id, download_plugin_path, plugin_version_id) | ||||
|  | ||||
| 	if config_values.connection != "local": | ||||
| 		remove_temp_plugin_folder() | ||||
| 	return None | ||||
| @@ -1,5 +1,5 @@ | ||||
| """ | ||||
| 	Holds all the utilitie code for pluGET and the webrequests function | ||||
| Holds all the utilitie code for pluGET and the webrequests function | ||||
| """ | ||||
|  | ||||
| import os | ||||
| @@ -12,7 +12,7 @@ from rich.console import Console | ||||
|  | ||||
| def api_do_request(url) -> list: | ||||
| 	""" | ||||
| 		Handles the webrequest and returns a json list | ||||
| 	Handles the webrequest and returns a json list | ||||
| 	""" | ||||
| 	webrequest_header = {'user-agent': 'pluGET/1.0'} | ||||
| 	try: | ||||
| @@ -26,7 +26,7 @@ def api_do_request(url) -> list: | ||||
|  | ||||
| def api_test_spiget() -> None: | ||||
| 	""" | ||||
| 		Test if the Spiget api sends a 200 status code back | ||||
| 	Test if the Spiget api sends a 200 status code back | ||||
| 	""" | ||||
| 	try: | ||||
| 		r = requests.get('https://api.spiget.org/v2/status') | ||||
| @@ -43,7 +43,7 @@ def api_test_spiget() -> None: | ||||
|  | ||||
| def rich_print_error(error_message) -> None: | ||||
| 	""" | ||||
| 		Prints a formatted error message from rich | ||||
| 	Prints a formatted error message from rich | ||||
| 	""" | ||||
| 	console = Console() | ||||
| 	console.print(error_message, style="bright_red") | ||||
| @@ -52,8 +52,8 @@ def rich_print_error(error_message) -> None: | ||||
|  | ||||
| def create_temp_plugin_folder() -> Path: | ||||
| 	""" | ||||
| 		Creates a temporary folder to store plugins inside | ||||
| 		Returns full path of temporary folder | ||||
| 	Creates a temporary folder to store plugins inside | ||||
| 	Returns full path of temporary folder | ||||
| 	""" | ||||
| 	path_temp_plugin_folder = Path("./TempSFTPFolder") | ||||
| 	if os.path.isdir(path_temp_plugin_folder): | ||||
| @@ -71,10 +71,19 @@ def create_temp_plugin_folder() -> Path: | ||||
|  | ||||
| def remove_temp_plugin_folder() -> None: | ||||
| 	""" | ||||
| 		Removes the temporary plugin folder and all content inside it | ||||
| 	Removes the temporary plugin folder and all content inside it | ||||
| 	""" | ||||
| 	try: | ||||
| 		shutil.rmtree(Path("./TempSFTPFolder")) | ||||
| 	except OSError as e: | ||||
| 		rich_print_error(f"Error: {e.filename} - {e.strerror}") | ||||
| 	return | ||||
|  | ||||
|  | ||||
| def convert_file_size_down(file_size) -> float: | ||||
| 	""" | ||||
| 	Convert the size of the number one down. E.g. MB -> KB through division with 1024 | ||||
| 	""" | ||||
| 	converted_file_size = (int(file_size)) / 1024 | ||||
| 	converted_file_size = round(converted_file_size, 2) | ||||
| 	return converted_file_size | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Neocky
					Neocky