mirror of
https://github.com/Neocky/pluGET.git
synced 2024-04-29 16:12:30 +00:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
afbc3e8029 | ||
![]() |
a08aab7ae4 | ||
![]() |
b31cca5e31 | ||
![]() |
cd4a66002c | ||
![]() |
0d709cfb6f | ||
![]() |
edc300a33d | ||
![]() |
11b4fdcbeb | ||
![]() |
716227eafa | ||
![]() |
6e980a1580 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -130,3 +130,6 @@ dmypy.json
|
|||||||
|
|
||||||
# VSCode Settings
|
# VSCode Settings
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
|
# PyCharm Settings
|
||||||
|
.idea
|
||||||
|
10
README.md
10
README.md
@@ -69,7 +69,7 @@ pluGET can:
|
|||||||
- update every installed/one specific plugin
|
- update every installed/one specific plugin
|
||||||
- check for an update of every installed/one specific plugin
|
- check for an update of every installed/one specific plugin
|
||||||
- remove a plugin from the plugin folder
|
- remove a plugin from the plugin folder
|
||||||
- manager server software:
|
- manage server software:
|
||||||
- download a specific server software version
|
- download a specific server software version
|
||||||
- check installed server software for update
|
- check installed server software for update
|
||||||
- update installed server software to a specific version
|
- update installed server software to a specific version
|
||||||
@@ -88,7 +88,7 @@ If you feel like showing your love and/or appreciation for this project then how
|
|||||||
|
|
||||||
|
|
||||||
## Need help?
|
## 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
|
## Installation
|
||||||
@@ -104,7 +104,7 @@ py -m pip install -r requirements.txt
|
|||||||
|
|
||||||
|
|
||||||
### Edit the Config
|
### Edit the Config
|
||||||
When run the first time, the `config.ini` file will be created in the `\src`folder and the program will close.
|
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.
|
Edit the config to your needs and relaunch pluGET.
|
||||||
**Now you are good to go!**
|
**Now you are good to go!**
|
||||||
|
|
||||||
@@ -112,6 +112,10 @@ Edit the config to your needs and relaunch pluGET.
|
|||||||
### Windows:
|
### Windows:
|
||||||
Execute the `launcher.bat` in the `\pluGET` folder.
|
Execute the `launcher.bat` in the `\pluGET` folder.
|
||||||
This will launch pluGET correctly.
|
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:
|
### Linux:
|
||||||
Use `cd` to change into the `/pluGET` directory and change the permission of the `launcher.sh` to make it executeable:
|
Use `cd` to change into the `/pluGET` directory and change the permission of the `launcher.sh` to make it executeable:
|
||||||
```
|
```
|
||||||
|
@@ -46,7 +46,7 @@ def getFileVersion(pluginName):
|
|||||||
if pluginVersionString.endswith('.'):
|
if pluginVersionString.endswith('.'):
|
||||||
pluginVersionString = ''
|
pluginVersionString = ''
|
||||||
if pluginVersionString == '':
|
if pluginVersionString == '':
|
||||||
pluginVersionString = eggCrackingJar(pluginNameFull)
|
pluginVersionString = eggCrackingJar(pluginNameFull, 'version')
|
||||||
return pluginVersionString
|
return pluginVersionString
|
||||||
|
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ def compareVersions(plugin_latest_version, pluginVersion):
|
|||||||
return plugin_is_outdated
|
return plugin_is_outdated
|
||||||
|
|
||||||
|
|
||||||
def eggCrackingJar(localJarFileName):
|
def eggCrackingJar(localJarFileName, searchMode):
|
||||||
configValues = configurationValues()
|
configValues = configurationValues()
|
||||||
if not configValues.localPluginFolder:
|
if not configValues.localPluginFolder:
|
||||||
if configValues.sftp_useSftp:
|
if configValues.sftp_useSftp:
|
||||||
@@ -82,21 +82,34 @@ def eggCrackingJar(localJarFileName):
|
|||||||
pluginPath = configValues.pathToPluginFolder
|
pluginPath = configValues.pathToPluginFolder
|
||||||
pathToPluginJar = Path(f"{pluginPath}/{localJarFileName}")
|
pathToPluginJar = Path(f"{pluginPath}/{localJarFileName}")
|
||||||
pluginVersion = ''
|
pluginVersion = ''
|
||||||
|
pluginName = ''
|
||||||
with ZipFile(pathToPluginJar, 'r') as pluginJar:
|
with ZipFile(pathToPluginJar, 'r') as pluginJar:
|
||||||
try:
|
try:
|
||||||
with io.TextIOWrapper(pluginJar.open('plugin.yml', 'r'), encoding="utf-8") as pluginYml:
|
with io.TextIOWrapper(pluginJar.open('plugin.yml', 'r'), encoding="utf-8") as pluginYml:
|
||||||
pluginYmlContentLine = pluginYml.readlines()
|
pluginYmlContentLine = pluginYml.readlines()
|
||||||
for line in pluginYmlContentLine:
|
for line in pluginYmlContentLine:
|
||||||
if "version: " in line:
|
if searchMode == 'version':
|
||||||
pluginVersion = line.replace('version: ', '')
|
if re.match(r'^version: ', line):
|
||||||
pluginVersion = pluginVersion.replace('\n', '')
|
pluginVersion = line.replace('version: ', '')
|
||||||
break
|
pluginVersion = pluginVersion.replace('\n', '')
|
||||||
|
pluginVersion = pluginVersion.replace("'", '')
|
||||||
|
pluginVersion = pluginVersion.replace('"', '')
|
||||||
|
elif searchMode == 'name':
|
||||||
|
if re.match(r'^name: ', line):
|
||||||
|
pluginName = line.replace('name: ', '')
|
||||||
|
pluginName = pluginName.replace('\n', '')
|
||||||
|
pluginName = pluginName.replace("'", '')
|
||||||
|
pluginName = pluginName.replace('"', '')
|
||||||
|
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
pluginVersion = ''
|
pluginVersion = ''
|
||||||
|
pluginName = ''
|
||||||
if not configValues.localPluginFolder:
|
if not configValues.localPluginFolder:
|
||||||
deleteTempPluginFolder(tempPluginFolderPath)
|
deleteTempPluginFolder(tempPluginFolderPath)
|
||||||
return pluginVersion
|
if searchMode == 'version':
|
||||||
|
return pluginVersion
|
||||||
|
if searchMode == 'name':
|
||||||
|
return pluginName
|
||||||
|
|
||||||
|
|
||||||
def checkInstalledPackage(inputSelectedObject="all"):
|
def checkInstalledPackage(inputSelectedObject="all"):
|
||||||
@@ -122,7 +135,7 @@ def checkInstalledPackage(inputSelectedObject="all"):
|
|||||||
try:
|
try:
|
||||||
fileName = getFileName(plugin)
|
fileName = getFileName(plugin)
|
||||||
fileVersion = getFileVersion(plugin)
|
fileVersion = getFileVersion(plugin)
|
||||||
pluginId = getInstalledPlugin(fileName, fileVersion)
|
pluginId = getInstalledPlugin(fileName, fileVersion, plugin)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
continue
|
continue
|
||||||
pluginIdStr = str(pluginId)
|
pluginIdStr = str(pluginId)
|
||||||
@@ -200,7 +213,7 @@ def updateInstalledPackage(inputSelectedObject='all'):
|
|||||||
try:
|
try:
|
||||||
fileName = getFileName(plugin)
|
fileName = getFileName(plugin)
|
||||||
fileVersion = getFileVersion(plugin)
|
fileVersion = getFileVersion(plugin)
|
||||||
pluginId = getInstalledPlugin(fileName, fileVersion)
|
pluginId = getInstalledPlugin(fileName, fileVersion, plugin)
|
||||||
latestVersion = getLatestPluginVersion(pluginId)
|
latestVersion = getLatestPluginVersion(pluginId)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
continue
|
continue
|
||||||
@@ -331,27 +344,40 @@ def updateInstalledPackage(inputSelectedObject='all'):
|
|||||||
print(oColors.brightGreen + "All found plugins are on the latest version!" + oColors.standardWhite)
|
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"
|
url = "https://api.spiget.org/v2/search/resources/" + localFileName + "?field=name&sort=-downloads"
|
||||||
packageName = doAPIRequest(url)
|
packageName = doAPIRequest(url)
|
||||||
plugin_match_found = False
|
plugin_match_found = False
|
||||||
pluginID = None
|
pluginID = None
|
||||||
for ressource in packageName:
|
localFileVersionNew = localFileVersion
|
||||||
|
i = 0
|
||||||
|
for i in range(0, 3):
|
||||||
if plugin_match_found == True:
|
if plugin_match_found == True:
|
||||||
break
|
break
|
||||||
pID = ressource["id"]
|
if i == 1:
|
||||||
url2 = f"https://api.spiget.org/v2/resources/{pID}/versions?size=100&sort=-name"
|
localFileVersionNew = re.sub(r'(\-\w*)', '', localFileVersion)
|
||||||
packageVersions = doAPIRequest(url2)
|
if i == 2:
|
||||||
for updates in packageVersions:
|
pluginNameinYML = eggCrackingJar(localPluginFullName, 'name')
|
||||||
updateVersion = updates["name"]
|
url = "https://api.spiget.org/v2/search/resources/" + pluginNameinYML + "?field=name&sort=-downloads"
|
||||||
if localFileVersion in updateVersion:
|
packageName = doAPIRequest(url)
|
||||||
plugin_match_found = True
|
localFileVersion = localFileVersionNew
|
||||||
pluginID = pID
|
|
||||||
updateId = updates["id"]
|
for ressource in packageName:
|
||||||
plugin_latest_version = getLatestPluginVersion(pID)
|
if plugin_match_found == True:
|
||||||
plugin_is_outdated = compareVersions(plugin_latest_version, updateVersion)
|
break
|
||||||
addToPluginList(pID, updateId, plugin_latest_version , plugin_is_outdated)
|
pID = ressource["id"]
|
||||||
return pluginID
|
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 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(pID, updateId, plugin_latest_version , plugin_is_outdated)
|
||||||
|
return pluginID
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if plugin_match_found != True:
|
if plugin_match_found != True:
|
||||||
|
@@ -15,6 +15,8 @@ from utils.utilities import createTempPluginFolder, deleteTempPluginFolder, calc
|
|||||||
|
|
||||||
# = 1.16.5
|
# = 1.16.5
|
||||||
def getInstalledPaperMinecraftVersion(localPaperName):
|
def getInstalledPaperMinecraftVersion(localPaperName):
|
||||||
|
if localPaperName is None:
|
||||||
|
return False
|
||||||
mcVersionFull = re.search(r'(\d*\.*\d)+', localPaperName)
|
mcVersionFull = re.search(r'(\d*\.*\d)+', localPaperName)
|
||||||
try:
|
try:
|
||||||
mcVersion = mcVersionFull.group()
|
mcVersion = mcVersionFull.group()
|
||||||
@@ -25,6 +27,8 @@ def getInstalledPaperMinecraftVersion(localPaperName):
|
|||||||
|
|
||||||
# = 550
|
# = 550
|
||||||
def getInstalledPaperVersion(localPaperName):
|
def getInstalledPaperVersion(localPaperName):
|
||||||
|
if localPaperName is None:
|
||||||
|
return False
|
||||||
paperBuildFull = re.search(r'([\d]*.jar)', localPaperName)
|
paperBuildFull = re.search(r'([\d]*.jar)', localPaperName)
|
||||||
try:
|
try:
|
||||||
paperBuild = paperBuildFull.group()
|
paperBuild = paperBuildFull.group()
|
||||||
@@ -36,52 +40,52 @@ def getInstalledPaperVersion(localPaperName):
|
|||||||
|
|
||||||
def findVersionGroup(mcVersion):
|
def findVersionGroup(mcVersion):
|
||||||
versionGroups = ['1.16', '1.15']
|
versionGroups = ['1.16', '1.15']
|
||||||
versionGroupFound = False
|
if mcVersion is None:
|
||||||
|
return False
|
||||||
for versionGroup in versionGroups:
|
for versionGroup in versionGroups:
|
||||||
if versionGroupFound == True:
|
|
||||||
break
|
|
||||||
url = f"https://papermc.io/api/v2/projects/paper/version_group/{versionGroup}/builds"
|
url = f"https://papermc.io/api/v2/projects/paper/version_group/{versionGroup}/builds"
|
||||||
papermcdetails = doAPIRequest(url)
|
papermcdetails = doAPIRequest(url)
|
||||||
papermcVersionForMc = papermcdetails["versions"]
|
papermcVersionForMc = papermcdetails["versions"]
|
||||||
for versions in papermcVersionForMc:
|
for versions in papermcVersionForMc:
|
||||||
if versions == mcVersion:
|
if versions == mcVersion:
|
||||||
versionGroupFound = True
|
|
||||||
paperVersionGroup = versionGroup
|
paperVersionGroup = versionGroup
|
||||||
break
|
return paperVersionGroup
|
||||||
if versionGroup == mcVersion:
|
if versionGroup == mcVersion:
|
||||||
versionGroupFound = True
|
|
||||||
paperVersionGroup = versionGroup
|
paperVersionGroup = versionGroup
|
||||||
break
|
return paperVersionGroup
|
||||||
|
return False # Not found
|
||||||
return paperVersionGroup
|
|
||||||
|
|
||||||
|
|
||||||
def findBuildVersion(wantedPaperBuild):
|
def findBuildVersion(wantedPaperBuild):
|
||||||
versionGroups = ['1.16', '1.15']
|
versionGroups = ['1.16', '1.15']
|
||||||
paperBuildFound = False
|
if wantedPaperBuild is None:
|
||||||
|
return False
|
||||||
for versionGroup in versionGroups:
|
for versionGroup in versionGroups:
|
||||||
if paperBuildFound is True:
|
|
||||||
break
|
|
||||||
url = f"https://papermc.io/api/v2/projects/paper/version_group/{versionGroup}/builds"
|
url = f"https://papermc.io/api/v2/projects/paper/version_group/{versionGroup}/builds"
|
||||||
papermcdetails = doAPIRequest(url)
|
papermcdetails = doAPIRequest(url)
|
||||||
paperMcBuilds = papermcdetails["builds"]
|
paperMcBuilds = papermcdetails["builds"]
|
||||||
for build in paperMcBuilds:
|
for build in paperMcBuilds:
|
||||||
paperBuild = str(build["build"])
|
paperBuild = str(build["build"])
|
||||||
if paperBuild == wantedPaperBuild:
|
if paperBuild == wantedPaperBuild:
|
||||||
paperBuildFound = True
|
|
||||||
paperVersionGroup = build["version"]
|
paperVersionGroup = build["version"]
|
||||||
break
|
return paperVersionGroup
|
||||||
return paperVersionGroup
|
return False # Not found
|
||||||
|
|
||||||
|
|
||||||
def findLatestBuild(paperVersionGroup):
|
def findLatestBuild(paperVersionGroup):
|
||||||
|
if paperVersionGroup is None:
|
||||||
|
return False
|
||||||
url = f"https://papermc.io/api/v2/projects/paper/version_group/{paperVersionGroup}/builds"
|
url = f"https://papermc.io/api/v2/projects/paper/version_group/{paperVersionGroup}/builds"
|
||||||
papermcbuilds = doAPIRequest(url)
|
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"]
|
latestPaperBuild = papermcbuilds["builds"][-1]["build"]
|
||||||
return latestPaperBuild
|
return latestPaperBuild
|
||||||
|
|
||||||
|
|
||||||
def findLatestBuildForVersion(mcVersion):
|
def findLatestBuildForVersion(mcVersion):
|
||||||
|
if mcVersion is None:
|
||||||
|
return False
|
||||||
url = f"https://papermc.io/api/v2/projects/paper/versions/{mcVersion}"
|
url = f"https://papermc.io/api/v2/projects/paper/versions/{mcVersion}"
|
||||||
papermcbuilds = doAPIRequest(url)
|
papermcbuilds = doAPIRequest(url)
|
||||||
latestPaperBuild = papermcbuilds["builds"][-1]
|
latestPaperBuild = papermcbuilds["builds"][-1]
|
||||||
@@ -89,6 +93,8 @@ def findLatestBuildForVersion(mcVersion):
|
|||||||
|
|
||||||
|
|
||||||
def versionBehind(installedPaperBuild, latestPaperBuild):
|
def versionBehind(installedPaperBuild, latestPaperBuild):
|
||||||
|
if installedPaperBuild or latestPaperBuild is None:
|
||||||
|
return False
|
||||||
installedPaperBuildint = int(installedPaperBuild)
|
installedPaperBuildint = int(installedPaperBuild)
|
||||||
latestPaperBuildint = int(latestPaperBuild)
|
latestPaperBuildint = int(latestPaperBuild)
|
||||||
versionsBehind = latestPaperBuildint - installedPaperBuildint
|
versionsBehind = latestPaperBuildint - installedPaperBuildint
|
||||||
@@ -96,6 +102,8 @@ def versionBehind(installedPaperBuild, latestPaperBuild):
|
|||||||
|
|
||||||
|
|
||||||
def getDownloadFileName(paperMcVersion, paperBuild):
|
def getDownloadFileName(paperMcVersion, paperBuild):
|
||||||
|
if paperMcVersion or paperBuild is None:
|
||||||
|
return False
|
||||||
url = f"https://papermc.io/api/v2/projects/paper/versions/{paperMcVersion}/builds/{paperBuild}"
|
url = f"https://papermc.io/api/v2/projects/paper/versions/{paperMcVersion}/builds/{paperBuild}"
|
||||||
buildDetails = doAPIRequest(url)
|
buildDetails = doAPIRequest(url)
|
||||||
downloadName = buildDetails["downloads"]["application"]["name"]
|
downloadName = buildDetails["downloads"]["application"]["name"]
|
||||||
@@ -104,11 +112,50 @@ def getDownloadFileName(paperMcVersion, paperBuild):
|
|||||||
|
|
||||||
def paperCheckForUpdate(installedServerjarFullName):
|
def paperCheckForUpdate(installedServerjarFullName):
|
||||||
mcVersion = getInstalledPaperMinecraftVersion(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)
|
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)
|
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)
|
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)
|
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("┌─────┬────────────────────────────────┬──────────────┬──────────────┬───────────────────┐")
|
||||||
print("│ No. │ Name │ Installed V. │ Latest V. │ Versions behind │")
|
print("│ No. │ Name │ Installed V. │ Latest V. │ Versions behind │")
|
||||||
print("└─────┴────────────────────────────────┴──────────────┴──────────────┴───────────────────┘")
|
print("└─────┴────────────────────────────────┴──────────────┴──────────────┴───────────────────┘")
|
||||||
@@ -176,4 +223,4 @@ def papermc_downloader(paperBuild='latest', installedServerjarName=None, mcVersi
|
|||||||
deleteTempPluginFolder(downloadPath)
|
deleteTempPluginFolder(downloadPath)
|
||||||
|
|
||||||
print(oColors.brightGreen + "Downloaded successfully " + oColors.standardWhite + f"Paper {paperBuild}" + \
|
print(oColors.brightGreen + "Downloaded successfully " + oColors.standardWhite + f"Paper {paperBuild}" + \
|
||||||
oColors.brightGreen + " for " + oColors.standardWhite + f"{mcVersion}" + oColors.standardWhite)
|
oColors.brightGreen + " for " + oColors.standardWhite + f"{mcVersion}" + oColors.standardWhite)
|
||||||
|
Reference in New Issue
Block a user