import asyncio import requests import functools import json import bpy import os import addon_utils import tempfile import urllib.request import zipfile import shutil async def do_request(): loop = asyncio.get_event_loop() future = loop.run_in_executor(None, requests.get, 'https://api.github.com/repos/norgeotloic/BakeMyScan/releases') response = await future object = json.loads(response.text) bpy.types.Scene.newVersion = object[0]["tag_name"] for mod in addon_utils.modules(): if mod.bl_info.get("name") == "BakeMyScan": bpy.types.Scene.currentVersion = ".".join([str(x) for x in mod.bl_info.get("version")]) if bpy.types.Scene.currentVersion == bpy.types.Scene.newVersion: print("No new updates") else: print("A new update is available") print("%s -> %s" % (bpy.types.Scene.currentVersion, bpy.types.Scene.newVersion)) for a in object[0]["assets"]: if a["name"] == "BakeMyScan.zip": bpy.types.Scene.update_url = a["browser_download_url"] print(bpy.types.Scene.update_url) class CheckUpdates(bpy.types.Operator): bl_idname = "bakemyscan.check_updates" bl_label = "Check for updates" @classmethod def poll(self, context): return 1 def execute(self, context): try: loop = asyncio.get_event_loop() loop.run_until_complete(do_request()) return {"FINISHED"} except: self.report({"ERROR"}, "Version check inoperative. Is internet off?") class Update(bpy.types.Operator): bl_idname = "bakemyscan.update" bl_label = "Update BakeMyScan" tmp = tempfile.TemporaryDirectory() @classmethod def poll(self, context): if bpy.types.Scene.newVersion is None or bpy.types.Scene.currentVersion is None: return 0 if bpy.types.Scene.newVersion == bpy.types.Scene.currentVersion: return 0 if bpy.types.Scene.update_url is None: return 0 return 1 def execute(self, context): #Download download_path = os.path.join(self.tmp.name, "BakeMyScan.zip") urllib.request.urlretrieve(bpy.types.Scene.update_url, filename=download_path) #Extract extract_path = os.path.join(self.tmp.name, "tmp_extract") with zipfile.ZipFile(download_path, 'r') as zip_ref: zip_ref.extractall(extract_path) #Move the BakeMyScan folder to the root temporary directory os.rename(os.path.join(self.tmp.name, "tmp_extract", "BakeMyScan"), os.path.join(self.tmp.name, "BakeMyScan")) shutil.rmtree(os.path.join(self.tmp.name, "tmp_extract")) #Replace final_path = os.path.join(bpy.utils.resource_path('USER'), "scripts", "addons", "BakeMyScan") print(final_path) go = True if go: if os.path.exists(final_path): if os.path.isdir(final_path): shutil.rmtree(final_path) os.rename(os.path.join(self.tmp.name, "BakeMyScan"), final_path) #Prepare the restart to update the scripts bpy.types.Scene.restartRequired = True return {"FINISHED"} def register(): bpy.utils.register_class(CheckUpdates) bpy.utils.register_class(Update) bpy.types.Scene.newVersion = None bpy.types.Scene.currentVersion = None bpy.types.Scene.update_url = None bpy.types.Scene.restartRequired = False def unregister(): bpy.utils.unregister_class(CheckUpdates) bpy.utils.unregister_class(Update) del bpy.types.Scene.newVersion del bpy.types.Scene.currentVersion del bpy.types.Scene.update_url del bpy.types.Scene.restartRequired