Compare commits

...

70 Commits

Author SHA1 Message Date
Neocky
496334a2fa Fixed check with seperatedownloadpath issue
Changes:
- fixed issue with seperate downloadpath and checking
2021-06-22 00:08:57 +02:00
Neocky
42be836928 Fixed wrong folder was used when trying to download plugin
Changes:
- fixed wrong folder use while downloading plugins
- made code a little bit cleaner
2021-06-21 10:18:52 +02:00
Neocky
1e7b30a1be Changed output when checking and removed debug output
Changes:
-removed update available columm and integrated it with colors of the plugin name
- removed leftover debug output
2021-06-20 13:54:15 +02:00
Neocky
a4b1b7acf9 Added changelog to check help 2021-06-20 00:54:30 +02:00
Neocky
8344ed0afc Merge pull request #27 from Neocky/dev/v1.6.0
Merge Dev/v1.6.0
2021-06-20 00:42:17 +02:00
Neocky
2a416bbbc2 Added conformation for updateing and fixed serverjar issues
Changes:
- updated paper checker to 1.17
- added conformation when updating plugins
- added error handling
- added changlog as optional param for the check command
- fixed problems with paper updated
- updated help
- removed debug output
- removed unnecesary commnents
2021-06-20 00:36:36 +02:00
Neocky
456a0e185a Merged all and individual checking/updating of plugins
Changes:
- added fail check with api connection
- added localFileName to INSTALLEDPLUGINLIST
- merged checking/updating plugins
2021-06-19 18:01:05 +02:00
Neocky
f4361ad137 Fixed bug when plugin wasn't found with description 2021-06-19 13:47:12 +02:00
Neocky
41527926b2 Fixed TypeError while checking for updates & added update notes test
Changes:
- fixed TypeError when folder in plugin folder had .jar in name
- added update notes test to check all
2021-06-12 17:03:55 +02:00
Neocky
93818b90d7 Removed . in initial config for SFTP 2021-05-30 19:00:09 +02:00
Neocky
2712bd5be6 Added .jar validation to SFTP/FTP
Changes:
- added `.jar` file validation to SFTP/FTP
- cleanup of old code
2021-05-30 18:52:35 +02:00
Neocky
3ad7753674 Added skip when file is not .jar file
Changes:
- added skipping file if not .jar file
- removed some unneceessary config lookups
- updated regex
2021-05-29 20:42:02 +02:00
Neocky
38edfc73d6 Create FUNDING.yml 2021-05-29 01:12:30 +02:00
Neocky
a4636153c0 Added Inconsisten Version & Names topic 2021-05-29 00:38:56 +02:00
Neocky
764e8bcb81 Fixed JsonDecodeError & Better pluginnames
Changes:
- fixed JsonDecodeError when filename had many special characters in it
- fixed version & name wouldn't get detectet when plugin.yml file would have whitespaces in the beginning
- better output of plugin names when checking & updating
2021-05-28 23:52:16 +02:00
Neocky
26d7965422 Added installer.bat
Changes:
- added installer.bat file which automaticcally will install the needed python packages to run pluGET
2021-05-26 20:57:25 +02:00
Neocky
78f38f36cd Added installer.bat help
Changes:
- added installer.bat help
- changed formating of windows security message
2021-05-26 20:54:12 +02:00
Neocky
afbc3e8029 Merge pull request #18 from ZandercraftGames/main
Error Handling To Address Paper Check Crashes
2021-05-19 21:08:45 +02:00
Zander
a08aab7ae4 Made paperVersionBehind display "N/A" instead of "False" for more clarity. 2021-05-15 19:05:29 -04:00
Zander
b31cca5e31 Fix findLatestBuild check returning false on a successful API response. 2021-05-15 19:02:09 -04:00
Neocky
cd4a66002c Added new discord picture 2021-05-15 01:30:22 +02:00
Neocky
0d709cfb6f Fixed typo 2021-05-15 00:47:06 +02:00
Neocky
edc300a33d Eggcracking for better name finding & added better version digging
Added:
- eggcracking to get plugin name
- better version find mechanism
2021-05-15 00:46:29 +02:00
Zander
11b4fdcbeb Add error handling to "check serverjar" command on paper servers. Fixes use assignment issues when detection doesn't work. 2021-05-09 01:33:05 -04:00
Zander
716227eafa Add PyCharm configurations to .gitignore 2021-05-09 00:23:11 -04:00
Neocky
6e980a1580 Fixed typo & added part about security warning 2021-04-12 23:26:12 +02:00
Neocky
cb0282e676 Fixed array index out of range
Changes:
- fixed array index out of range error when checking/updating
2021-04-07 20:38:29 +02:00
Neocky
1dad1c62cd Removed typos 2021-04-03 20:36:33 +02:00
Neocky
91a5e84028 Added FTP to feature list 2021-04-03 20:33:58 +02:00
Neocky
60a41015e6 Merge pull request #16 from Neocky/dev/ftp
For Version 1.5.0
2021-03-31 18:19:39 +02:00
Neocky
706b8049c3 Added custom header to download & better ftp error messages
Changes:
- added custom header to plugin download
- added better sftp/ftp error messages
- removed unnecessary sftp/ftp functions
2021-03-31 18:11:41 +02:00
Neocky
927767b0aa Added FTP support
Changes:
- added ftp support
- added ftp to every function which had already sftp interaction
- edited config
- added handle_ftp.py
fixed old configcheck() bugs
- added sftp/ftp to eggcrackingjar mechanism
- added new line input with enter
2021-03-30 23:55:04 +02:00
Neocky
2a7372dae1 Added new start pluGET topic
Changes:
- added docs to launch pluGET on linux
2021-03-28 17:41:55 +02:00
Neocky
31a2a4aa89 Added full linux support & better output when searching
Changes:
- added launcher.sh file to launch pluGET on linux
- beautified output when searching for a ressource
- deleted .vscode folder & added it to the .gitignore list
2021-03-28 16:15:03 +02:00
Neocky
aceca0dec3 Merge pull request #14 from Neocky/dev/v1.3.2
Dev/v1.3.2
2021-03-27 19:02:21 +01:00
Neocky
205a13ee94 Optimized config handling & beautified output
Changes:
- optimized config handling
- added spinner to paper download
- changed progress bar colors
- better output for updating paper version
- misc code cleanup
2021-03-27 18:58:16 +01:00
Neocky
fddc0c252c Better config handling & better output for serverjar
Changes:
- better config handling
- better output for serverjar checking
2021-03-27 12:07:19 +01:00
Neocky
17611c741e Better output & first part of new config handling
Changes:
- better output when downloading files
- optimization when getting values from the config
2021-03-26 20:24:15 +01:00
Neocky
e8e46bb014 Changed command & misc 2021-03-24 23:06:27 +01:00
Neocky
5086b36aa3 Added gif 2021-03-23 18:45:14 +01:00
Neocky
2a481acbef Fixed formating issues
Changes:
- fixed some formating issues
2021-03-23 18:32:20 +01:00
Neocky
5b68181661 Added screenshots 2021-03-21 18:58:02 +01:00
Neocky
9b628498f1 Added new command/ examples & updated know problems 2021-03-21 18:19:44 +01:00
Neocky
d40ee52da1 Merge pull request #12 from Neocky/dev/eggcracking
Dev/eggcracking
2021-03-21 17:44:10 +01:00
Neocky
e66985054c Removed debug print & text formating
Changes:
- removed debug prints
- changed some text formating
2021-03-21 16:37:25 +01:00
Neocky
e1efcc4fc7 Added help for all commands & general better output
Changes:
- added help fo all/specific commands
- unified the output of check/update
- beautified the output of check/update
- a little code cleanup
2021-03-21 14:30:27 +01:00
Neocky
1147d4f29c Added better view counter 2021-03-19 19:16:02 +01:00
Neocky
ebb04085d3 Changed theme size 2021-03-19 19:03:42 +01:00
Neocky
e161d2c2f9 Added meme 2021-03-19 19:02:38 +01:00
Neocky
01465eb769 Added new progress bar and some formating
Changes:
- added simple progress bar when checking/updating plugins
- misc code cleanup
- changed logo
2021-03-18 23:42:02 +01:00
Neocky
d478432396 Added rich librarie 2021-03-18 18:46:19 +01:00
Neocky
d7fc68195b Added eggcracking method and first progress bar tests
Changes:
- added eggcracking method for plugins
- plugins will be unzipped when they don't have a version in their name and the version will be searched inside the `plugin.yml` file
- added progress bar tests
- changed default paths in config
2021-03-18 00:03:07 +01:00
Neocky
e87729f700 Merge pull request #9 from Neocky/dev/paper
Dev/paper to main
For new release
2021-03-16 21:50:49 +01:00
Neocky
01b9a52b40 Added server software parts and new usage parts 2021-03-16 21:45:37 +01:00
Neocky
76e1d7f5fd Fixed array was not created
Changes:
- fixed array would not be created for a plugin when plugin would throw a type- or valueerror
- deleted testing prints
- minor code cleanup
2021-03-16 21:10:09 +01:00
Neocky
430dbcd8d2 Finished paper support; Created independent paths
Changes:
- Created OS independent paths
- finished paper support
- created many catches for paper handling errors
2021-03-16 01:04:13 +01:00
Neocky
5e296e858f Added papermc support & fixing some issues
Changes:
- adding papermc support
- paper can be checked for an update
- can be updated to latest or specific version
- download specific paper version for different minecraft versions
2021-03-15 16:26:00 +01:00
Neocky
20261d110e Added catch for HTTPError and added papermc ground work
Changes:
- Added HTTPError catch when searching for a plugin
- Created first ground work for papermc server jar support
2021-03-15 01:20:18 +01:00
Neocky
932ae66827 Edited hit counter 2021-03-14 22:30:07 +01:00
Neocky
1e7de3ac5a FileNotFoundError will catch when using SFTP 2021-03-14 21:07:06 +01:00
Neocky
662f303935 Catched FileNotfoundError & Plugins updated will now display correctly
Changes:
- Catched file not found error
- Plugins updated
- Updated wrong index numbers when updating
2021-03-14 20:21:26 +01:00
Neocky
053a67e2d8 Update README.md 2021-03-14 19:38:47 +01:00
Neocky
e37840e665 Update README.md 2021-03-14 19:38:22 +01:00
Neocky
ac9b89de4f Edited license badge link 2021-03-14 19:15:06 +01:00
Neocky
f704b29ff9 Added latest release badge 2021-03-14 19:12:56 +01:00
Neocky
12f28107de Updated link 2021-03-14 18:55:39 +01:00
Neocky
b7e9673c80 Updated link 2021-03-14 18:51:43 +01:00
Neocky
0e4abad762 Update README.md 2021-03-14 18:02:09 +01:00
Neocky
972daf5687 Update README.md 2021-03-14 17:53:41 +01:00
Neocky
540a355d3d Added hit counter and removed star counter 2021-03-14 14:14:12 +01:00
21 changed files with 1345 additions and 366 deletions

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
# These are supported funding model platforms
custom: https://www.buymeacoffee.com/Neocky # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

6
.gitignore vendored
View File

@@ -127,3 +127,9 @@ dmypy.json
# Pyre type checker
.pyre/
# VSCode Settings
.vscode
# PyCharm Settings
.idea

View File

@@ -1,4 +0,0 @@
{
"python.linting.pylintEnabled": true,
"python.linting.enabled": true
}

200
README.md
View File

@@ -1,4 +1,5 @@
<p align="center">
<img src="https://i.ibb.co/JyCxnQn/logoreal.png" alt="pluGET" border="0"></a>
</p>
@@ -8,15 +9,35 @@
</p>
<p align="center">
<a href="https://github.com/Neocky/pluGET/blob/main/LICENSE"> <img src="https://img.shields.io/badge/license-Apache--2.0-blue" alt="Apache-2.0" border="0"></a>
<a href="https://github.com/Neocky/pluGET/stargazers"> <img src="https://img.shields.io/github/stars/Neocky/pluGET?color=yellow" alt="stars" border="0"></a>
<a href="https://github.com/Neocky/pluGET/blob/main/LICENSE"> <img src="https://img.shields.io/github/license/Neocky/pluGET" alt="Apache-2.0" border="0"></a>
<a href="https://github.com/Neocky/pluGET/releases"> <img src="https://img.shields.io/github/v/release/Neocky/pluGET?include_prereleases" alt"latestrelease"></a>
<a href="https://github.com/Neocky/pluGET/releases"> <img src="https://img.shields.io/github/downloads/Neocky/pluGET/total" alt="downloads" border="0"></a>
<a href="https://hits.seeyoufarm.com"><img src="https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2FNeocky%2FpluGET&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false"/></a>
</p>
# pluGET
A powerfull package manager which handles [Plugins](https://www.spigotmc.org/resources/) for minecraft servers.
# pluGET
#### A powerful package manager which updates [Plugins](https://www.spigotmc.org/resources/) and Server Software for minecraft servers.
<img src="https://www.bildhost.com/images/2021/03/23/pluGET.gif" alt="pluGET.gif" border="0" />
<details>
<summary>Screenshots</summary>
`check all` to check installed plugins for updates:
![screenshot1](https://i.ibb.co/QM7xh7w/pluget-checkall-small.png)
`check all` with more plugins:
![screenshot2](https://i.ibb.co/VmSNh6K/pluget-checkall.png)
`help command` list all available commands:
![screenshot3](https://i.ibb.co/9VZCjD6/pluget-help2.png)
</details>
<img src="https://i.ibb.co/82dnyrK/image.png" alt="meme" border="0" height="350" width="350"></a>
## Issues? Found a bug?
@@ -26,10 +47,11 @@ A powerfull package manager which handles [Plugins](https://www.spigotmc.org/res
## About
This is a package manager for minecraft [Spigot](https://www.spigotmc.org/) servers and its forks (e.g. [PaperMC](https://papermc.io/)).
This is a standalone program written in python.
The program works with a locally installed server or with a remote host through SFTP, when configured in the config.
The program works with a locally installed server or with a remote host through SFTP/FTP, when configured in the config.
It uses the [Spiget](https://spiget.org/) API to download and compare plugin versions and can download the latest version of plugins from the [Spigot](https://www.spigotmc.org/) site.
It can also compare and download the latest update of specific server software (e.g. [PaperMC](https://papermc.io/)).
Plugin management was the hard part of mangaging a minecraft server. The time it took to check the [Spigot ressource](https://www.spigotmc.org/resources/) page for updates for the installed plugins and updating all plugins manually which have available updates was too long and shocking.
Plugin management was the hard part of managing a minecraft server. The time it took to check the [Spigot ressource](https://www.spigotmc.org/resources/) page for updates for the installed plugins and updating all plugins manually which have available updates was too long and daunting.
So I built pluGET to automate and ease the plugin handling of a minecraft server and to turn the most time consuming part of managing a minecraft server to an easy one.
This program is suited for minecraft server owners who want to save time and stay on top of their plugin versions.
@@ -41,11 +63,17 @@ If you still have questions [here](https://github.com/Neocky/pluGET#need-help) i
So what can it do exactly?
pluGET can:
- work locally or through sftp
- download the latest version of a plugin
- update every installed/one specific plugin
- check for an update of every installed/one specific plugin
- remove a plugin from the plugin folder
- work locally or through SFTP/FTP
- manage plugins:
- download the latest version of a plugin
- update every installed/one specific plugin
- check for an update of every installed/one specific plugin
- remove a plugin from the plugin folder
- manage server software:
- download a specific server software version
- check installed server software for update
- update installed server software to a specific version
- supported server software: [PaperMc](https://papermc.io/)
There are more features in the work. Check [Projects](https://github.com/Neocky/pluGET/projects) for a complete list.
@@ -60,32 +88,73 @@ If you feel like showing your love and/or appreciation for this project then how
## Need help?
[<img src="https://i.imgur.com/D5vyVzC.png" alt="Discord" width="272"/>](https://discord.gg/475Uf4NBPF)
[<img src="https://i.ibb.co/CMKbT0L/rsz-1rsz-discord.png" alt="Discord" width="272"/>](https://discord.gg/475Uf4NBPF)
## Installation
### Python
### 1. Python
Python needs to be installed on your machine.
Get it [here](https://www.python.org/downloads/).
### Dependencies
### 2. Dependencies
Install the needed packages for this project.
Execute this command in the ```\plugGET``` folder:
#### Automatically (Windows only)
Execute the `installer.bat` file to automaticcally install the needed packages for this project.
> Sometimes the security warning `Windows protected your PC` comes when launching the `installer.bat` file.
> This is a normal behaviour from the windows defender because this is a unknown `.bat` file.
> To run the `installer.bat` anyway, click `More Info` and then `Run anyway` when the message pops up.
##### Manually
Execute this command in the `\plugGET` folder:
```python
pip install -r requirements.txt
py -m pip install -r requirements.txt
```
### Edit the Config
When run the first time, the `config.ini` file will be created in the root package folder and the program will close.
### 3. Edit the Config
When run the first time, the `config.ini` file will be created in the `\src` folder and the program will close.
Edit the config to your needs and relaunch pluGET.
**Now you are good to go!**
## Start pluGET
### Windows:
Execute the `launcher.bat` in the `\pluGET` folder.
This will launch pluGET correctly.
> Sometimes the security warning `Windows protected your PC` comes when launching the `launcher.bat` file.
> This is a normal behaviour from the windows defender because this is a unknown `.bat` file.
> To run the `launcher.bat` anyway, click `More Info` and then `Run anyway` when the message pops up.
### Linux:
Use `cd` to change into the `/pluGET` directory and change the permission of the `launcher.sh` to make it executeable:
```
$ chmod +x launcher.sh
```
Execute the `launcher.sh` file:
```
$ ./launcher.sh
```
> On both OS you can also launch the `src/__main__.py` file.
## Usage
Execute the `launcher.bat` in the `\pluGET` folder. This will launch pluGET correctly.
Another way is to launch the `src\__main__.py` file.
> As always, if you update plugins, shut down your server!
The following are examples of input for the general usage:
(Hint: 'all' can always be exchanged through the plugin name or the plugin id and reverse)
(Hint: [thingsInBrackets] are optional & 'all' can always be exchanged through the plugin name or the plugin id and reverse)
### General
#### Command help:
`help command [all/command]`
```
help command
```
<details>
<summary>Output</summary>
![Output](https://i.ibb.co/9VZCjD6/pluget-help2.png)
</details>
### Manage Plugins
#### Download the latest update of a specific package:
`get [pluginID/pluginName]`
```
@@ -95,15 +164,24 @@ or:
```
get 'pluginName'
```
#### Check all plugins/one specific plugin for updates:
`check [all/pluginName]`
#### Check all plugins/one specific plugin for updates with optional changelog output:
`check [all/pluginName] [changelog]`
```
check all
```
or:
```
check 'pluginName'
check 'pluginName' changelog
```
<details>
<summary>Output</summary>
![Output](https://i.ibb.co/VmSNh6K/pluget-checkall.png)
</details>
#### Update all plugins/one specific plugin:
`update [all/pluginName]`
```
@@ -137,37 +215,49 @@ exit .
```
help .
```
### Manage Server Software
#### Check installed server software for updates:
`check serverjar`
```
check serverjar
```
### Update installed server software to latest/specific version:
`update serverjar [Version]`
```
update serverjar 'PaperMCVersion'
```
### Download specific paper version:
`get-paper [paperBuild] [minecraftVersion]`
```
get-paper 550 1.16.5
```
or:
```
get-paper 321
```
## Known problems
### Can't get installed version
For example:
```
pluGET >> check all
Checking: all
Index | Name | Installed V. | Latest V. | Update available
[1] Vault N/A 1.7.3 False
```
This is a known issue because the filename in the `\plugin` folder doesn't include a version.
This is the plugin file in the `\plugin` folder right now: `Vault.jar`
How it should be: `Vault-1.7.3.jar`
Many plugins which get download from Spigot won't have a file version in the name.
#### How to solve:
Delete the `Vault.jar` file and download the newest version with the `get` command:
```
pluGET >> get vault
Index | Name | Description | Downloads
[1] Vault Vault is a Permissions, Chat, & Economy API to give plugins easy hooks into these systems. 989046
Select your wanted Ressource (Index)(0 to exit): 1
Downloadsize: 267.31 KB
File downloaded here: C:\Users\USER\Desktop\plugins\Vault-1.7.3.jar
```
Now you got the plugin with the correct name inside your `\plugin` folder: `Vault-1.7.3.jar`
And pluGET will tell you the installed version and check if an update is available when checking again:
```
pluGET >> check all
Checking: all
Index | Name | Installed V. | Latest V. | Update available
[1] Vault 1.7.3 1.7.3 False
```
### Can't get latest version/Update available
#### Inconsistent Names and Versions
For example:
![EssentialsX](https://i.ibb.co/fDyCYQ8/essentialsx.png)
EssentialsX is a prominent example of inconsisten version naming. The installed version is `2.18.2.0` but on [Spigot](https://www.spigotmc.org/resources/essentialsx.9089/update?update=371379) the version is only described as `2.18.2`.
That's the reason pluGET can't detect it automatically.
> There are of course many more plugins which have some sort of inconsistency which makes it sadly impossible for pluGET to detect them all. EssentialsX is used only as an example.
#### Solution
Download the plugins with the `get [pluginName]` command to make them detectable for pluGET.
After downloading EssentialsX with `get EssentialsX` and using `check all`:
![EssentialsX](https://i.ibb.co/ws5wHTj/essentialsx-2.png)
EssentialsX is now detected from pluGET and can update automatically when a new version comes out.
#### Bukkit plugins
For example:
![worldguard](https://i.ibb.co/7NJ9HRG/pluget-checkallonlyone.png)
As you can see the installed version was found but not the latest version for this plugin.
This is because this is a plugin which is not available on [Spigot](https://www.spigotmc.org/resources/).
pluGET supports currently only plugins from [Spigot](https://www.spigotmc.org/resources/).
In this example this is a bukkit plugin.

34
installer.bat Normal file
View File

@@ -0,0 +1,34 @@
@ECHO OFF
cd /d %~dp0
Echo ___ ___ ___ ___ ___ ___
Echo /\ \ /\__\ /\__\ /\ \ /\ \ /\ \
Echo /::\ \ /:/ / /:/ / /::\ \ /::\ \ \:\ \
Echo /:/\:\ \ /:/ / /:/ / /:/\:\ \ /:/\:\ \ \:\ \
Echo /::\~\:\ \ /:/ / /:/ / ___ /:/ \:\ \ /::\~\:\ \ /::\ \
Echo /:/\:\ \:\__\ /:/__/ /:/__/ /\__\ /:/__/_\:\__\ /:/\:\ \:\__\ /:/\:\__\
Echo \/__\:\/:/ / \:\ \ \:\ \ /:/ / \:\ /\ \/__/ \:\~\:\ \/__/ /:/ \/__/
Echo \::/ / \:\ \ \:\ /:/ / \:\ \:\__\ \:\ \:\__\ /:/ /
Echo \/__/ \:\ \ \:\/:/ / \:\/:/ / \:\ \/__/ \/__/
Echo \:\__\ \::/ / \::/ / \:\__\
Echo \/__/ \/__/ \/__/ \/__/
Echo `
Echo `
Echo ------------------------------------
Echo [By Neocky]
Echo https://github.com/Neocky/pluGET
Echo pluGET-Installer
Echo ------------------------------------
Echo `
Echo ----------------------------------------------------------------------------------
Echo Installing Python packages and dependencies...
py -m pip install -r requirements.txt
Echo `
Echo Launching pluGET...
launcher.bat
exit

2
launcher.sh Normal file
View File

@@ -0,0 +1,2 @@
cd src/
python3 "__main__.py"

View File

@@ -7,4 +7,8 @@ pynacl >= 1.4.0
cffi >= 1.14.5
six >= 1.15.0
pycparser >= 2.20
pysftp >= 0.2.9
pysftp >= 0.2.9
rich >= 9.13.0
commonmark >= 0.9.1
Pygments >= 2.8.1
typing_extensions >= 3.7.4.3

View File

@@ -1,10 +1,7 @@
from utils.consoleoutput import consoleTitle, clearConsole, printMainMenu, oColors
from utils.utilities import getHelp, check_requirements
from utils.consoleoutput import consoleTitle, clearConsole, printMainMenu
from utils.utilities import check_requirements
from handlers.handle_input import createInputLists, getInput
from handlers.handle_config import checkConfig
from plugin.plugin_downloader import searchPackage, getSpecificPackage
from plugin.plugin_updatechecker import updateInstalledPackage, checkInstalledPackage
from plugin.plugin_remover import removePlugin
def mainFunction():

View File

@@ -1,79 +1,87 @@
import os
import sys
import configparser
from pathlib import Path
from utils.consoleoutput import oColors
class configurationValues:
def __init__(self):
config = configparser.ConfigParser()
config.sections()
config.read("config.ini")
localPluginFolder = config['General']['UseLocalPluginFolder']
self.pathToPluginFolder = Path(config['Local - This Machine']['PathToPluginFolder'])
seperateDownloadPath = config['Local - This Machine']['SeperateDownloadPath']
self.pathToSeperateDownloadPath = Path(config['Local - This Machine']['PathToSeperateDownloadPath'])
self.sftp_server = config['SFTP - Remote Server']['Server']
self.sftp_user = config['SFTP - Remote Server']['Username']
self.sftp_password = config['SFTP - Remote Server']['Password']
sftp_port = config['SFTP - Remote Server']['SFTPPort']
self.sftp_folderPath = config['SFTP - Remote Server']['PluginFolderOnServer']
sftp_useSftp = config['SFTP - Remote Server']['USE_SFTP']
sftp_seperateDownloadPath = config['SFTP - Remote Server']['SeperateDownloadPath']
self.sftp_pathToSeperateDownloadPath = config['SFTP - Remote Server']['PathToSeperateDownloadPath']
self.sftp_port = int(sftp_port)
if localPluginFolder == 'True':
self.localPluginFolder = True
else:
self.localPluginFolder = False
if seperateDownloadPath == 'True':
self.seperateDownloadPath = True
else:
self.seperateDownloadPath = False
if sftp_seperateDownloadPath == 'True':
self.sftp_seperateDownloadPath = True
else:
self.sftp_seperateDownloadPath = False
if sftp_useSftp == 'True':
self.sftp_useSftp = True
else:
self.sftp_useSftp = False
def checkConfig():
currentFolder = os.getcwd()
os.chdir('..')
configAvailable = os.path.isfile("config.ini")
if not configAvailable:
createConfig()
print(oColors.brightRed + "Config created. Edit config before executing again!" + oColors.standardWhite)
input("Press any key + enter to exit...")
sys.exit()
class configValues:
config = configparser.ConfigParser()
config.sections()
config.read("config.ini")
localPluginFolder = config['General']['LocalPluginFolder']
pathToPluginFolder = config['General']['PathToPluginFolder']
seperateDownloadPath = config['General']['SeperateDownloadPath']
pathToSeperateDownloadPath = config['General']['PathToSeperateDownloadPath']
sftp_server = config['SFTP - Remote Server']['Server']
sftp_user = config['SFTP - Remote Server']['Username']
sftp_password = config['SFTP - Remote Server']['Password']
sftp_port = config['SFTP - Remote Server']['Port']
sftp_folderPath = config['SFTP - Remote Server']['PluginFolderOnServer']
sftp_seperateDownloadPath = config['SFTP - Remote Server']['SeperateDownloadPath']
sftp_pathToSeperateDownloadPath = config['SFTP - Remote Server']['PathToSeperateDownloadPath']
sftp_port = int(sftp_port)
if localPluginFolder == 'True':
localPluginFolder = True
else:
localPluginFolder = False
if seperateDownloadPath == 'True':
seperateDownloadPath = True
else:
seperateDownloadPath = False
if sftp_seperateDownloadPath == 'True':
sftp_seperateDownloadPath = True
else:
sftp_seperateDownloadPath = False
os.chdir(currentFolder)
return configValues
def createConfig():
config = configparser.ConfigParser(allow_no_value=True)
config['General'] = {}
config['General'][';'] = 'If a local plugin folder exists (True/False): (If False SFTP will be used)'
config['General']['LocalPluginFolder'] = 'True'
config['General']['PathToPluginFolder'] = 'C:\\Users\\USER\\Desktop\\plugins'
config['General'][';_'] = 'If you want a different folder to store the updated plugins change to (True/False) and the path below'
config['General']['SeperateDownloadPath'] = 'False'
config['General']['PathToSeperateDownloadPath'] = 'C:\\Users\\USER\\Desktop\\plugins'
config['General'][';'] = 'If a local plugin folder exists (True/False) (If False SFTP/FTP will be used):'
config['General']['UseLocalPluginFolder'] = 'True'
config['Local - This Machine'] = {}
config['Local - This Machine']['PathToPluginFolder'] = 'C:/Users/USER/Desktop/plugins'
config['Local - This Machine'][';'] = 'For a different folder to store the updated plugins change to (True/False) and the path below'
config['Local - This Machine']['SeperateDownloadPath'] = 'False'
config['Local - This Machine']['PathToSeperateDownloadPath'] = 'C:/Users/USER/Desktop/plugins'
config['SFTP - Remote Server'] = {}
config['SFTP - Remote Server']['Server'] = '0.0.0.0'
config['SFTP - Remote Server']['Username'] = 'user'
config['SFTP - Remote Server']['Password'] = 'password'
config['SFTP - Remote Server'][';'] = 'Normally you won*t need to change anything below this line'
config['SFTP - Remote Server']['Port'] = '22'
config['SFTP - Remote Server']['PluginFolderOnServer'] = '.\\plugins'
config['SFTP - Remote Server'][';_'] = 'If you want a different folder to store the updated plugins change to (True/False) and the path below'
config['SFTP - Remote Server'][';'] = 'If a different Port for SFTP needs to be used (Works only for SFTP)'
config['SFTP - Remote Server']['SFTPPort'] = '22'
config['SFTP - Remote Server'][';_'] = '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)'
config['SFTP - Remote Server']['PluginFolderOnServer'] = '/plugins'
config['SFTP - Remote Server'][';__'] = 'If you want to use FTP instead of SFTP change to (False) else use (True)'
config['SFTP - Remote Server']['USE_SFTP'] = 'True'
config['SFTP - Remote Server'][';___'] = 'For a different folder to store the updated plugins (Only with the update command!) change to (True/False) and the path below'
config['SFTP - Remote Server']['SeperateDownloadPath'] = 'False'
config['SFTP - Remote Server']['PathToSeperateDownloadPath'] = '.\\plugins'
config['SFTP - Remote Server']['PathToSeperateDownloadPath'] = '/plugins'
with open('./config.ini', 'w') as configfile:
with open('config.ini', 'w') as configfile:
config.write(configfile)

107
src/handlers/handle_ftp.py Normal file
View File

@@ -0,0 +1,107 @@
import os
import sys
import ftplib
import stat
import re
from utils.consoleoutput import oColors
from handlers.handle_config import configurationValues
def createFTPConnection():
configValues = configurationValues()
ftp = ftplib.FTP(configValues.sftp_server, user=configValues.sftp_user, \
passwd=configValues.sftp_password)
try:
return ftp
except UnboundLocalError:
print(oColors.brightRed + "[FTP]: Check your config.ini!" + oColors.standardWhite)
print(oColors.brightRed + "Exiting program..." + oColors.standardWhite)
sys.exit()
def ftp_showPlugins(ftp):
configValues = configurationValues()
ftp.cwd(configValues.sftp_folderPath)
for attr in ftp.dir():
print(attr.filename, attr)
def ftp_upload_file(ftp, itemPath):
configValues = configurationValues()
try:
ftp.cwd(configValues.sftp_folderPath)
itemPath = os.path.relpath(itemPath, 'TempSFTPFolder/')
itemPath = str(itemPath)
currentDirectory = os.getcwd()
os.chdir('TempSFTPFolder')
with open (itemPath, 'rb') as plugin_file:
ftp.storbinary('STOR '+ str(itemPath), plugin_file)
except FileNotFoundError:
print(oColors.brightRed + "[FTP]: The 'plugins' folder couldn*t be found on the remote host!" + oColors.standardWhite)
print(oColors.brightRed + "[FTP]: Aborting uploading." + oColors.standardWhite)
os.chdir(currentDirectory)
ftp.close()
def ftp_upload_server_jar(ftp, itemPath):
try:
print(f"itempath: {itemPath}")
ftp.cwd('.')
itemPath = os.path.relpath(itemPath, 'TempSFTPFolder/')
itemPath = str(itemPath)
currentDirectory = os.getcwd()
os.chdir('TempSFTPFolder')
with open (itemPath, 'rb') as server_jar:
ftp.storbinary('STOR '+ str(itemPath), server_jar)
except FileNotFoundError:
print(oColors.brightRed + "[FTP]: The 'root' folder couldn*t be found on the remote host!" + oColors.standardWhite)
print(oColors.brightRed + "[FTP]: Aborting uploading." + oColors.standardWhite)
os.chdir(currentDirectory)
ftp.close()
def ftp_listAll(ftp):
configValues = configurationValues()
try:
ftp.cwd(configValues.sftp_folderPath)
installedPlugins = ftp.nlst()
except FileNotFoundError:
print(oColors.brightRed + "[FTP]: The 'plugins' folder couldn*t be found on the remote host!" + oColors.standardWhite)
try:
return installedPlugins
except UnboundLocalError:
print(oColors.brightRed + "[FTP]: No plugins were found." + oColors.standardWhite)
def ftp_listFilesInServerRoot(ftp):
try:
ftp.cwd('.')
filesInServerRoot = ftp.nlst()
except FileNotFoundError:
print(oColors.brightRed + "[FTP]: The 'root' folder couldn*t be found on the remote host!" + oColors.standardWhite)
try:
return filesInServerRoot
except UnboundLocalError:
print(oColors.brightRed + "[FTP]: No Serverjar was found." + oColors.standardWhite)
def ftp_downloadFile(ftp, downloadPath, fileToDownload):
configValues = configurationValues()
ftp.cwd(configValues.sftp_folderPath)
filedata = open(downloadPath,'wb')
ftp.retrbinary('RETR '+fileToDownload, filedata.write)
filedata.close()
ftp.quit()
def ftp_validateFileAttributes(ftp, pluginPath):
pluginFTPAttribute = ftp.lstat(pluginPath)
if stat.S_ISDIR(pluginFTPAttribute.st_mode):
return False
elif re.search(r'.jar$', pluginPath):
return True
else:
return False

View File

@@ -1,11 +1,14 @@
import sys
from utils.consoleoutput import oColors
from utils.utilities import getHelp
from handlers.handle_config import checkConfig
from utils.utilities import getHelp, getCommandHelp
from handlers.handle_config import configurationValues
from plugin.plugin_downloader import searchPackage, getSpecificPackage
from plugin.plugin_updatechecker import updateInstalledPackage, checkInstalledPackage
from plugin.plugin_remover import removePlugin
from serverjar.serverjar_checker import checkInstalledServerjar, updateServerjar
from serverjar.serverjar_paper import papermc_downloader
def createInputLists():
global COMMANDLIST
@@ -16,7 +19,8 @@ def createInputLists():
'search',
'exit',
'help',
'remove'
'remove',
'get-paper'
]
global INPUTSELECTEDOBJECT
INPUTSELECTEDOBJECT = [
@@ -26,31 +30,38 @@ def createInputLists():
def handleInput(inputCommand, inputSelectedObject, inputParams):
configValues = configurationValues()
while True:
if inputCommand == 'get':
if inputSelectedObject.isdigit():
if not checkConfig().localPluginFolder:
if checkConfig().sftp_seperateDownloadPath is True:
pluginPath = checkConfig().sftp_pathToSeperateDownloadPath
if not configValues.localPluginFolder:
if configValues.sftp_seperateDownloadPath is True:
pluginPath = configValues.sftp_pathToSeperateDownloadPath
else:
pluginPath = checkConfig().sftp_folderPath
pluginPath = configValues.sftp_folderPath
getSpecificPackage(inputSelectedObject, pluginPath, inputParams)
break
else:
if checkConfig().seperateDownloadPath is True:
pluginPath = checkConfig().pathToSeperateDownloadPath
if configValues.seperateDownloadPath is True:
pluginPath = configValues.pathToSeperateDownloadPath
else:
pluginPath = checkConfig().pathToPluginFolder
pluginPath = configValues.pathToPluginFolder
getSpecificPackage(inputSelectedObject, pluginPath, inputParams)
break
else:
searchPackage(inputSelectedObject)
break
if inputCommand == 'update':
updateInstalledPackage(inputSelectedObject)
if inputSelectedObject == 'serverjar':
updateServerjar(inputParams)
else:
updateInstalledPackage(inputSelectedObject)
break
if inputCommand == 'check':
checkInstalledPackage(inputSelectedObject)
if inputSelectedObject == 'serverjar':
checkInstalledServerjar()
else:
checkInstalledPackage(inputSelectedObject, inputParams)
break
if inputCommand == 'search':
searchPackage(inputSelectedObject)
@@ -58,24 +69,37 @@ def handleInput(inputCommand, inputSelectedObject, inputParams):
if inputCommand == 'exit':
sys.exit()
if inputCommand == 'help':
getHelp()
if inputSelectedObject == 'command' or inputSelectedObject == 'commands':
getCommandHelp(inputParams)
else:
getHelp()
break
if inputCommand == 'remove':
removePlugin(inputSelectedObject)
break
if inputCommand == 'get-paper':
papermc_downloader(inputSelectedObject, inputParams)
break
else:
print(oColors.brightRed + "Command not found. Please try again." + oColors.standardWhite)
print(oColors.brightRed + "Error: Command not found. Please try again. :(" + oColors.standardWhite)
print(oColors.brightRed + "Use: '" + oColors.standardWhite +"help command" + oColors.brightRed +"' to get all available commands" + oColors.standardWhite)
getInput()
getInput()
def getInput():
inputCommand = None
while True:
try:
inputCommand, inputSelectedObject, *inputParams = input("pluGET >> ").split()
break
except ValueError:
print(oColors.brightRed + "Wrong input! Use: > *command* *selectedObject* *optionalParams*" + oColors.standardWhite)
if inputCommand == None:
continue
else:
print(oColors.brightRed + "Wrong input! Use: > 'command' 'selectedObject' [optionalParams]" + oColors.standardWhite)
print(oColors.brightRed + "Use: '" + oColors.standardWhite +"help command" + oColors.brightRed +"' to get all available commands" + oColors.standardWhite)
except KeyboardInterrupt:
sys.exit()
inputParams = inputParams[0] if inputParams else None
handleInput(inputCommand, inputSelectedObject, inputParams)

View File

@@ -1,17 +1,21 @@
import sys
import os
import pysftp
import paramiko
import stat
import re
from utils.consoleoutput import oColors
from handlers.handle_config import checkConfig
from handlers.handle_config import configurationValues
def createSFTPConnection():
configValues = configurationValues()
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None # TODO fix this
try:
sftp = pysftp.Connection(checkConfig().sftp_server, username=checkConfig().sftp_user, \
password=checkConfig().sftp_password, port=checkConfig().sftp_port, cnopts=cnopts)
sftp = pysftp.Connection(configValues.sftp_server, username=configValues.sftp_user, \
password=configValues.sftp_password, port=configValues.sftp_port, cnopts=cnopts)
except paramiko.ssh_exception.AuthenticationException:
print(oColors.brightRed + "[SFTP]: Wrong Username/Password" + oColors.standardWhite)
except paramiko.ssh_exception.SSHException:
@@ -25,35 +29,75 @@ def createSFTPConnection():
def sftp_showPlugins(sftp):
sftp.cd('plugins')
configValues = configurationValues()
sftp.cd(configValues.sftp_folderPath)
for attr in sftp.listdir_attr():
print(attr.filename, attr)
def sftp_cdPluginDir(sftp):
sftp.cd('plugins')
def sftp_upload_file(sftp, itemPath):
configValues = configurationValues()
try:
sftp.chdir('plugins')
sftp.chdir(configValues.sftp_folderPath)
sftp.put(itemPath)
except FileNotFoundError:
print(oColors.brightRed + "The 'plugins' folder couldn*t be found on the remote host!" + oColors.standardWhite)
print(oColors.brightRed + "Aborting installation." + oColors.standardWhite)
print(oColors.brightRed + "[SFTP]: The 'plugins' folder couldn*t be found on the remote host!" + oColors.standardWhite)
print(oColors.brightRed + "[SFTP]: Aborting uploading." + oColors.standardWhite)
sftp.close()
def sftp_upload_server_jar(sftp, itemPath):
try:
sftp.chdir('.')
sftp.put(itemPath)
except FileNotFoundError:
print(oColors.brightRed + "[SFTP]: The 'root' folder couldn*t be found on the remote host!" + oColors.standardWhite)
print(oColors.brightRed + "[SFTP]: Aborting uploading." + oColors.standardWhite)
sftp.close()
def sftp_listAll(sftp):
configValues = configurationValues()
try:
sftp.chdir('plugins')
sftp.chdir(configValues.sftp_folderPath)
installedPlugins = sftp.listdir()
except FileNotFoundError:
print(oColors.brightRed + "The 'plugins' folder couldn*t be found on the remote host!" + oColors.standardWhite)
print(oColors.brightRed + "[SFTP]: The 'plugins' folder couldn*t be found on the remote host!" + oColors.standardWhite)
try:
return installedPlugins
except UnboundLocalError:
print(oColors.brightRed + "No plugins were found." + oColors.standardWhite)
print(oColors.brightRed + "[SFTP]: No plugins were found." + oColors.standardWhite)
def sftp_listFilesInServerRoot(sftp):
try:
filesInServerRoot = sftp.listdir()
except FileNotFoundError:
print(oColors.brightRed + "[SFTP]: The 'root' folder couldn*t be found on the remote host!" + oColors.standardWhite)
try:
return filesInServerRoot
except UnboundLocalError:
print(oColors.brightRed + "[SFTP]: No Serverjar was found." + oColors.standardWhite)
def sftp_downloadFile(sftp, downloadPath, fileToDownload):
configValues = configurationValues()
sftp.cwd(configValues.sftp_folderPath)
currentDirectory = os.getcwd()
os.chdir('TempSFTPFolder')
sftp.get(fileToDownload)
sftp.close()
os.chdir(currentDirectory)
def sftp_validateFileAttributes(sftp, pluginPath):
pluginSFTPAttribute = sftp.lstat(pluginPath)
if stat.S_ISDIR(pluginSFTPAttribute.st_mode):
return False
elif re.search(r'.jar$', pluginPath):
return True
else:
return False

View File

@@ -1,19 +1,14 @@
import re
import urllib.request
from urllib.error import HTTPError
from pathlib import Path
from utils.consoleoutput import oColors
from utils.web_request import doAPIRequest
from utils.utilities import createTempPluginFolder, deleteTempPluginFolder
from handlers.handle_config import checkConfig
from handlers.handle_sftp import sftp_upload_file, sftp_cdPluginDir, createSFTPConnection
def calculateFileSize(downloadFileSize):
fileSizeDownload = int(downloadFileSize)
fileSizeKb = fileSizeDownload / 1024
roundedFileSize = round(fileSizeKb, 2)
return roundedFileSize
from utils.utilities import createTempPluginFolder, deleteTempPluginFolder, calculateFileSizeKb, calculateFileSizeMb
from handlers.handle_config import configurationValues
from handlers.handle_sftp import sftp_upload_file, createSFTPConnection
from handlers.handle_ftp import ftp_upload_file, createFTPConnection
def handleRegexPackageName(packageNameFull):
@@ -57,33 +52,49 @@ def getVersionName(packageId, versionId):
def searchPackage(ressourceName):
configValues = configurationValues()
url = f"https://api.spiget.org/v2/search/resources/{ressourceName}?field=name&sort=-downloads"
packageName = doAPIRequest(url)
i = 1
print(f"Searching: {ressourceName}")
print("Index | Name | Description | Downloads")
print(oColors.brightBlack + f"Searching: {ressourceName}" + oColors.standardWhite)
print("┌─────┬─────────────────────────────┬───────────┬──────────────────────────────────────────────────────────────────────┐")
print("│ No. │ Name │ Downloads │ Description │")
print("└─────┴─────────────────────────────┴───────────┴──────────────────────────────────────────────────────────────────────┘")
for ressource in packageName:
pName = ressource["name"]
newName = handleRegexPackageName(pName)
pTag = ressource["tag"]
pDownloads = ressource["downloads"]
print(f" [{i}]".ljust(8), end='')
print(f" [{i}]".rjust(6), end='')
print(" ", end='')
print(f"{newName}".ljust(30), end='')
print(f"{pTag}".ljust(120), end='')
print(f"{pDownloads}".ljust(7))
print(f"{pDownloads}".rjust(9), end='')
print(" ", end='')
print(f"{pTag}".ljust(120))
i = i + 1
ressourceSelected = int(input("Select your wanted Ressource (Index)(0 to exit): "))
ressourceSelected = int(input("Select your wanted Ressource (No.)(0 to exit): "))
if ressourceSelected != 0:
ressourceSelected = ressourceSelected - 1
ressourceId = packageName[ressourceSelected]["id"]
if not checkConfig().localPluginFolder:
getSpecificPackage(ressourceId, checkConfig().sftp_folderPath)
if not configValues.localPluginFolder:
if configValues.sftp_seperateDownloadPath is True:
pluginDownloadPath = configValues.sftp_pathToSeperateDownloadPath
else:
pluginDownloadPath = configValues.sftp_folderPath
else:
getSpecificPackage(ressourceId, checkConfig().pathToPluginFolder)
if configValues.seperateDownloadPath is True:
pluginDownloadPath = configValues.pathToSeperateDownloadPath
else:
pluginDownloadPath = configValues.pathToPluginFolder
try:
getSpecificPackage(ressourceId, pluginDownloadPath)
except HTTPError as err:
print(oColors.brightRed + f"Error: {err.code} - {err.reason}" + oColors.standardWhite)
def downloadSpecificVersion(ressourceId, downloadPath, versionID='latest'):
configValues = configurationValues()
if versionID != 'latest':
#url = f"https://spigotmc.org/resources/{ressourceId}/download?version={versionID}"
print(oColors.brightRed + "Sorry but specific version downloads aren't supported because of cloudflare protection. :(" + oColors.standardWhite)
@@ -92,19 +103,33 @@ def downloadSpecificVersion(ressourceId, downloadPath, versionID='latest'):
url = f"https://api.spiget.org/v2/resources/{ressourceId}/download"
#url = f"https://api.spiget.org/v2/resources/{ressourceId}/versions/latest/download" #throws 403 forbidden error...cloudflare :(
urrlib_opener = urllib.request.build_opener()
urrlib_opener.addheaders = [('User-agent', 'pluGET/1.0')]
urllib.request.install_opener(urrlib_opener)
remotefile = urllib.request.urlopen(url)
filesize = remotefile.info()['Content-Length']
urllib.request.urlretrieve(url, downloadPath)
filesizeData = calculateFileSize(filesize)
print(f"Downloadsize: {filesizeData} KB")
print(f"File downloaded here: {downloadPath}")
if not checkConfig().localPluginFolder:
sftpSession = createSFTPConnection()
sftp_upload_file(sftpSession, downloadPath)
filesize = int(filesize)
print(" ", end='')
if filesize >= 1000000:
filesizeData = calculateFileSizeMb(filesize)
print("Downloaded " + (str(filesizeData)).rjust(9) + f" MB here {downloadPath}")
else:
filesizeData = calculateFileSizeKb(filesize)
print("Downloaded " + (str(filesizeData)).rjust(9) + f" KB here {downloadPath}")
if not configValues.localPluginFolder:
if configValues.sftp_useSftp:
sftpSession = createSFTPConnection()
sftp_upload_file(sftpSession, downloadPath)
else:
ftpSession = createFTPConnection()
ftp_upload_file(ftpSession, downloadPath)
def getSpecificPackage(ressourceId, downloadPath, inputPackageVersion='latest'):
if checkConfig().localPluginFolder == False:
configValues = configurationValues()
if configValues.localPluginFolder == False:
downloadPath = createTempPluginFolder()
url = f"https://api.spiget.org/v2/resources/{ressourceId}"
packageDetails = doAPIRequest(url)
@@ -113,30 +138,11 @@ def getSpecificPackage(ressourceId, downloadPath, inputPackageVersion='latest'):
versionId = getVersionID(ressourceId, inputPackageVersion)
packageVersion = getVersionName(ressourceId, versionId)
packageDownloadName = f"{packageNameNew}-{packageVersion}.jar"
downloadPackagePath = f"{downloadPath}\\{packageDownloadName}"
if checkConfig().localPluginFolder:
if inputPackageVersion is None or inputPackageVersion == 'latest':
try:
downloadSpecificVersion(ressourceId=ressourceId, downloadPath=downloadPackagePath)
except HTTPError as err:
print(oColors.brightRed + f"Error: {err.code} - {err.reason}" + oColors.standardWhite)
else:
try:
downloadSpecificVersion(ressourceId, downloadPackagePath, versionId)
except HTTPError as err:
print(oColors.brightRed + f"Error: {err.code} - {err.reason}" + oColors.standardWhite)
if not checkConfig().localPluginFolder:
if inputPackageVersion is None or inputPackageVersion == 'latest':
try:
downloadSpecificVersion(ressourceId=ressourceId, downloadPath=downloadPackagePath)
deleteTempPluginFolder(downloadPath)
except HTTPError as err:
print(oColors.brightRed + f"Error: {err.code} - {err.reason}" + oColors.standardWhite)
else:
try:
downloadSpecificVersion(ressourceId, downloadPackagePath, versionId)
deleteTempPluginFolder(downloadPath)
except HTTPError as err:
print(oColors.brightRed + f"Error: {err.code} - {err.reason}" + oColors.standardWhite)
downloadPackagePath = Path(f"{downloadPath}/{packageDownloadName}")
if inputPackageVersion is None or inputPackageVersion == 'latest':
downloadSpecificVersion(ressourceId=ressourceId, downloadPath=downloadPackagePath)
else:
downloadSpecificVersion(ressourceId, downloadPackagePath, versionId)
if not configValues.localPluginFolder:
deleteTempPluginFolder(downloadPath)

View File

@@ -1,19 +1,26 @@
import os
import re
from pathlib import Path
from utils.consoleoutput import oColors
from handlers.handle_config import checkConfig
from handlers.handle_config import configurationValues
from handlers.handle_sftp import createSFTPConnection, sftp_listAll
from handlers.handle_ftp import createFTPConnection, ftp_listAll
from plugin.plugin_updatechecker import getFileName, getFileVersion, getInstalledPlugin, createPluginList
def removePlugin(pluginToRemove):
configValues = configurationValues()
createPluginList()
if not checkConfig().localPluginFolder:
sftp = createSFTPConnection()
pluginList = sftp_listAll(sftp)
if not configValues.localPluginFolder:
if not configValues.sftp_useSftp:
ftp = createFTPConnection()
pluginList = ftp_listAll(ftp)
else:
sftp = createSFTPConnection()
pluginList = sftp_listAll(sftp)
else:
pluginList = os.listdir(checkConfig().pathToPluginFolder)
pluginList = os.listdir(configValues.pathToPluginFolder)
i = 0
try:
for plugin in pluginList:
@@ -27,17 +34,21 @@ def removePlugin(pluginToRemove):
if pluginToRemove == pluginIdStr or re.search(pluginToRemove, fileName, re.IGNORECASE):
print(f"Removing: {fileName}")
if not checkConfig().localPluginFolder:
pluginPath = checkConfig().sftp_folderPath
pluginPath = f"{pluginPath}\\{plugin}"
sftp = createSFTPConnection()
sftp.remove(pluginPath)
if not configValues.localPluginFolder:
pluginPath = configValues.sftp_folderPath
pluginPath = f"{pluginPath}/{plugin}"
if not configValues.sftp_useSftp:
ftp = createFTPConnection()
ftp.delete(pluginPath)
else:
sftp = createSFTPConnection()
sftp.remove(pluginPath)
print(f"Removed: {fileName}")
i += 1
break
else:
pluginPath = checkConfig().pathToPluginFolder
pluginPath = f"{pluginPath}\\{plugin}"
pluginPath = configValues.pathToPluginFolder
pluginPath = Path(f"{pluginPath}/{plugin}")
os.remove(pluginPath)
print(f"Removed: {fileName}")
i += 1

View File

@@ -1,11 +1,19 @@
import os
import re
import io
import base64
from zipfile import ZipFile
from urllib.error import HTTPError
from pathlib import Path
from rich.progress import track
from utils.consoleoutput import oColors
from utils.web_request import doAPIRequest
from handlers.handle_config import checkConfig
from handlers.handle_sftp import createSFTPConnection, sftp_listAll
from handlers.handle_config import configurationValues
from handlers.handle_sftp import createSFTPConnection, sftp_listAll, sftp_downloadFile, sftp_validateFileAttributes
from handlers.handle_ftp import createFTPConnection, ftp_listAll, ftp_downloadFile, ftp_validateFileAttributes
from plugin.plugin_downloader import getSpecificPackage
from utils.utilities import createTempPluginFolder, deleteTempPluginFolder
def createPluginList():
@@ -14,8 +22,8 @@ def createPluginList():
return INSTALLEDPLUGINLIST
def addToPluginList(pluginId, versionId, plugin_latest_version, plugin_is_outdated):
INSTALLEDPLUGINLIST.append([pluginId, versionId, plugin_latest_version, plugin_is_outdated])
def addToPluginList(localFileName, pluginId, versionId, plugin_latest_version, plugin_is_outdated):
INSTALLEDPLUGINLIST.append([localFileName, pluginId, versionId, plugin_latest_version, plugin_is_outdated])
def getFileName(pluginName):
@@ -36,6 +44,10 @@ def getFileVersion(pluginName):
pluginVersion = re.search(r'([\d.]+[.jar]+)', pluginNameFull)
pluginVersionFull = pluginVersion.group()
pluginVersionString = pluginVersionFull.replace('.jar', '')
if pluginVersionString.endswith('.'):
pluginVersionString = ''
if pluginVersionString == '':
pluginVersionString = eggCrackingJar(pluginNameFull, 'version')
return pluginVersionString
@@ -46,6 +58,23 @@ def getLatestPluginVersion(pluginId):
return versionLatestUpdate
def getUpdateDescription(pluginId):
url = f"https://api.spiget.org/v2/resources/{pluginId}/updates?size=1&sort=-date"
latestDescriptionSearch = doAPIRequest(url)
versionLatestDescription = latestDescriptionSearch[0]["description"]
versionLatestDescription = base64.b64decode(versionLatestDescription)
versionLatestDescriptionText =versionLatestDescription.decode('utf-8')
htmlRegex = re.compile('<.*?>')
versionLatestDescriptionText = re.sub(htmlRegex, '', versionLatestDescriptionText)
linesChangelogDescription = versionLatestDescriptionText.split("\n")
nonEmptyLines = [line for line in linesChangelogDescription if line.strip() != ""]
stringnonEmptyLines = ""
for line in nonEmptyLines:
stringnonEmptyLines += line + "\n"
stringnonEmptyLines = stringnonEmptyLines[:-1]
return stringnonEmptyLines
def compareVersions(plugin_latest_version, pluginVersion):
if pluginVersion < plugin_latest_version:
plugin_is_outdated = True
@@ -54,40 +83,112 @@ def compareVersions(plugin_latest_version, pluginVersion):
return plugin_is_outdated
def checkInstalledPackage(inputSelectedObject="all"):
createPluginList()
if not checkConfig().localPluginFolder:
sftp = createSFTPConnection()
pluginList = sftp_listAll(sftp)
def eggCrackingJar(localJarFileName, searchMode):
configValues = configurationValues()
if not configValues.localPluginFolder:
if configValues.sftp_useSftp:
tempPluginFolderPath = createTempPluginFolder()
sftp = createSFTPConnection()
pathToPluginJar = Path(f"{tempPluginFolderPath}/{localJarFileName}")
sftp_downloadFile(sftp, pathToPluginJar, localJarFileName)
else:
tempPluginFolderPath = createTempPluginFolder()
ftp = createFTPConnection()
pathToPluginJar = Path(f"{tempPluginFolderPath}/{localJarFileName}")
ftp_downloadFile(ftp, pathToPluginJar, localJarFileName)
else:
pluginList = os.listdir(checkConfig().pathToPluginFolder)
pluginPath = configValues.pathToPluginFolder
pathToPluginJar = Path(f"{pluginPath}/{localJarFileName}")
pluginVersion = ''
pluginName = ''
with ZipFile(pathToPluginJar, 'r') as pluginJar:
try:
with io.TextIOWrapper(pluginJar.open('plugin.yml', 'r'), encoding="utf-8") as pluginYml:
pluginYmlContentLine = pluginYml.readlines()
for line in pluginYmlContentLine:
if searchMode == 'version':
if re.match(r'^\s*?version: ', line):
pluginVersion = re.sub(r'^\s*?version: ', '', line)
pluginVersion = pluginVersion.replace('\n', '')
pluginVersion = pluginVersion.replace("'", '')
pluginVersion = pluginVersion.replace('"', '')
elif searchMode == 'name':
if re.match(r'^\s*?name: ', line):
pluginName = re.sub(r'^\s*?name: ', '', line)
pluginName = pluginName.replace('\n', '')
pluginName = pluginName.replace("'", '')
pluginName = pluginName.replace('"', '')
except FileNotFoundError:
pluginVersion = ''
pluginName = ''
if not configValues.localPluginFolder:
deleteTempPluginFolder(tempPluginFolderPath)
if searchMode == 'version':
return pluginVersion
if searchMode == 'name':
return pluginName
def checkInstalledPackage(inputSelectedObject="all", inputOptionalParam=None):
configValues = configurationValues()
createPluginList()
pluginFolderPath = configValues.pathToPluginFolder
if not configValues.localPluginFolder:
if configValues.sftp_useSftp:
connection = createSFTPConnection()
pluginList = sftp_listAll(connection)
else:
connection = createFTPConnection()
pluginList = ftp_listAll(connection)
else:
pluginList = os.listdir(pluginFolderPath)
i = 0
oldPackages = 0
print(f"Checking: {inputSelectedObject}")
print("Index | Name | Installed V. | Latest V. | Update available")
oldPlugins = 0
print(oColors.brightBlack + f"Checking: {inputSelectedObject}" + oColors.standardWhite)
if inputOptionalParam != "changelog":
print(oColors.brightBlack + f"Use 'check {inputSelectedObject} changelog' to get the latest changelog from plugins" + oColors.standardWhite)
print("┌─────┬────────────────────────────────┬──────────────┬──────────────┐")
print("│ No. │ Name │ Installed V. │ Latest V. │")
print("└─────┴────────────────────────────────┴──────────────┴──────────────┘")
try:
for plugin in pluginList:
for plugin in track(pluginList, description="Checking for updates" ,transient=True, complete_style="bright_yellow"):
if not configValues.localPluginFolder:
pluginFile = f"{configValues.sftp_folderPath}/{plugin}"
if configValues.sftp_useSftp:
pluginAttributes = sftp_validateFileAttributes(connection, pluginFile)
if pluginAttributes == False:
continue
else:
pluginAttributes = ftp_validateFileAttributes(connection, pluginFile)
if pluginAttributes == False:
continue
else:
if not os.path.isfile(Path(f"{pluginFolderPath}/{plugin}")):
continue
if not re.search(r'.jar$', plugin):
continue
try:
fileName = getFileName(plugin)
fileVersion = getFileVersion(plugin)
pluginId = getInstalledPlugin(fileName, fileVersion)
pluginId = getInstalledPlugin(fileName, fileVersion, plugin)
except TypeError:
continue
pluginIdStr = str(pluginId)
pluginIdStr = str(pluginId)
if fileVersion == '':
fileVersion = 'N/A'
try:
pluginLatestVersion = INSTALLEDPLUGINLIST[i][2]
pluginLatestVersion = INSTALLEDPLUGINLIST[i][3]
except IndexError:
pluginLatestVersion = 'N/A'
if pluginLatestVersion == None:
pluginLatestVersion = 'N/A'
try:
pluginIsOutdated = INSTALLEDPLUGINLIST[i][3]
pluginIsOutdated = INSTALLEDPLUGINLIST[i][4]
except IndexError:
pluginIsOutdated = 'N/A'
@@ -95,163 +196,271 @@ def checkInstalledPackage(inputSelectedObject="all"):
pluginIsOutdated = 'N/A'
if pluginIsOutdated == True:
oldPackages = oldPackages + 1
oldPlugins = oldPlugins + 1
if inputSelectedObject != "*" and inputSelectedObject != "all":
if re.search(r'.jar$', fileName):
fileName = eggCrackingJar(plugin, "name")
if inputSelectedObject != "all" and inputSelectedObject != "*":
if inputSelectedObject != pluginIdStr or not re.search(inputSelectedObject, fileName, re.IGNORECASE):
i += 1
continue
if inputSelectedObject == "all" or inputSelectedObject != "*" or inputSelectedObject != "all":
if inputSelectedObject == pluginIdStr or re.search(inputSelectedObject, fileName, re.IGNORECASE):
print(f" [{1}]".ljust(8), end='')
if pluginLatestVersion == 'N/A':
print(oColors.brightBlack + f" [{1}]".rjust(6), end='')
else:
print(f" [{1}]".rjust(6), end='')
else:
if pluginLatestVersion == 'N/A':
print(oColors.brightBlack + f" [{i+1}]".rjust(6), end='')
else:
print(f" [{i+1}]".rjust(6), end='')
print(" ", end='')
if pluginIsOutdated == True:
print(oColors.brightGreen + f"{fileName}".ljust(33) + oColors.standardWhite, end='')
elif pluginIsOutdated == False:
print(oColors.brightRed + f"{fileName}".ljust(33) + oColors.standardWhite, end='')
else:
print(f"{fileName}".ljust(33), end='')
print(f"{fileVersion}".ljust(15), end='')
print(f"{pluginLatestVersion}".ljust(12), end='')
print(f" {pluginIsOutdated}".ljust(5))
print(f"{fileVersion}".ljust(15), end='')
print(f"{pluginLatestVersion}".ljust(15))
if (inputOptionalParam == "changelog" and pluginLatestVersion != 'N/A'):
print(oColors.brightYellow + f"CHANGELOG {fileName}:" + oColors.standardWhite)
description = getUpdateDescription(pluginId)
print(description)
print()
if inputSelectedObject == pluginIdStr or re.search(inputSelectedObject, fileName, re.IGNORECASE):
break
else:
print(f" [{i+1}]".ljust(8), end='')
print(f"{fileName}".ljust(33), end='')
print(f"{fileVersion}".ljust(15), end='')
print(f"{pluginLatestVersion}".ljust(12), end='')
print(f" {pluginIsOutdated}".ljust(5))
print(oColors.brightRed + "Wrong input! Use 'check all' to check every plugin for updates!" + oColors.standardWhite)
break
i = i + 1
i += 1
except TypeError:
print(oColors.brightRed + "Aborted checking for plugins." + oColors.standardWhite)
print(oColors.brightYellow + f"Old packages: [{oldPackages}/{i}]" + oColors.standardWhite)
print(oColors.brightRed + "Error occured: Aborted checking for updates." + oColors.standardWhite)
print(oColors.brightYellow + f"Outdated plugins: [{oldPlugins}/{i}]" + oColors.standardWhite)
def updateInstalledPackage(inputSelectedObject='all'):
createPluginList()
if not checkConfig().localPluginFolder:
sftp = createSFTPConnection()
pluginList = sftp_listAll(sftp)
else:
pluginList = os.listdir(checkConfig().pathToPluginFolder)
configValues = configurationValues()
if not configValues.localPluginFolder:
if configValues.sftp_useSftp:
connection = createSFTPConnection()
else:
connection = createFTPConnection()
try:
print(oColors.brightBlack + "Selected plugins with available Updates:" + oColors.standardWhite)
if inputSelectedObject == "all" or inputSelectedObject == "*":
for pluginIndex in range(len(INSTALLEDPLUGINLIST)):
if INSTALLEDPLUGINLIST[pluginIndex][4] == True:
fileName = getFileName(INSTALLEDPLUGINLIST[pluginIndex][0])
print(fileName, end=' ')
else:
print(inputSelectedObject, end=' ')
print()
updateConfirmation = input("Update these plugins [y/n] ? ")
if updateConfirmation != "y":
print(oColors.brightRed + "Aborting the update process."+ oColors.standardWhite)
return False
except NameError:
print(oColors.brightRed + "Check for updates before updating plugins with: 'check all'" + oColors.standardWhite)
print(oColors.brightRed + "Started checking for updates..." + oColors.standardWhite)
checkInstalledPackage()
print(oColors.brightRed + f"Please input 'update {inputSelectedObject}' again!" + oColors.standardWhite)
return False
i = 0
pluginsUpdated = 0
print(f"Updating: {inputSelectedObject}")
print("Index | Name | Old V. | New V.")
indexNumberUpdated = 0
print(oColors.brightBlack + f"Updating: {inputSelectedObject}" + oColors.standardWhite)
print("┌─────┬────────────────────────────────┬────────────┬──────────┐")
print("│ No. │ Name │ Old V. │ New V. │")
print("└─────┴────────────────────────────────┴────────────┴──────────┘")
try:
for plugin in pluginList:
for pluginArray in track(INSTALLEDPLUGINLIST, description="Updating" ,transient=True, complete_style="bright_magenta", ):
plugin = INSTALLEDPLUGINLIST[i][0]
if not configValues.localPluginFolder:
if configValues.sftp_seperateDownloadPath is True:
pluginFile = f"{configValues.sftp_pathToSeperateDownloadPath}/{plugin}"
else:
pluginFile = f"{configValues.sftp_folderPath}/{plugin}"
if configValues.sftp_useSftp:
pluginAttributes = sftp_validateFileAttributes(connection, pluginFile)
if pluginAttributes == False:
i += 1
continue
else:
pluginAttributes = ftp_validateFileAttributes(connection, pluginFile)
if pluginAttributes == False:
i += 1
continue
else:
pluginFolderPath = configValues.pathToPluginFolder
if not os.path.isfile(Path(f"{pluginFolderPath}/{plugin}")):
i += 1
continue
if not re.search(r'.jar$', plugin):
i += 1
continue
try:
fileName = getFileName(plugin)
fileVersion = getFileVersion(plugin)
pluginId = getInstalledPlugin(fileName, fileVersion)
latestVersion = getLatestPluginVersion(pluginId)
except TypeError:
continue
except ValueError:
pluginId = INSTALLEDPLUGINLIST[i][1]
latestVersion = INSTALLEDPLUGINLIST[i][3]
except (TypeError, ValueError):
i += 1
continue
if re.search(r'.jar$', fileName):
fileName = eggCrackingJar(plugin, "name")
pluginIdStr = str(pluginId)
if pluginId == None:
print(oColors.brightRed + "Couldn't find plugin id. Sorry :(" + oColors.standardWhite)
if pluginId == None or pluginId == '':
i += 1
continue
if inputSelectedObject == pluginIdStr or re.search(inputSelectedObject, fileName, re.IGNORECASE):
if INSTALLEDPLUGINLIST[i][3] == True:
print(f" [{pluginsUpdated+1}]".ljust(8), end='')
print(f"{fileName}".ljust(30), end='')
print(f"{fileVersion}".ljust(8), end='')
print(" ", end='')
print(f"{latestVersion}".ljust(8))
if not checkConfig().localPluginFolder:
pluginPath = checkConfig().sftp_folderPath
pluginPath = f"{pluginPath}\\{plugin}"
sftp = createSFTPConnection()
sftp.remove(pluginPath)
getSpecificPackage(pluginId, checkConfig().sftp_folderPath)
pluginsUpdated += 1
else:
if checkConfig().seperateDownloadPath is True:
pluginPath = checkConfig().pathToSeperateDownloadPath
if inputSelectedObject == 'all' or inputSelectedObject == pluginIdStr or re.search(inputSelectedObject, fileName, re.IGNORECASE):
if INSTALLEDPLUGINLIST[i][4] == True:
print(f" [{indexNumberUpdated+1}]".rjust(6), end='')
print(" ", end='')
print(f"{fileName}".ljust(33), end='')
print(f"{fileVersion}".ljust(13), end='')
print(f"{latestVersion}".ljust(13))
if not configValues.localPluginFolder:
if configValues.sftp_useSftp:
if configValues.sftp_seperateDownloadPath is True:
pluginPath = configValues.sftp_pathToSeperateDownloadPath
else:
pluginPath = configValues.sftp_folderPath
pluginPath = f"{pluginPath}/{plugin}"
sftp = createSFTPConnection()
indexNumberUpdated += 1
pluginsUpdated += 1
try:
getSpecificPackage(pluginId, configValues.sftp_folderPath)
if configValues.sftp_seperateDownloadPath is False:
sftp.remove(pluginPath)
except HTTPError as err:
print(oColors.brightRed + f"HTTPError: {err.code} - {err.reason}" + oColors.standardWhite)
pluginsUpdated -= 1
except FileNotFoundError:
print(oColors.brightRed + f"FileNotFoundError: Old plugin file coulnd't be deleted" + oColors.standardWhite)
else:
pluginPath = checkConfig().pathToPluginFolder
pluginPath = f"{pluginPath}\\{plugin}"
os.remove(pluginPath)
getSpecificPackage(pluginId, checkConfig().pathToPluginFolder)
if configValues.sftp_seperateDownloadPath is True:
pluginPath = configValues.sftp_pathToSeperateDownloadPath
else:
pluginPath = configValues.sftp_folderPath
pluginPath = f"{pluginPath}/{plugin}"
ftp = createFTPConnection()
indexNumberUpdated += 1
pluginsUpdated += 1
try:
getSpecificPackage(pluginId, configValues.sftp_folderPath)
if configValues.sftp_seperateDownloadPath is False:
ftp.delete(pluginPath)
except HTTPError as err:
print(oColors.brightRed + f"HTTPError: {err.code} - {err.reason}" + oColors.standardWhite)
pluginsUpdated -= 1
except FileNotFoundError:
print(oColors.brightRed + f"FileNotFoundError: Old plugin file coulnd't be deleted" + oColors.standardWhite)
else:
if configValues.seperateDownloadPath is True:
pluginPath = configValues.pathToSeperateDownloadPath
else:
pluginPath = pluginFolderPath
pluginPath = Path(f"{pluginPath}/{plugin}")
indexNumberUpdated += 1
pluginsUpdated += 1
break
else:
print(f"{fileName} is already on {latestVersion}")
try:
getSpecificPackage(pluginId, pluginFolderPath)
if configValues.seperateDownloadPath is False:
os.remove(pluginPath)
except HTTPError as err:
print(oColors.brightRed + f"HTTPError: {err.code} - {err.reason}" + oColors.standardWhite)
pluginsUpdated -= 1
except FileNotFoundError:
print(oColors.brightRed + f"FileNotFoundError: Old plugin file coulnd't be deleted" + oColors.standardWhite)
if inputSelectedObject != 'all':
break
elif inputSelectedObject != 'all':
print(oColors.brightGreen + f"{fileName} is already on {latestVersion}" + oColors.standardWhite)
print(oColors.brightRed + "Aborting the update process."+ oColors.standardWhite)
break
else:
i += 1
continue
if inputSelectedObject == 'all':
if INSTALLEDPLUGINLIST[i][3] == True:
print(f" [{pluginsUpdated+1}]".ljust(8), end='')
print(f"{fileName}".ljust(30), end='')
print(f"{fileVersion}".ljust(8), end='')
print(" ", end='')
print(f"{latestVersion}".ljust(8))
if not checkConfig().localPluginFolder:
if checkConfig().sftp_seperateDownloadPath is True:
pluginPath = checkConfig().sftp_pathToSeperateDownloadPath
else:
pluginPath = checkConfig().sftp_folderPath
pluginPath = checkConfig().sftp_folderPath
pluginPath = f"{pluginPath}\\{plugin}"
sftp = createSFTPConnection()
sftp.remove(pluginPath)
getSpecificPackage(pluginId, checkConfig().sftp_folderPath)
pluginsUpdated += 1
else:
if checkConfig().seperateDownloadPath is True:
pluginPath = checkConfig().pathToSeperateDownloadPath
else:
pluginPath = checkConfig().pathToPluginFolder
pluginPath = f"{pluginPath}\\{plugin}"
os.remove(pluginPath)
getSpecificPackage(pluginId, checkConfig().pathToPluginFolder)
pluginsUpdated += 1
i = i + 1
i += 1
except TypeError:
print(oColors.brightRed + "Aborted updating for plugins." + oColors.standardWhite)
print(f"[{pluginsUpdated}/{i}] Plugins updated")
if inputSelectedObject =='all' and pluginsUpdated == 0:
print(oColors.brightGreen + "All plugins are on the latest version!" + oColors.standardWhite)
print(oColors.brightRed + "Error occured: Aborted updating plugins." + oColors.standardWhite)
except NameError:
print(oColors.brightRed + "Check for updates before updating plugins with: 'check all'" + oColors.standardWhite)
print(oColors.brightRed + "Started checking for updates..." + oColors.standardWhite)
checkInstalledPackage()
print(oColors.brightRed + f"Please input 'update {inputSelectedObject}' again!" + oColors.standardWhite)
if i != 0:
print(oColors.brightYellow + f"Plugins updated: [{pluginsUpdated}/{i}]" + oColors.standardWhite)
if inputSelectedObject =='all' and pluginsUpdated == 0 and i != 0:
print(oColors.brightGreen + "All found plugins are on the latest version!" + oColors.standardWhite)
def getInstalledPlugin(localFileName, localFileVersion):
def getInstalledPlugin(localFileName, localFileVersion, localPluginFullName):
url = "https://api.spiget.org/v2/search/resources/" + localFileName + "?field=name&sort=-downloads"
packageName = doAPIRequest(url)
i = 1
plugin_match_found = False
pluginID = None
for ressource in packageName:
localFileVersionNew = localFileVersion
i = 0
for i in range(0, 3):
if plugin_match_found == True:
break
if i == 1:
localFileVersionNew = re.sub(r'(\-\w*)', '', localFileVersion)
if i == 2:
pluginNameinYML = eggCrackingJar(localPluginFullName, 'name')
url = "https://api.spiget.org/v2/search/resources/" + pluginNameinYML + "?field=name&sort=-downloads"
try:
packageName = doAPIRequest(url)
except ValueError:
continue
pID = ressource["id"]
url2 = f"https://api.spiget.org/v2/resources/{pID}/versions?size=100&sort=-name"
packageVersions = doAPIRequest(url2)
for updates in packageVersions:
updateVersion = updates["name"]
if localFileVersion in updateVersion:
plugin_match_found = True
pluginID = pID
updateId = updates["id"]
plugin_latest_version = getLatestPluginVersion(pID)
plugin_is_outdated = compareVersions(plugin_latest_version, updateVersion)
addToPluginList(pID, updateId, plugin_latest_version , plugin_is_outdated)
break
localFileVersion = localFileVersionNew
for ressource in packageName:
if plugin_match_found == True:
continue
pID = ressource["id"]
url2 = f"https://api.spiget.org/v2/resources/{pID}/versions?size=100&sort=-name"
try:
packageVersions = doAPIRequest(url2)
except ValueError:
continue
for updates in packageVersions:
updateVersion = updates["name"]
if localFileVersionNew in updateVersion:
plugin_match_found = True
pluginID = pID
updateId = updates["id"]
plugin_latest_version = getLatestPluginVersion(pID)
plugin_is_outdated = compareVersions(plugin_latest_version, updateVersion)
addToPluginList(localPluginFullName, pID, updateId, plugin_latest_version , plugin_is_outdated)
return pluginID
i = i + 1
else:
if plugin_match_found != True:
pID = None
updateId = None
plugin_latest_version = None
plugin_is_outdated = None
addToPluginList(pID, updateId, plugin_latest_version , plugin_is_outdated)
addToPluginList(localPluginFullName, pID, updateId, plugin_latest_version , plugin_is_outdated)
return pluginID
# start query
# get id
# search with id for all version upates
# get version that matches installed version
# if match then download latest update
# else get second query

View File

View File

@@ -0,0 +1,122 @@
import os
import sys
from urllib.error import HTTPError
from pathlib import Path
from handlers.handle_sftp import createSFTPConnection, sftp_listFilesInServerRoot
from handlers.handle_ftp import createFTPConnection, ftp_listFilesInServerRoot
from handlers.handle_config import configurationValues
from utils.consoleoutput import oColors
from serverjar.serverjar_paper import paperCheckForUpdate, papermc_downloader
def checkInstalledServerjar():
configValues = configurationValues()
if not configValues.localPluginFolder:
if not configValues.sftp_useSftp:
ftp = createFTPConnection()
serverRootList = ftp_listFilesInServerRoot(ftp)
else:
sftp = createSFTPConnection()
serverRootList = sftp_listFilesInServerRoot(sftp)
else:
serverRootList = os.path.dirname(configValues.pathToPluginFolder)
serverRootList = os.listdir(serverRootList)
installedServerjarFullName = None
try:
for files in serverRootList:
try:
if '.jar' in files:
installedServerjarFullName = files
break
except TypeError:
continue
except TypeError:
print(oColors.brightRed + "Serverjar couldn't be found." + oColors.standardWhite)
print(oColors.brightRed + "Aborting the process." + oColors.standardWhite)
if installedServerjarFullName == None:
print(oColors.brightRed + "Serverjar couldn't be found." + oColors.standardWhite)
print(oColors.brightRed + "Aborting the process." + oColors.standardWhite)
input("Press any key + enter to exit...")
sys.exit()
print(oColors.brightBlack + f"Checking: {installedServerjarFullName}" + oColors.standardWhite)
if 'paper' in installedServerjarFullName:
paperCheckForUpdate(installedServerjarFullName)
else:
print(oColors.brightRed + f"{installedServerjarFullName} isn't supported.")
print(oColors.brightRed + "Aborting the process." + oColors.standardWhite)
def updateServerjar(serverJarBuild='latest'):
configValues = configurationValues()
try:
if serverJarBuild == None:
serverJarBuild = 'latest'
if not configValues.localPluginFolder:
sftp = createSFTPConnection()
serverRootPath = configValues.sftp_folderPath
serverRootPath = Path(str(serverRootPath).replace(r'/plugins', ''))
serverRootList = sftp_listFilesInServerRoot(sftp)
else:
serverRoot = os.path.dirname(configValues.pathToPluginFolder)
serverRootList = os.listdir(serverRoot)
serverRootPath = configValues.pathToPluginFolder
helpPath = Path('/plugins')
helpPathstr = str(helpPath)
serverRootPath = Path(str(serverRootPath).replace(helpPathstr, ''))
installedServerjarFullName = None
except FileNotFoundError:
print(oColors.brightRed + "Path couldn't be found!" + oColors.standardWhite)
print(oColors.brightRed + "Check your config!" + oColors.standardWhite)
print(oColors.brightRed + "Aborting the process." + oColors.standardWhite)
input("Press any key + enter to exit...")
sys.exit()
try:
for files in serverRootList:
try:
if '.jar' in files:
installedServerjarFullName = files
break
except TypeError:
continue
except TypeError:
print(oColors.brightRed + "Serverjar couldn't be found." + oColors.standardWhite)
print(oColors.brightRed + "Aborting the process." + oColors.standardWhite)
if installedServerjarFullName == None:
print(oColors.brightRed + "Serverjar couldn't be found." + oColors.standardWhite)
print(oColors.brightRed + "Aborting the process." + oColors.standardWhite)
input("Press any key + enter to exit...")
sys.exit()
serverJarPath = Path(f"{serverRootPath}/{installedServerjarFullName}")
if 'paper' in installedServerjarFullName:
print(oColors.brightBlack + f"Updating Paper to build: {serverJarBuild}" + oColors.standardWhite)
if not configValues.localPluginFolder:
try:
papermc_downloader(serverJarBuild, installedServerjarFullName)
sftp.remove(serverJarPath)
except HTTPError as err:
print(oColors.brightRed + f"Error: {err.code} - {err.reason}" + oColors.standardWhite)
except FileNotFoundError:
print(oColors.brightRed + "Error: Old serverjar file coulnd't be deleted" + oColors.standardWhite)
else:
try:
papermc_downloader(serverJarBuild, installedServerjarFullName)
os.remove(serverJarPath)
except HTTPError as err:
print(oColors.brightRed + f"Error: {err.code} - {err.reason}" + oColors.standardWhite)
except FileNotFoundError:
print(oColors.brightRed + "Error: Old serverjar file coulnd't be deleted" + oColors.standardWhite)
else:
print(oColors.brightRed + f"{installedServerjarFullName} isn't supported.")
print(oColors.brightRed + "Aborting the process." + oColors.standardWhite)

View File

@@ -0,0 +1,216 @@
import re
import urllib.request
from pathlib import Path
from rich.console import Console
from utils.consoleoutput import oColors
from utils.web_request import doAPIRequest
from handlers.handle_sftp import createSFTPConnection, sftp_upload_server_jar
from handlers.handle_ftp import createFTPConnection, ftp_upload_server_jar
from handlers.handle_config import configurationValues
from utils.utilities import createTempPluginFolder, deleteTempPluginFolder, calculateFileSizeMb
def getInstalledPaperMinecraftVersion(localPaperName):
if localPaperName is None:
return False
mcVersionFull = re.search(r'(\d*\.*\d)+', localPaperName)
try:
mcVersion = mcVersionFull.group()
except AttributeError:
mcVersion = mcVersionFull
return mcVersion
def getInstalledPaperVersion(localPaperName):
if localPaperName is None:
return False
paperBuildFull = re.search(r'([\d]*.jar)', localPaperName)
try:
paperBuild = paperBuildFull.group()
except AttributeError:
paperBuild = paperBuildFull
paperBuild = paperBuild.replace('.jar', '')
return paperBuild
def findVersionGroup(mcVersion):
versionGroups = ['1.17', '1.16', '1.15']
if mcVersion is None:
return False
for versionGroup in versionGroups:
url = f"https://papermc.io/api/v2/projects/paper/version_group/{versionGroup}/builds"
papermcdetails = doAPIRequest(url)
papermcVersionForMc = papermcdetails["versions"]
for versions in papermcVersionForMc:
if versions == mcVersion:
paperVersionGroup = versionGroup
return paperVersionGroup
if versionGroup == mcVersion:
paperVersionGroup = versionGroup
return paperVersionGroup
return False # Not found
def findBuildVersion(wantedPaperBuild):
versionGroups = ['1.17', '1.16', '1.15']
if wantedPaperBuild is None:
return False
for versionGroup in versionGroups:
url = f"https://papermc.io/api/v2/projects/paper/version_group/{versionGroup}/builds"
papermcdetails = doAPIRequest(url)
paperMcBuilds = papermcdetails["builds"]
for build in paperMcBuilds:
paperBuild = str(build["build"])
if paperBuild == wantedPaperBuild:
paperVersionGroup = build["version"]
return paperVersionGroup
return False # Not found
def findLatestBuild(paperVersionGroup):
if paperVersionGroup is None:
return False
url = f"https://papermc.io/api/v2/projects/paper/version_group/{paperVersionGroup}/builds"
papermcbuilds = doAPIRequest(url)
if "status" in papermcbuilds: # Checks if the API returns a status. This means that there was an error.
return False
latestPaperBuild = papermcbuilds["builds"][-1]["build"]
return latestPaperBuild
def findLatestBuildForVersion(mcVersion):
if mcVersion is None:
return False
url = f"https://papermc.io/api/v2/projects/paper/versions/{mcVersion}"
papermcbuilds = doAPIRequest(url)
latestPaperBuild = papermcbuilds["builds"][-1]
return latestPaperBuild
def versionBehind(installedPaperBuild, latestPaperBuild):
if installedPaperBuild is None or latestPaperBuild is None:
return False
installedPaperBuildint = int(installedPaperBuild)
latestPaperBuildint = int(latestPaperBuild)
versionsBehind = latestPaperBuildint - installedPaperBuildint
return versionsBehind
def getDownloadFileName(paperMcVersion, paperBuild):
if paperMcVersion is None or paperBuild is None:
return False
url = f"https://papermc.io/api/v2/projects/paper/versions/{paperMcVersion}/builds/{paperBuild}"
buildDetails = doAPIRequest(url)
downloadName = buildDetails["downloads"]["application"]["name"]
return downloadName
def paperCheckForUpdate(installedServerjarFullName):
mcVersion = getInstalledPaperMinecraftVersion(installedServerjarFullName)
# Report an error if getInstalledPaperMinecraftVersion encountered an issue.
if not mcVersion:
print(oColors.brightRed + f"ERR: An error was encountered while detecting the server's Minecraft version." +
oColors.standardWhite)
return False
paperInstalledBuild = getInstalledPaperVersion(installedServerjarFullName)
# Report an error if getInstalledPaperVersion encountered an issue.
if not paperInstalledBuild:
print(oColors.brightRed + f"ERR: An error was encountered while detecting the server's Paper version." +
oColors.standardWhite)
return False
versionGroup = findVersionGroup(mcVersion)
# Report an error if findVersionGroup encountered an issue.
if not versionGroup:
print(oColors.brightRed + f"ERR: An error was encountered while fetching the server's version group." +
oColors.standardWhite)
return False
paperLatestBuild = findLatestBuild(versionGroup)
# Report an error if findLatestBuild encountered an issue.
if not paperLatestBuild:
print(oColors.brightRed + f"ERR: An error was encountered while fetching the latest version of PaperMC." +
oColors.standardWhite)
return False # Not currently handled, but can be at a later date. Currently just stops the following from
# being printed.
paperVersionBehind = versionBehind(paperInstalledBuild, paperLatestBuild)
# Report an error if getInstalledPaperVersion encountered an issue.
if not paperVersionBehind:
print(oColors.brightRed + f"ERR: An error was encountered while detecting how many versions behind you are. "
f"Will display as 'N/A'." + oColors.standardWhite)
paperVersionBehind = "N/A" # Sets paperVersionBehind to N/A while still letting the versionBehind check return
# False for error-handing reasons.
# Does not return false as versions behind doesn't break things. It is just helpful information.
# paperVersionBehind will just display as "N/A"
print("┌─────┬────────────────────────────────┬──────────────┬──────────────┬───────────────────┐")
print("│ No. │ Name │ Installed V. │ Latest V. │ Versions behind │")
print("└─────┴────────────────────────────────┴──────────────┴──────────────┴───────────────────┘")
print(" [1]".rjust(6), end='')
print(" ", end='')
print("paper".ljust(33), end='')
print(f"{paperInstalledBuild}".ljust(15), end='')
print(f"{paperLatestBuild}".ljust(15), end='')
print(f"{paperVersionBehind}".ljust(8))
print(oColors.brightYellow + f"Versions behind: [{paperVersionBehind}]" + oColors.standardWhite)
# https://papermc.io/api/docs/swagger-ui/index.html?configUrl=/api/openapi/swagger-config#/
def papermc_downloader(paperBuild='latest', installedServerjarName=None, mcVersion=None):
configValues = configurationValues()
if configValues.localPluginFolder == False:
downloadPath = createTempPluginFolder()
else:
downloadPath = configValues.pathToPluginFolder
helpPath = Path('/plugins')
helpPathstr = str(helpPath)
downloadPath = Path(str(downloadPath).replace(helpPathstr, ''))
if mcVersion == None:
if paperBuild == 'latest':
mcVersion = '1.17'
else:
mcVersion = findBuildVersion(paperBuild)
if installedServerjarName != None:
mcVersion = getInstalledPaperMinecraftVersion(installedServerjarName)
if paperBuild == 'latest':
paperBuild = findLatestBuildForVersion(mcVersion)
try:
downloadFileName = getDownloadFileName(mcVersion, paperBuild)
except KeyError:
print(oColors.brightRed + f"This version wasn't found for {mcVersion}" + oColors.standardWhite)
print(oColors.brightRed + f"Reverting to latest version for {mcVersion}" + oColors.standardWhite)
paperBuild = findLatestBuildForVersion(mcVersion)
downloadFileName = getDownloadFileName(mcVersion, paperBuild)
downloadPackagePath = Path(f"{downloadPath}/{downloadFileName}")
if configValues.localPluginFolder == False:
downloadPath = createTempPluginFolder()
url = f"https://papermc.io/api/v2/projects/paper/versions/{mcVersion}/builds/{paperBuild}/downloads/{downloadFileName}"
remotefile = urllib.request.urlopen(url)
filesize = remotefile.info()['Content-Length']
print(f"Getting Paper {paperBuild} for {mcVersion}")
console = Console()
with console.status("Downloading...", spinner='line', spinner_style='bright_magenta') as status:
urllib.request.urlretrieve(url, downloadPackagePath)
filesizeData = calculateFileSizeMb(filesize)
print("Downloaded " + (str(filesizeData)).rjust(9) + f" MB here {downloadPackagePath}")
if not configValues.localPluginFolder:
if not configValues.sftp_useSftp:
ftpSession = createFTPConnection()
ftp_upload_server_jar(ftpSession, downloadPackagePath)
else:
sftpSession = createSFTPConnection()
sftp_upload_server_jar(sftpSession, downloadPackagePath)
deleteTempPluginFolder(downloadPath)
print(oColors.brightGreen + "Downloaded successfully " + oColors.standardWhite + f"Paper {paperBuild}" + \
oColors.brightGreen + " for " + oColors.standardWhite + f"{mcVersion}" + oColors.standardWhite)

View File

@@ -13,11 +13,11 @@ def clearConsole():
# https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
class oColors:
standardWhite = "\033[0m"
brightYellow = "\033[93m"
brightMagenta = "\033[95m"
brightBlack = "\033[90m"
brightRed = "\033[91m"
brightGreen = "\033[92m"
darkMagenta = "\033[35m"
brightYellow = "\033[93m"
brightMagenta = "\033[95m"
def printLogo():
@@ -72,9 +72,12 @@ def printLogo():
oColors.standardWhite)
print()
print()
print(oColors.brightYellow + " [" + oColors.darkMagenta + "By Neocky" +
oColors.brightYellow + "] " + oColors.standardWhite)
print()
print(oColors.brightBlack + " ┌────────────────────────────────────┐" + oColors.standardWhite)
print(oColors.brightBlack + " [" + oColors.brightMagenta + "By Neocky" +oColors.brightBlack +
"] │ " + oColors.standardWhite)
print(oColors.brightBlack + "" + oColors.brightMagenta + "https://github.com/Neocky/pluGET" + oColors.brightBlack +
"" + oColors.standardWhite)
print(oColors.brightBlack + " └────────────────────────────────────┘" + oColors.standardWhite)
def printHorizontalLine():

View File

@@ -3,26 +3,105 @@ import os
import sys
import shutil
import requests
from pathlib import Path
from utils.consoleoutput import oColors
from handlers.handle_config import checkConfig
from handlers.handle_config import configurationValues
from handlers.handle_sftp import createSFTPConnection
from handlers.handle_ftp import createFTPConnection
def getHelp():
print(oColors.brightYellow+ "Need help?" + oColors.standardWhite)
print("Check the docs here:")
print("For a list of all commands: 'help command'")
print("Or check the docs here:")
print("https://github.com/Neocky/pluGET")
print("Or go to the official discord.")
print("The link for discord can also be found on Github!")
def check_local_plugin_folder():
if checkConfig().localPluginFolder:
if checkConfig().seperateDownloadPath:
pluginFolderPath = checkConfig().pathToSeperateDownloadPath
def getCommandHelp(optionalParams):
if optionalParams == None:
optionalParams = 'all'
print(oColors.brightBlack + f"Help for command: {optionalParams}" +oColors.standardWhite)
print("┌────────────────┬─────────────────┬─────────────────┬────────────────────────────────────────────────────────┐")
print("│ Command │ Selected Object │ Optional Params │ Function │")
print("└────────────────┴─────────────────┴─────────────────┴────────────────────────────────────────────────────────┘")
while True:
if optionalParams == 'all':
print(oColors.brightBlack + " GENERAL:" + oColors.standardWhite)
print(" exit ./anything Exit pluGET")
print(" help ./anything Get general help")
print(" help command all/command Get specific help to the commands of pluGET")
print(oColors.brightBlack + " PLUGIN MANAGEMENT:" + oColors.standardWhite)
print(" get Name/ID Version Downloads the latest version of a plugin")
print(" check Name/ID/all changelog Check for an update of an installed plugin")
print(" update Name/ID/all Update installed plugins to the latest version")
print(" search Name Search for a plugin and download the latest version")
print(" remove Name/ID Delete an installed plugin")
print(oColors.brightBlack + " SERVER SOFTWARE MANAGEMENT:" + oColors.standardWhite)
print(" check serverjar Check installed server software for an update")
print(" update serverjar Version/Latest Update installed server software to a specific version")
print(" get-paper PaperVersion McVersion Downloads a specific PaperMc version")
break
if optionalParams == 'exit':
print(oColors.brightBlack + " GENERAL:" + oColors.standardWhite)
print(" exit ./anything Exit pluGET")
break
if optionalParams == 'help':
print(oColors.brightBlack + " GENERAL:" + oColors.standardWhite)
print(" help ./anything Get general help")
print(" help command all/command Get specific help to the commands of pluGET")
break
if optionalParams == 'get':
print(oColors.brightBlack + " PLUGIN MANAGEMENT:" + oColors.standardWhite)
print(print(" get Name/ID Version Downloads the latest version of a plugin"))
break
if optionalParams == 'check':
print(oColors.brightBlack + " PLUGIN MANAGEMENT:" + oColors.standardWhite)
print(" check Name/ID/all Check for an update of an installed plugin")
print(oColors.brightBlack + " SERVER SOFTWARE MANAGEMENT:" + oColors.standardWhite)
print(" check serverjar Check installed server software for an update")
break
if optionalParams == 'update':
print(oColors.brightBlack + " PLUGIN MANAGEMENT:" + oColors.standardWhite)
print(" update Name/ID/all Update installed plugins to the latest version")
print(oColors.brightBlack + " SERVER SOFTWARE MANAGEMENT:" + oColors.standardWhite)
print(" update serverjar Version/Latest Update installed server software to a specific version")
break
if optionalParams == 'search':
print(oColors.brightBlack + " PLUGIN MANAGEMENT:" + oColors.standardWhite)
print(" search Name Search for a plugin and download the latest version")
break
if optionalParams == 'remove':
print(oColors.brightBlack + " PLUGIN MANAGEMENT:" + oColors.standardWhite)
print(" remove Name/ID Delete an installed plugin")
break
if optionalParams == 'get-paper':
print(oColors.brightBlack + " SERVER SOFTWARE MANAGEMENT:" + oColors.standardWhite)
print(" get-paper PaperVersion McVersion Downloads a specific PaperMc version")
break
else:
pluginFolderPath = checkConfig().pathToPluginFolder
print(oColors.brightRed + "Error: Help for Command not found. Please try again. :(" + oColors.standardWhite)
break
def check_local_plugin_folder():
configValues = configurationValues()
if configValues.localPluginFolder:
if configValues.seperateDownloadPath:
pluginFolderPath = configValues.pathToSeperateDownloadPath
else:
pluginFolderPath = configValues.pathToPluginFolder
if not os.path.isdir(pluginFolderPath):
print(oColors.brightRed + "Plugin folder coulnd*t be found. Creating one..." + oColors.standardWhite)
@@ -41,7 +120,7 @@ def apiTest():
apiStatusUrl = 'https://api.spiget.org/v2/status'
try:
r = requests.get(apiStatusUrl)
except requests.exceptions.HTTPError:
except (requests.exceptions.HTTPError, requests.exceptions.ConnectionError):
print(oColors.brightRed + "Couldn't make a connection to the API. Check you connection to the internet!" + oColors.standardWhite)
input("Press any key + enter to exit...")
sys.exit()
@@ -52,19 +131,24 @@ def apiTest():
def check_requirements():
configValues = configurationValues()
apiTest()
check_local_plugin_folder()
if not checkConfig().localPluginFolder:
createSFTPConnection()
if not configValues.localPluginFolder:
if configValues.sftp_useSftp:
createSFTPConnection()
else:
createFTPConnection()
def createTempPluginFolder():
tempPluginFolder = ".\\plugins"
configValues = configurationValues()
tempPluginFolder = Path("./TempSFTPFolder")
if not os.path.isdir(tempPluginFolder):
try:
os.mkdir(tempPluginFolder)
except OSError:
print(oColors.brightRed + "Creation of directory %s failed" % checkConfig().pathToPluginFolder)
print(oColors.brightRed + "Creation of directory %s failed" % configValues.pathToPluginFolder)
print(oColors.brightRed + "Please check the config file!" + oColors.standardWhite)
input("Press any key + enter to exit...")
sys.exit()
@@ -76,3 +160,16 @@ def deleteTempPluginFolder(tempPluginFolder):
shutil.rmtree(tempPluginFolder)
except OSError as e:
print ("Error: %s - %s." % (e.filename, e.strerror))
def calculateFileSizeMb(downloadFileSize):
fileSizeDownload = int(downloadFileSize)
fileSizeMb = fileSizeDownload / 1024 / 1024
roundedFileSize = round(fileSizeMb, 2)
return roundedFileSize
def calculateFileSizeKb(downloadFileSize):
fileSizeDownload = int(downloadFileSize)
fileSizeKb = fileSizeDownload / 1024
roundedFileSize = round(fileSizeKb, 2)
return roundedFileSize

View File

@@ -3,7 +3,7 @@ import requests
def doAPIRequest(url):
headers = {'user-agent': 'pluGET'}
headers = {'user-agent': 'pluGET/1.0'}
response = requests.get(url, headers=headers)
packageDetails = response.json()
return packageDetails