Skip to content

Commit

Permalink
Fixed some bugs and added legacy version
Browse files Browse the repository at this point in the history
  • Loading branch information
noneeeeeeeeeee committed Jul 25, 2023
1 parent 6571654 commit 73eb0cf
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 52 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
config.ini
*.txt
*.txt
*ico
26 changes: 18 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
# AutoUpdaterGUI
Update your app from latest release. Works by deleting all your files in that one folder then pulling the .zip and extracting it

# Downloading v1.0(depricated)
Since you cannot configure using a file you have to modify the code and build the app using this command to build below and make sure to create a version.txt file or it will not launch. An empty one would suffice
Update your app to the latest release by a click of a button!

```pyinstaller --noconfirm --onedir --windowed --add-data "<CustomTkinter Location>/customtkinter;customtkinter/" "getupdate.py"```
## How to configure the auto updater

# Downloading v1.5 and above
- Launch the .exe and wait for it to generate a **config.ini** file
- Set the config.ini file with your ```API_KEY``` checking the scopes of managing private repositories
- Now when you launch it again it will create a **version.txt** file. That file will be used to compare the latest release with the current one.
- The `USERNAME` Should be your github username
- The `REPO` Should be your repository you want to pull the updates from
- Set the config.ini file with your `API_KEY` checking the scopes of managing private repositories
- The `VERSION_FILE` should be where your version number is. It should only be your current version. Because this file is used to compare your current version with the latest release (I recommend to not change the file name in the config.ini)
- After you fill in the config.ini file launch the program again and it create a version.txt file. There should be an example if the point below this one isn't clear enough
- For example `v1.0`. It should not be filled in with anything else

**It should look like this when its filled in**

![Untitled](https://github.com/noneeeeeeeeeee/AutoUpdaterGUI/assets/64634725/21abae9d-4233-48f8-9d95-5da691a2348b)

### Need a portable version?

Instructions and download provided [here](https://github.com/noneeeeeeeeeee/AutoUpdaterGUI/releases/tag/1.0.1-Legacy)

## How it works
It will get the latest release from the assets(not the source code) and extract that zip into the same directory as the application

It will delete all the files in the folder that the app is in then it gets the latest release from the assets(not the source code) and extract that zip into the same directory as the application. It will not delete the file thats in `APP_FILE`. That is also not an array so it can only do 1 file(I will implement arrays in the next version).
82 changes: 39 additions & 43 deletions getupdate.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,24 @@

config = configparser.ConfigParser()

# Try to read the config file

# If the file exists, load the values
config.read("config.ini")
try:
# Try to get the values from the config file

USERNAME = config["DEFAULT"]["USERNAME"]
REPO = config["DEFAULT"]["REPO"]
API_KEY = config["DEFAULT"]["API_KEY"]
VERSION_FILE = config["DEFAULT"]["VERSION_FILE"]
APP_FILE = config["DEFAULT"]["APP_FILE"]
except KeyError as e:
# If a key is missing, use a default value or ask the user for input

print(f"{e} is missing in the config file, Filling it with default values")
USERNAME = "YOUR_USERNAME_HERE"
REPO = "YOUR_REPOSITORY_HERE"
API_KEY = "YOUR_API_KEY_HERE"
VERSION_FILE = "version.txt"
APP_FILE = "getupdate.exe"
# Write the values to the config file

config["DEFAULT"] = {
"USERNAME": USERNAME,
"REPO": REPO,
Expand Down Expand Up @@ -71,7 +69,7 @@ def check_version():
return output == latest_tag


# Add a user agent header to your requests

s.headers["User-Agent"] = "Custom"


Expand All @@ -83,7 +81,7 @@ def update():
None, "runas", sys.executable, __file__, None, 1
)

# Delete all files and folders except the app file using a list comprehension and shutil.rmtree

[
os.remove(file)
for file in os.listdir()
Expand All @@ -94,7 +92,7 @@ def update():
for file in os.listdir()
if file != APP_FILE and os.path.exists(file) and os.path.isdir(file)
]
# Download the zip file from GitHub using requests.get and a context manager

url = f"https://api.github.com/repos/{USERNAME}/{REPO}/releases/latest"
headers = {
"Authorization": f"token {API_KEY}",
Expand All @@ -103,64 +101,63 @@ def update():
}
with requests.get(url, headers=headers) as response:
response.raise_for_status()
# Get the asset URL from the response JSON data using a for loop and a break statement

asset_url = None
for asset in response.json()["assets"]:
if asset["name"].endswith(".zip"):
asset_url = asset["url"]
break
# Download the asset file using requests.get and a context manager

headers = {
"Authorization": f"token {API_KEY}",
"Accept": "application/octet-stream",
"User-Agent": "Custom",
}
with requests.get(asset_url, headers=headers, stream=True) as response:
response.raise_for_status()
# Write the zip file using a context manager and a generator expression

with open("update.zip", "wb") as f:
# Get the total size of the file from the response headers

total_size = int(response.headers["Content-Length"])
label.configure(text="Downloading File...")
time.sleep(1)
downloaded_size = 0
for chunk in response.iter_content(chunk_size=1024):
f.write(chunk)
# Update the downloaded size by adding the chunk size

downloaded_size += len(chunk)
progress.set(downloaded_size / total_size)
downloadsizeshow = round(downloaded_size / total_size * 100, 8)
percentageshow.configure(text = f"{downloadsizeshow}%")
root.update()
time.sleep(0.1)

# Extract the zip file and delete it using a context manager and os.remove
with zipfile.ZipFile(file="update.zip") as zip_file:
# Get the total size of the zip file

uncompress_size = sum((file.file_size for file in zip_file.infolist()))
# Initialize the extracted size

label.configure(text="Extracting File...")
time.sleep(0.5)
extracted_size = 0
percentageshow.configure("0%")
progress.set(0)
# Loop over each file

for file in zip_file.infolist():
# Extract each file

zip_file.extract(member=file)
# Update the extracted size

extracted_size += file.file_size
# Calculate the percentage of completion

progressextract = extracted_size / uncompress_size
# Update the progress bar value

progress.set(progressextract)
progressextractshow = round(progressextract * 100, 8)
percentageshow.configure(text = f"{progressextractshow}%")
# Update the app window

root.update_idletasks()
time.sleep(0.9)
os.remove("update.zip")
# Show a success message using message["text"]

updatebtn.configure(state=ctk.DISABLED)
updatebtn.configure(fg_color="gray")
checkforupdates.configure(state=ctk.NORMAL)
Expand All @@ -172,17 +169,17 @@ def update():
resultcheck = check_version()


# Create the GUI using ctk.CTk and ctk.geometry

root = ctk.CTk()
root.title("Updater v2.0")
root.geometry("320x400")

root.resizable(False, False)
# Set the appearance mode and color theme using ctk.set_appearance_mode and ctk.set_color_theme

ctk.set_appearance_mode("dark")
ctk.set_default_color_theme("green")

# Create the widgets using ctk.Label, ctk.Button, ctk.Progressbar, and ctk.pack

label = ctk.CTkLabel(root, text="Checking for Updates...")
label.grid(row=0, column=0, sticky=ctk.N, columnspan=2)

Expand All @@ -203,13 +200,22 @@ def update():

def check_updatemanual():
resultcheck = check_version()
print(resultcheck)
label.configure(text="Checking for Updates...")
time.sleep(2)
if resultcheck == True:
label.configure(text="You are up to date!")
updatebtn.configure(state=ctk.DISABLED)
updatebtn.configure(fg_color="gray")
else:
with requests.get(
f"https://api.github.com/repos/{USERNAME}/{REPO}/releases/latest",
auth=(USERNAME, API_KEY),
) as response:
response.raise_for_status()
latest_tag = response.json()["tag_name"]
label.configure(text=f"There is an update available! ({latest_tag})")
updatebtn.configure(state=ctk.NORMAL)
updatebtn.configure(fg_color="green")


checkforupdates = ctk.CTkButton(
Expand All @@ -222,7 +228,7 @@ def check_updatemanual():
checkforupdates.grid(row=2, column=1, sticky='nsew', padx=10, pady=5)


# Check for updates and enable the button if needed using an if-else statement and button["state"]


if resultcheck == True:
label.configure(text="You are up to date!")
Expand All @@ -240,42 +246,32 @@ def check_updatemanual():
updatebtn.configure(fg_color="green")


#Changelog Show here

changeloglabel = ctk.CTkLabel(root, text="Changelog")
changeloglabel.grid(row=3, column=0, sticky=ctk.W, padx=15, pady=5)

# Create a CTk textbox

textbox = ctk.CTkTextbox(root, width=300, height=250)
textbox.grid(row=4, column=0, columnspan=2, pady=5)


url = f"https://api.github.com/repos/{USERNAME}/{REPO}/releases/latest"
# Define a function to display the latest release

headers = {"Authorization": f"token {API_KEY}"}
response = requests.get(url, headers=headers)

checkchangelog = check_version()
if checkchangelog == False:
if response.status_code == 200:
# Parse the JSON response
data = response.json()

# Extract the information you need
tag_name = data["tag_name"]
release_name = data["name"]
release_date = data["published_at"]
changelog = data["body"]

# Set the text of the textbox widget to the changelog
textbox.insert(ctk.END, changelog)

# Start the main loop of the window
else:
# Handle the error
print(f"Error: {response.status_code}")
else:
textbox.insert(ctk.END, "Your Up To Date! Nothing to See Here..")


textbox.configure(state="disabled")

# Start the main loop using root.mainloop
root.mainloop()

0 comments on commit 73eb0cf

Please sign in to comment.