Skip to content

Commit

Permalink
fix(updater.py): update check fyxed with regular expression to search…
Browse files Browse the repository at this point in the history
… for a version number in the format major.minor.patch inside release string
  • Loading branch information
MRColorR committed Sep 19, 2024
1 parent cc3ff19 commit f67bbd8
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 28 deletions.
2 changes: 1 addition & 1 deletion config/m4b-config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"project": {
"project_version": "4.3.5",
"project_version": "4.3.6",
"compose_project_name": "money4band",
"ds_project_server_url": "https://discord.com/invite/Fq8eeazBAD"
},
Expand Down
75 changes: 48 additions & 27 deletions utils/updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import json
import logging
from datetime import datetime
import re
from colorama import Fore, Back, Style, just_fix_windows_console

script_dir = os.path.dirname(os.path.abspath(__file__))
Expand All @@ -14,29 +15,27 @@
from utils.loader import load_json_config


class Version():
class Version:
"""
A class to represent a version number in the format major.minor.patch.
Supports comparison operators (==, !=, <, >, <=, >=) and can be created from a string or individual components.
"""

version_regex = re.compile(
r'(?:(?:v|version)?\s*)?(\d+)\.(\d+)\.(\d+)', re.IGNORECASE)

@staticmethod
def from_string(version_str: str):
"""
Create a Version object from a string in the format major.minor.patch.
Create a Version object by extracting version numbers from a string.
"""
version_str = version_str.strip().lower().replace('v.', '').replace('v', '')
version_parts = version_str.split('.')
if len(version_parts) != 3:
raise ValueError("Invalid version string format")
try:
major = int(version_parts[0])
minor = int(version_parts[1])
patch = int(version_parts[2])
except ValueError:
raise ValueError("Invalid version string format")
return Version(major, minor, patch)

version_str = version_str.strip()
match = Version.version_regex.search(version_str)
if not match:
raise ValueError(f"Invalid version string format: '{version_str}'")
major, minor, patch = match.groups()
return Version(int(major), int(minor), int(patch))

def __init__(self, major: int, minor: int, patch: int):
self.major = major
self.minor = minor
Expand All @@ -49,32 +48,42 @@ def __repr__(self):
return str(self)

def __eq__(self, other):
if not isinstance(other, Version):
return False
return (
self.major == other.major
and self.minor == other.minor
and self.patch == other.patch
)

def __lt__(self, other):
if not isinstance(other, Version):
return NotImplemented
if self.major < other.major:
return True
elif self.major > other.major:
return False
else: # major is equal
else: # major is equal
if self.minor < other.minor:
return True
elif self.minor > other.minor:
return False
else: # minor is equal
else: # minor is equal
return self.patch < other.patch

def __gt__(self, other):
if not isinstance(other, Version):
return NotImplemented
return not self.__lt__(other) and not self.__eq__(other)

def __le__(self, other):
if not isinstance(other, Version):
return NotImplemented
return self.__lt__(other) or self.__eq__(other)

def __ge__(self, other):
if not isinstance(other, Version):
return NotImplemented
return not self.__lt__(other)

def __ne__(self, other):
Expand All @@ -89,19 +98,23 @@ def get_latest_releases(count: int = 5) -> List[Dict]:
with urllib.request.urlopen(url) as response:
data = response.read().decode()
releases = json.loads(data)
releases = releases[:count]
stripped_releases = []
for release in releases:
if release['prerelease']:
continue
if release['draft']:
continue
name = release['name']
if name == '':
if not name:
name = release['tag_name']
if name == '':
if not name:
continue
try:
version = Version.from_string(name)
except ValueError:
logging.warning(
f"Skipping release with unparseable version: '{name}'")
continue
version = Version.from_string(name)
url = release['html_url']
published_at = release['published_at']
published_at = datetime.strptime(
Expand All @@ -112,7 +125,9 @@ def get_latest_releases(count: int = 5) -> List[Dict]:
'url': url,
'published_at': published_at
})
return stripped_releases
stripped_releases.sort(
key=lambda x: x['version'], reverse=True)
return stripped_releases[:count]
except urllib.error.HTTPError as e:
raise Exception(f"Failed to fetch releases. HTTP Error: {e.code}")
except urllib.error.URLError as e:
Expand All @@ -127,22 +142,28 @@ def check_update_available(m4b_config_path_or_dict: str | dict) -> None:
just_fix_windows_console()
m4b_config = load_json_config(m4b_config_path_or_dict)
try:
current_version = m4b_config.get('project',{}).get('project_version', "0.0.0")
current_version = Version.from_string(current_version)
latest_release = get_latest_releases()
latest_release.sort(key=lambda x: x['version'], reverse=True)
latest_release = latest_release[0]
current_version_str = m4b_config.get('project', {}).get(
'project_version', "0.0.0")
current_version = Version.from_string(current_version_str)
latest_releases = get_latest_releases()
if not latest_releases:
print(f"{Fore.YELLOW}No releases found.")
return
latest_release = latest_releases[0]
if current_version < latest_release['version']:
print(f"{Fore.YELLOW}New version available: {latest_release['version']}, published at {latest_release['published_at']}")
print(
f"{Fore.YELLOW}New version available: {latest_release['version']}, published at {latest_release['published_at']}")
print(f"Download URL: {Style.RESET_ALL}{latest_release['url']}")
except Exception as e:
logging.error(e)
print(f"Error checking for updates: {e}")


def main():
releases = get_latest_releases()
for release in releases:
print(release)


if __name__ == '__main__':
main()

0 comments on commit f67bbd8

Please sign in to comment.