import platform
import requests
from os import popen,remove,mkdir
import shutil
from time import sleep
import re
import pathlib
import json
import socket
def checkConnection(host="8.8.8.8", port=53, timeout=3):
try:
socket.setdefaulttimeout(timeout)
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
return True
except socket.error:
return False
def regainedConnection() -> bool :
global lostConnection
checkedConnection = checkConnection()
if checkedConnection == True :
if checkedConnection == lostConnection :
lostConnection = not checkedConnection
return True
else :
return False
else :
lostConnection = not checkedConnection
return True
lostConnection = True
def getArch() -> str :
arch = platform.machine()
if arch in ['x86_64','AMD64'] :
return 'x86_64'
elif arch in ['arm64','aarch64'] :
return 'arm64'
OS = platform.system()
if OS == 'Linux' :
APPDATA = f"{pathlib.Path.home()}/.gvm_data/"
elif OS == 'Windows' :
APPDATA =f"{pathlib.Path.home()}\\AppData\\Roaming\\GVM\\"
FIRSTOPEN = not pathlib.Path(f"{APPDATA}settings.json").exists()
if FIRSTOPEN :
try :
mkdir(APPDATA)
except :
pass
finally :
open(f"{APPDATA}settings.json",'w').write(json.dumps({'appPath':'','token':''}))
SETTINGS = json.load(open(f"{APPDATA}settings.json",'r'))
def updateSettings(appPath: str, token: str) -> None :
global APP_PATH
global TOKEN
APP_PATH = appPath
TOKEN = token
APP_PATH: str = SETTINGS['appPath']
WIN_COMP: str = APP_PATH.replace('/','\\')
TOKEN: str = SETTINGS['token']
ARCH = getArch()
def requestGitHubInfo() -> list :
if len(TOKEN) > 0 :
response = requests.get("https://api.github.com/repos/godotengine/godot/releases?per_page=100",headers={"Accept":"application/vnd.github+json","Authorization":f"Bearer {TOKEN}","X-GitHub-Api-Version":"2022-11-28"})
else :
return []
return response.json()
# Get the versions of the Godot Engine and sort them from latest to oldest
def verOptions(mono: str, curVersion: list|None) -> list:
tag_list = []
if regainedConnection() :
response = requestGitHubInfo()
else :
response = curVersion
if type(response) == dict :
installed_files = getAllFiles(mono)
installed_files.sort(reverse=True)
if installed_files != [] :
return installed_files
else:
tag_list.append('No options available')
return tag_list
elif curVersion != None and checkConnection() :
return curVersion
for i in response :
tag_list.append(i['tag_name'])
if tag_list != [] :
tag_list.sort(reverse=True)
tag_list.pop()
else :
installed_files = getAllFiles(mono)
installed_files.sort(reverse=True)
if installed_files != [] :
return installed_files
else:
tag_list.append('No options available')
return tag_list
def downloadGodot(cur_version: str,mono: str) -> int :
if not pathlib.Path(APP_PATH).exists() :
return 1
response = requestGitHubInfo()
if type(response) == dict :
return 1
VERSION = cur_version
response.sort(key=lambda x: x['tag_name'],reverse=True)
ASSETS = getAssets(response, VERSION)
if ASSETS != [] :
for asset in ASSETS :
if OS == 'Linux' :
regex: list = re.findall("linux|x11",asset['name']) + re.findall("x86_64|64",asset['name'])
if mono != 'no_mono' :
regex += re.findall(mono,asset['name'])
monoCatch = ""
monoGoal = ['mono']
else :
monoCatch = "|mono"
monoGoal = []
if re.findall(f"server|headless{monoCatch}",asset['name']) == [] and regex in [['linux','x86_64']+monoGoal,['x11','64']+monoGoal] :#(asset['name'].find('linux') > 0 or asset['name'].find('x11') > 0) and (asset['name'].find(ARCH) > 0 or asset['name'].find('64') > 0) and asset['name'].find('server') == -1:
popen(f"curl -Lo {APP_PATH}/Godot.zip {asset['browser_download_url']}")
sleep(10)
popen(f"unzip -d {APP_PATH} {APP_PATH}/Godot.zip")
sleep(10)
remove(f"{APP_PATH}/Godot.zip")
return 0
elif OS == 'Windows' :
if mono != 'no_mono' :
monoGoal = ['mono']
else :
monoGoal = []
if ['win','arm64'] + monoGoal == re.findall('win',asset['name']) + re.findall('arm64',asset['name']) + re.findall('mono',asset['name']) :
popen(f"curl -Lo {APP_PATH}/Godot.zip {asset['browser_download_url']}")
sleep(10)
popen(f"tar -xf {APP_PATH}/Godot.zip -C {APP_PATH}")
sleep(10)
remove(f"{APP_PATH}/Godot.zip")
return 0
elif ['win64'] + monoGoal == re.findall('win64',asset['name']) + re.findall('mono',asset['name']) :
popen(f"curl -Lo {APP_PATH}/Godot.zip {asset['browser_download_url']}")
sleep(10)
popen(f"tar -xf {APP_PATH}/Godot.zip -C {APP_PATH}")
sleep(10)
remove(f"{APP_PATH}/Godot.zip")
return 0
else :
return 1
else :
return 1
def getAssets(response: list, tag: str) -> list :
for i in response :
if i['tag_name'] == tag :
return i['assets']
else :
continue
return []
def launch(cur_version: str, mono: str) -> int :
if not pathlib.Path(APP_PATH).exists() :
return 1
VERSION = cur_version.split('-')[0]
file = getFile(VERSION,mono)
if file.exists() and not file.is_dir() :
popen(f"{file.as_posix()}")
return 0
elif file.exists() and file.is_dir() :
for exe in file.iterdir() :
if re.findall('exe|x86_64|64',exe.name) and exe.is_file() :
popen(f"{exe.as_posix()}")
else :
return 1
def getFile(cur_version: str, mono: str) -> pathlib.Path | int :
if not pathlib.Path(APP_PATH).exists() :
return 1
VERSION = cur_version.split('-')[0]
appDir = pathlib.Path(APP_PATH)
if mono == 'no_mono' :
for i in appDir.iterdir() :
if re.findall(f"{VERSION}-|{VERSION}_",i.name) in [[f"{VERSION}-"],[f"{VERSION}_"]] and i.is_file() :
return i
elif mono == 'mono' :
for i in appDir.iterdir() :
if re.findall(f"{VERSION}-|{VERSION}_",i.name) + re.findall('mono',i.name) in [[f"{VERSION}-",'mono'],[f"{VERSION}_",'mono']] and i.is_dir() :
return i
return 1
def getAllFiles(mono: str) -> list :
if not pathlib.Path(APP_PATH).exists() :
return []
files = []
appDir = pathlib.Path(APP_PATH)
if mono == 'no_mono' :
for i in appDir.iterdir() :
if re.findall("-stable|_stable",i.name) in [["-stable"],["_stable"]] and i.is_file() :
if re.findall("_stable",i.name) in ["_stable"] :
i.name.replace("_stable","-stable")
files.append(re.findall("[1-9].+-stable",i.name)[0])
elif mono == 'mono' :
for i in appDir.iterdir() :
if re.findall("-stable|_stable",i.name) + re.findall('mono',i.name) in [["-stable",'mono'],["_stable",'mono']] and i.is_dir() :
if re.findall("_stable",i.name) in ["_stable"] :
i.name.replace("_stable","-stable")
files.append(re.findall("[1-9].+-stable",i.name)[0])
if files != [] :
return files
else :
return []
def suddenSet(appPath: str, token: str) -> None :
open(f"{APPDATA}settings.json",'w').write(json.dumps({'appPath':appPath,'token':token}))
updateSettings(appPath,token)
def checkSettings() -> bool :
settings = json.load(open(f"{APPDATA}settings.json",'r'))
if settings['appPath'] == '' or settings['token'] == '' :
return False
else :
return True
def removeGodot(cur_version: str, mono: str) -> int :
if not pathlib.Path(APP_PATH).exists() :
return 1
VERSION = cur_version.split('-')[0]
file = getFile(VERSION,mono)
if file.exists() :
if file.is_file() :
remove(f"{file.as_posix()}")
else :
shutil.rmtree(file.as_posix())
return 0
else :
return 1