2024-08-18 21:17:43 +00:00
|
|
|
import requests
|
|
|
|
import logging
|
|
|
|
import os
|
|
|
|
import argparse
|
|
|
|
from tqdm import tqdm
|
|
|
|
import re
|
|
|
|
|
|
|
|
|
|
|
|
githubApi = "https://api.github.com/repos"
|
|
|
|
|
|
|
|
applications = {
|
|
|
|
"freecad": { "org": "FreeCAD", # https://github.com/FreeCAD/FreeCAD-Bundle/releases
|
2024-08-18 22:56:23 +00:00
|
|
|
"repo": "FreeCAD-Bundle",
|
|
|
|
"assetRegex": "FreeCAD_weekly-builds-.*-x86_64-.*AppImage$" },
|
2024-08-18 21:17:43 +00:00
|
|
|
"bambustudio": { "org": "bambulab", # https://github.com/bambulab/BambuStudio/releases
|
2024-08-18 22:56:23 +00:00
|
|
|
"repo": "BambuStudio",
|
2024-08-29 19:54:24 +00:00
|
|
|
# "assetRegex": "Bambu_Studio_linux_ubuntu_24.*AppImage$" },
|
|
|
|
"assetRegex": "Bambu_Studio_ubuntu.*AppImage$" },
|
2024-08-18 21:17:43 +00:00
|
|
|
}
|
|
|
|
|
2024-08-18 22:56:23 +00:00
|
|
|
# get script path
|
|
|
|
scriptFolder = os.path.dirname(os.path.realpath(__file__))
|
|
|
|
|
2024-08-18 21:17:43 +00:00
|
|
|
|
|
|
|
# Cortesy: https://gist.github.com/yanqd0/c13ed29e29432e3cf3e7c38467f42f51
|
|
|
|
def download(url: str, fname: str, chunk_size=1024):
|
|
|
|
log.info("Downloading " + url)
|
|
|
|
resp = requests.get(url, stream=True)
|
|
|
|
total = int(resp.headers.get('content-length', 0))
|
|
|
|
with open(fname, 'wb') as file, tqdm(
|
|
|
|
desc=fname,
|
|
|
|
total=total,
|
|
|
|
unit='iB',
|
|
|
|
unit_scale=True,
|
|
|
|
unit_divisor=1024,
|
|
|
|
) as bar:
|
|
|
|
for data in resp.iter_content(chunk_size=chunk_size):
|
|
|
|
size = file.write(data)
|
|
|
|
bar.update(size)
|
|
|
|
|
|
|
|
|
|
|
|
def main(app):
|
|
|
|
org = applications[app]["org"]
|
|
|
|
repo = applications[app]["repo"]
|
|
|
|
# releaseTag = applications[app]["releaseTag"]
|
|
|
|
|
|
|
|
url = githubApi + "/" + org + "/" + repo + "/releases"
|
|
|
|
log.debug("url: " + url)
|
|
|
|
|
|
|
|
response = requests.get(url)
|
|
|
|
data = response.json()
|
|
|
|
# log.info("response: " + str(data))
|
|
|
|
|
|
|
|
assets = data[0]["assets"]
|
|
|
|
# log.info("Assets: " + str(assets))
|
|
|
|
|
|
|
|
assetName = None
|
|
|
|
assetUrl = None
|
|
|
|
for asset in assets:
|
|
|
|
# Eg. "FreeCAD_weekly-builds-38467-conda-Linux-x86_64-py311.AppImage"
|
|
|
|
# regex match
|
2024-08-29 19:54:24 +00:00
|
|
|
log.debug("Asset: " + asset["name"])
|
2024-08-18 21:17:43 +00:00
|
|
|
if re.match(applications[app]["assetRegex"], asset["name"]):
|
|
|
|
log.debug("Asset: " + str(asset["name"]))
|
|
|
|
assetName = asset["name"]
|
|
|
|
assetUrl = asset["browser_download_url"]
|
|
|
|
break
|
|
|
|
|
|
|
|
if assetName:
|
|
|
|
# if file exists
|
2024-08-18 22:56:23 +00:00
|
|
|
if os.path.isfile(scriptFolder + "/" + assetName):
|
2024-08-18 21:17:43 +00:00
|
|
|
log.info("Application " + app + " is already up-to-date (" + assetName + ")")
|
2024-08-18 22:35:04 +00:00
|
|
|
else: # Download it
|
|
|
|
# Eg. https://github.com/FreeCAD/FreeCAD-Bundle/releases/download/weekly-builds/FreeCAD_weekly-builds-38467-conda-Linux-x86_64-py311.AppImage
|
|
|
|
log.debug("url: " + assetUrl)
|
2024-08-18 21:17:43 +00:00
|
|
|
|
2024-08-18 22:35:04 +00:00
|
|
|
# Download to file with progress bar
|
2024-08-18 22:56:23 +00:00
|
|
|
download(assetUrl, scriptFolder + "/" + assetName + ".tmp")
|
2024-08-18 21:17:43 +00:00
|
|
|
|
2024-08-18 22:35:04 +00:00
|
|
|
# Rename
|
2024-08-18 22:56:23 +00:00
|
|
|
os.rename(scriptFolder + "/" + assetName + ".tmp", assetName)
|
2024-08-18 21:17:43 +00:00
|
|
|
|
2024-08-18 22:35:04 +00:00
|
|
|
# todo remove old appimages
|
|
|
|
|
|
|
|
# chmod
|
2024-08-18 22:56:23 +00:00
|
|
|
os.chmod(scriptFolder + "/" + assetName, 0o755)
|
2024-08-18 21:17:43 +00:00
|
|
|
|
2024-08-18 22:56:23 +00:00
|
|
|
# get user home directory
|
|
|
|
home = os.path.expanduser("~")
|
2024-08-18 21:17:43 +00:00
|
|
|
|
|
|
|
# link
|
2024-08-18 22:56:23 +00:00
|
|
|
if os.path.isfile(scriptFolder + "/" + app):
|
|
|
|
os.remove(scriptFolder + "/" + app)
|
|
|
|
os.symlink(scriptFolder + "/" + assetName, scriptFolder + "/" + app)
|
|
|
|
|
|
|
|
# Add link to start menu
|
|
|
|
desktopLink = home + "/.local/share/applications/" + app + ".desktop"
|
|
|
|
if os.path.isfile(desktopLink):
|
|
|
|
os.remove(desktopLink)
|
|
|
|
os.symlink(scriptFolder + "/" + app + ".desktop", desktopLink)
|
2024-08-18 21:17:43 +00:00
|
|
|
|
2024-08-18 22:35:04 +00:00
|
|
|
# log.info("Application " + app + " updated")
|
2024-08-29 19:54:24 +00:00
|
|
|
else:
|
|
|
|
log.error("No matching asset found in the latest release!")
|
|
|
|
exit(2)
|
2024-08-18 21:17:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument("--app", type=str, required=True, help="Application name")
|
2024-08-29 19:54:24 +00:00
|
|
|
parser.add_argument("-v", action='store_true', help="Show verbose log")
|
2024-08-18 21:17:43 +00:00
|
|
|
args = parser.parse_args()
|
2024-08-29 19:54:24 +00:00
|
|
|
|
|
|
|
if args.v:
|
|
|
|
loglevel = logging.DEBUG
|
|
|
|
else:
|
|
|
|
loglevel = logging.INFO
|
|
|
|
|
|
|
|
logging.basicConfig(format='%(asctime)s %(levelname)-8s %(message)s', level=loglevel, datefmt='%Y-%m-%d %H:%M:%S')
|
|
|
|
log = logging.getLogger(__name__)
|
2024-08-18 21:17:43 +00:00
|
|
|
|
|
|
|
for app in applications:
|
|
|
|
if app == args.app:
|
|
|
|
main(app)
|
|
|
|
exit(0)
|
|
|
|
break
|
|
|
|
|
|
|
|
log.error("Application '" + args.app + "' not found")
|
|
|
|
log.error("Supported applications: '" + "', '".join((applications.keys())) + "'")
|
|
|
|
exit(1)
|