mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-04 20:43:04 +00:00
fix client: download fallback to github release client
+ add fallback release version data to version.txt + move classproperty class to utils + update Dockerfile to install from source using pip install + move version info to Metadata class in settings.py
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
from dataclasses import asdict
|
||||
from importlib import metadata
|
||||
from typing import Any
|
||||
from flask_openapi3 import Tag
|
||||
from flask_openapi3 import APIBlueprint
|
||||
@@ -9,6 +8,7 @@ from swingmusic.api.auth import admin_required
|
||||
from swingmusic.db.userdata import PluginTable
|
||||
from swingmusic.lib.index import index_everything
|
||||
from swingmusic.config import UserConfig
|
||||
from swingmusic.settings import Metadata
|
||||
from swingmusic.utils.auth import get_current_userid
|
||||
|
||||
bp_tag = Tag(name="Settings", description="Customize stuff")
|
||||
@@ -102,7 +102,11 @@ def get_all_settings():
|
||||
config[key] = sorted(list(value))
|
||||
|
||||
config["plugins"] = [p for p in PluginTable.get_all()]
|
||||
config["version"] = metadata.version("swingmusic")
|
||||
config["version"] = Metadata.version
|
||||
|
||||
if config["version"] == "0.0.0":
|
||||
# fallback to version.txt (useful for docker builds)
|
||||
config["version"] = open("version.txt", "r").read().strip()
|
||||
|
||||
# only return lastfmSessionKey for the current user
|
||||
current_user = get_current_userid()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
from importlib import metadata
|
||||
import datetime as dt
|
||||
import pathlib
|
||||
import logging
|
||||
@@ -13,7 +12,7 @@ from flask_jwt_extended import JWTManager, create_access_token, get_jwt, get_jwt
|
||||
from swingmusic import api as swing_api
|
||||
from swingmusic.config import UserConfig
|
||||
from swingmusic.db.userdata import UserTable
|
||||
from swingmusic.settings import Paths
|
||||
from swingmusic.settings import Metadata, Paths
|
||||
from swingmusic.utils.paths import get_client_files_extensions
|
||||
|
||||
from swingmusic.api.plugins import lyrics as lyrics_plugin
|
||||
@@ -102,7 +101,7 @@ def load_plugins(web: OpenAPI):
|
||||
|
||||
api_info = Info(
|
||||
title="Swing Music",
|
||||
version=f"v{metadata.version('swingmusic')}",
|
||||
version=f"v{Metadata.version}",
|
||||
description="The REST API exposed by your Swing Music server",
|
||||
)
|
||||
|
||||
|
||||
+46
-29
@@ -16,7 +16,9 @@ from pathlib import Path
|
||||
import os
|
||||
import logging
|
||||
import requests
|
||||
from importlib import resources as imres
|
||||
from importlib import metadata, resources as imres
|
||||
|
||||
from swingmusic.utils import classproperty
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -45,9 +47,7 @@ class AssetHandler:
|
||||
Handles all assets configuration
|
||||
"""
|
||||
|
||||
CLIENT_RELEASES_URL = (
|
||||
"https://api.github.com/repos/swingmx/swingmusic/releases/latest"
|
||||
)
|
||||
RELEASES_URL = "https://api.github.com/repos/swingmx/swingmusic/releases"
|
||||
|
||||
@staticmethod
|
||||
def copy_assets_dir():
|
||||
@@ -104,30 +104,37 @@ class AssetHandler:
|
||||
Downloads the latest supported client from Github
|
||||
and places it in the swingmusic client folder.
|
||||
"""
|
||||
path = Paths().config_parent / "client"
|
||||
log.error("Default client not found. Downloading from GitHub ...")
|
||||
path = Paths().client_path
|
||||
|
||||
try:
|
||||
answer = requests.get(AssetHandler.CLIENT_RELEASES_URL).json()
|
||||
# INFO: downlaod the current version of the client from GitHub
|
||||
releases = requests.get(AssetHandler.RELEASES_URL).json()
|
||||
|
||||
for asset in answer["assets"]:
|
||||
if asset["name"] == "client.zip":
|
||||
# download and convert client
|
||||
client = requests.get(asset["browser_download_url"])
|
||||
mem_file = io.BytesIO(client.content)
|
||||
file = zipfile.ZipFile(mem_file)
|
||||
# INFO: find the release for the current version
|
||||
for release in releases:
|
||||
if release["tag_name"] == f"v{Metadata.version}":
|
||||
# INFO: find the client.zip asset
|
||||
for asset in release["assets"]:
|
||||
if asset["name"] == "client.zip":
|
||||
# download and extract client
|
||||
clientzip = requests.get(asset["browser_download_url"])
|
||||
mem_file = io.BytesIO(clientzip.content)
|
||||
file = zipfile.ZipFile(mem_file)
|
||||
|
||||
# create new dir for extraction
|
||||
log.info(f"Storing client in '{path.as_posix()}'.")
|
||||
with tempfile.TemporaryDirectory() as temp_folder:
|
||||
file.extractall(temp_folder)
|
||||
# create new dir for extraction
|
||||
with tempfile.TemporaryDirectory() as temp_folder:
|
||||
file.extractall(temp_folder)
|
||||
|
||||
shutil.copytree(
|
||||
Path(temp_folder) / "client",
|
||||
path,
|
||||
copy_function=shutil.copy2,
|
||||
dirs_exist_ok=True,
|
||||
)
|
||||
shutil.copytree(
|
||||
Path(temp_folder) / "client",
|
||||
path,
|
||||
copy_function=shutil.copy2,
|
||||
dirs_exist_ok=True,
|
||||
)
|
||||
|
||||
log.info("Client downloaded successfully.")
|
||||
break
|
||||
break
|
||||
|
||||
except (
|
||||
@@ -140,12 +147,6 @@ class AssetHandler:
|
||||
exc_info=e,
|
||||
)
|
||||
return False
|
||||
except requests.exceptions.InvalidJSONError as e:
|
||||
log.error(
|
||||
"Client could not be downloaded from releases. JSON ERROR",
|
||||
exc_info=e,
|
||||
)
|
||||
return False
|
||||
except zipfile.BadZipfile as e:
|
||||
log.error("Client could not be unpacked. ZIP ERROR", exc_info=e)
|
||||
return False
|
||||
@@ -155,8 +156,9 @@ class AssetHandler:
|
||||
"""
|
||||
Runs on startup to ensure the default client is present.
|
||||
"""
|
||||
|
||||
extracted = True
|
||||
client_path = Paths().client_path
|
||||
extracted = False
|
||||
|
||||
if not client_path.exists() or not (client_path / "index.html").exists():
|
||||
extracted = cls.extract_default_client(Paths().config_dir)
|
||||
@@ -504,3 +506,18 @@ class TCOLOR:
|
||||
BOLD = "\033[1m"
|
||||
UNDERLINE = "\033[4m"
|
||||
# credits: https://stackoverflow.com/a/287944
|
||||
|
||||
|
||||
class Metadata:
|
||||
"""
|
||||
Contains metadata for the application.
|
||||
"""
|
||||
|
||||
@classproperty
|
||||
def version(self) -> str:
|
||||
version = metadata.version("swingmusic")
|
||||
|
||||
if version == "0.0.0":
|
||||
return open("version.txt", "r").read().strip()
|
||||
|
||||
return version
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
from swingmusic.settings import TCOLOR, Paths
|
||||
from swingmusic.settings import TCOLOR, Metadata, Paths
|
||||
from swingmusic.utils.network import get_ip
|
||||
from importlib import metadata
|
||||
|
||||
|
||||
def log_startup_info(host: str, port: int):
|
||||
print(f"{TCOLOR.HEADER}Swing Music v{metadata.version('swingmusic')} {TCOLOR.ENDC}")
|
||||
print(f"{TCOLOR.HEADER}Swing Music v{Metadata.version} {TCOLOR.ENDC}")
|
||||
|
||||
addresses = [host]
|
||||
|
||||
@@ -14,8 +13,6 @@ def log_startup_info(host: str, port: int):
|
||||
|
||||
print("Server running on:\n")
|
||||
for address in addresses:
|
||||
print(
|
||||
f"{TCOLOR.OKGREEN}http://{address}:{port}{TCOLOR.ENDC}"
|
||||
)
|
||||
print(f"{TCOLOR.OKGREEN}http://{address}:{port}{TCOLOR.ENDC}")
|
||||
|
||||
print(f"\n{TCOLOR.YELLOW}Data folder: {Paths().config_dir}{TCOLOR.ENDC}\n")
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import socket
|
||||
import sys
|
||||
from swingmusic import app_builder
|
||||
from swingmusic.crons import start_cron_jobs
|
||||
from swingmusic.plugins.register import register_plugins
|
||||
|
||||
@@ -6,6 +6,7 @@ from typing import Callable, Iterable
|
||||
from swingmusic.db.libdata import TrackTable
|
||||
|
||||
from swingmusic.models import Track
|
||||
from swingmusic.utils import classproperty
|
||||
from swingmusic.utils.auth import get_current_userid
|
||||
from swingmusic.utils.remove_duplicates import remove_duplicates
|
||||
|
||||
@@ -61,14 +62,7 @@ class TrackGroup:
|
||||
return len(self.tracks)
|
||||
|
||||
|
||||
class classproperty(property):
|
||||
"""
|
||||
A class property decorator.
|
||||
"""
|
||||
|
||||
def __get__(self, owner_self, owner_cls):
|
||||
if self.fget:
|
||||
return self.fget(owner_cls)
|
||||
|
||||
|
||||
class TrackStore:
|
||||
|
||||
@@ -19,3 +19,13 @@ def flatten(list_: Iterable[list[T]]) -> list[T]:
|
||||
Flattens a list of lists into a single list.
|
||||
"""
|
||||
return [item for sublist in list_ for item in sublist]
|
||||
|
||||
|
||||
class classproperty(property):
|
||||
"""
|
||||
A class property decorator.
|
||||
"""
|
||||
|
||||
def __get__(self, owner_self, owner_cls):
|
||||
if self.fget:
|
||||
return self.fget(owner_cls)
|
||||
Reference in New Issue
Block a user