modularize src

+ merge main.py and manage.py
+ move start logic to swingmusic/__main__.py
+ add a run.py on the project root
This commit is contained in:
cwilvx
2025-05-25 20:35:54 +03:00
parent 76fc97e088
commit 86fabcd5e3
171 changed files with 658 additions and 627 deletions
+1 -1
View File
@@ -107,7 +107,7 @@ jobs:
# python -m poetry install # python -m poetry install
- name: Build server - name: Build server
run: | run: |
python main.py --build python run.py --build
env: env:
SWINGMUSIC_APP_VERSION: ${{ inputs.tag }} SWINGMUSIC_APP_VERSION: ${{ inputs.tag }}
- name: Rename Unix binary - name: Rename Unix binary
+1 -1
View File
@@ -35,4 +35,4 @@ RUN pip install bjoern
ARG app_version ARG app_version
ENV SWINGMUSIC_APP_VERSION=$app_version ENV SWINGMUSIC_APP_VERSION=$app_version
ENTRYPOINT ["python", "main.py", "--host", "0.0.0.0", "--config", "/config"] ENTRYPOINT ["python", "run.py", "--host", "0.0.0.0", "--config", "/config"]
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2023 Mungai Njoroge Copyright (c) 2025 Mungai Njoroge
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+52 -1
View File
@@ -122,12 +122,63 @@ services:
restart: unless-stopped restart: unless-stopped
``` ```
### Contributing ### Contributing and Development
Swing Music is looking for contributors. If you're interested, please join us at the [Swing Music Community](https://t.me/+9n61PFcgKhozZDE0) group on Telegram. For more information, take a look at https://github.com/swing-opensource/swingmusic/issues/186. Swing Music is looking for contributors. If you're interested, please join us at the [Swing Music Community](https://t.me/+9n61PFcgKhozZDE0) group on Telegram. For more information, take a look at https://github.com/swing-opensource/swingmusic/issues/186.
[**CONTRIBUTING GUIDELINES**](.github/contributing.md). [**CONTRIBUTING GUIDELINES**](.github/contributing.md).
> [!TIP]
> This project runs on Python 3.11 or newer and uses [uv](https://docs.astral.sh/uv) to manage dependencies. Please [install uv](https://docs.astral.sh/uv/getting-started/installation/) before continuing for an easy setup.
To set up this project on your computer follow the following steps:
```sh
# 1. Fork the project
git clone https://github.com/swingmx/swingmusic.git
# or via SSH
git clone git@github.com:swingmx/swingmusic.git
```
```sh
# 2. Install dependencies
uv sync
```
```sh
# 3. Install wsgi server
# If you are on Windows, install waitress:
uv add waitress
# If you are on Unix, install bjoern:
uv add bjoern
```
> [!TIP]
> The `libev` package is needed on Linux and MacOS. You can install it on other system as shown:
>
> ```sh
> # Arch Linux
> pacman -S libev
>
> # Fedora, CentOS
> dnf install libev-devel
>
> # MacOS
> brew install libev
> ```
```sh
# 4. Run the program
uv run python run.py
```
### License ### License
This software is provided to you with terms stated in the MIT License. Read the full text in the `LICENSE` file located at the root of this repository. This software is provided to you with terms stated in the MIT License. Read the full text in the `LICENSE` file located at the root of this repository.
+1 -1
View File
@@ -44,7 +44,7 @@ cd ../swingmusic
# poetry install # poetry install
# Swing gives error if this is not set. Set to version of repo you cloned. # Swing gives error if this is not set. Set to version of repo you cloned.
export SWINGMUSIC_APP_VERSION="TAG" export SWINGMUSIC_APP_VERSION="TAG"
python main.py --build python run.py --build
# rename binary # rename binary
mv dist/swingmusic dist/swingmusic_linux_arm64 mv dist/swingmusic dist/swingmusic_linux_arm64
View File
-19
View File
@@ -1,19 +0,0 @@
#!/bin/bash
# REVIEW Above: bash is way more compatible than other shells
# builds the latest version of the client and server
# REVIEW These are not useful if you dont have the source code
#cd ../swingmusic-client
#yarn build --outDir ../swingmusic/client
#../swingmusic
# REVIEW Cleaning up
rm -rf build dist
# REVIEW Install poetry & requirements
poetry || pip install poetry
poetry install --no-root
# Build the app
poetry run python manage.py --build
-16
View File
@@ -1,16 +0,0 @@
#!/bin/bash
# REVIEW Above: bash is way more compatible than other shells
# builds the latest version of the client and server
# NOTE Changes directory to the webclient directory and builds it
cd ../swingmusic-client || exit # REVIEW Failsafe exit
yarn build --outDir ../swingmusic/client
cd ../swingmusic || exit # REVIEW Failsafe exit
# REVIEW Optional cleaning up
# rm -rf build dist
# REVIEW Install poetry & requirements
# Build the app
poetry run python manage.py --build
-80
View File
@@ -1,80 +0,0 @@
import os
import sys
import click
import pathlib
import multiprocessing
from app.arg_handler import handle_build, handle_password_reset
from app.utils.filesystem import get_home_res_path
from app.utils.xdg_utils import get_xdg_config_dir
from manage import create_app
def version(*args, **kwargs):
if not args[2]:
return
path = get_home_res_path("version.txt")
if not path:
click.echo("Version file not found.")
sys.exit(1)
with open(path, "r") as f:
version = f.read()
click.echo(version)
sys.exit(0)
@click.command(options_metavar="<options>", context_settings={"show_default": True})
@click.option(
"--build",
default=False,
help="Build the project.",
is_eager=True,
callback=handle_build,
is_flag=True,
)
@click.option("--host", default="0.0.0.0", help="Host to run the app on.")
@click.option("--port", default=1970, help="HTTP port to run the app on.")
@click.option(
"--config",
default=lambda: get_xdg_config_dir(),
show_default="XDG_CONFIG_HOME",
help="Path to the config file.",
type=click.Path(
exists=True,
file_okay=False,
dir_okay=True,
writable=True,
resolve_path=True,
allow_dash=False,
path_type=pathlib.Path,
),
)
@click.option(
"--password-reset",
is_flag=True,
help="Reset the password.",
is_eager=True,
callback=handle_password_reset,
)
@click.option(
"--version",
is_flag=True,
default=False,
callback=version,
help="Show the version and exit",
is_eager=True,
)
def run(*args, **kwargs):
# INFO: Set the config dir as an environment variable
os.environ["SWINGMUSIC_XDG_CONFIG_DIR"] = str(
pathlib.Path(kwargs["config"]).resolve()
)
create_app(kwargs["host"], kwargs["port"], kwargs["config"])
if __name__ == "__main__":
multiprocessing.freeze_support()
multiprocessing.set_start_method("spawn")
run()
+1 -2
View File
@@ -1,6 +1,6 @@
[project] [project]
name = "swingmusic" name = "swingmusic"
version = "2.0.2" version = "2.0.6"
description = "Swing Music" description = "Swing Music"
readme = "README.md" readme = "README.md"
requires-python = ">=3.11, <3.12" requires-python = ">=3.11, <3.12"
@@ -31,7 +31,6 @@ dependencies = [
"pillow>=11.1.0", "pillow>=11.1.0",
"flask-openapi3==3.0.2", "flask-openapi3==3.0.2",
"rapidfuzz==3.11.0", "rapidfuzz==3.11.0",
"waitress>=3.0.2",
"pendulum>=3.0.0", "pendulum>=3.0.0",
"bjoern>=3.2.2", "bjoern>=3.2.2",
] ]
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
poetry run python manage.py
+9
View File
@@ -0,0 +1,9 @@
# Launcher script
import multiprocessing
import swingmusic.__main__ as app
if __name__ == "__main__":
multiprocessing.freeze_support()
multiprocessing.set_start_method("spawn")
app.run()
+114 -16
View File
@@ -1,12 +1,12 @@
"""
This file is used to run the application.
"""
import os import os
import sys
import click
import pathlib
import logging import logging
import mimetypes import mimetypes
import setproctitle import setproctitle
from pathlib import Path import multiprocessing
from flask_jwt_extended import ( from flask_jwt_extended import (
create_access_token, create_access_token,
@@ -18,19 +18,58 @@ from flask_jwt_extended import (
from datetime import datetime, timezone from datetime import datetime, timezone
from flask import Response, request from flask import Response, request
from app import settings from swingmusic import settings
from app.api import create_api from swingmusic.api import create_api
from app.crons import start_cron_jobs from swingmusic.crons import start_cron_jobs
from app.utils.threading import background from swingmusic.utils.threading import background
from app.setup import load_into_mem, run_setup from swingmusic.setup import load_into_mem, run_setup
from app.plugins.register import register_plugins from swingmusic.plugins.register import register_plugins
from app.start_info_logger import log_startup_info from swingmusic.utils.xdg_utils import get_xdg_config_dir
from app.utils.filesystem import get_home_res_path from swingmusic.start_info_logger import log_startup_info
from app.utils.paths import getClientFilesExtensions from swingmusic.utils.filesystem import get_home_res_path
from swingmusic.utils.paths import getClientFilesExtensions
from swingmusic.arg_handler import handle_build, handle_password_reset
def print_version(*args, **kwargs):
"""
Prints the version of the application.
"""
if not args[2]:
return
path = get_home_res_path("version.txt")
if not path:
click.echo("Version file not found.")
sys.exit(1)
with open(path, "r") as f:
version = f.read()
click.echo(version)
sys.exit(0)
def create_app(host: str, port: int, config: Path): def start_swingmusic(host: str, port: int):
# settings.Paths.set_config_dir(config) """
Creates and starts the Flask application server for Swing Music.
This function sets up the Flask application with all necessary
configurations, including static file handling, authentication middleware, and
server setup, then runs it. It also sets up background tasks and cron jobs.
Args:
host (str): The host address to bind the server to (e.g., 'localhost' or '0.0.0.0')
port (int): The port number to run the server on
Note:
The application uses either bjoern or waitress as the WSGI server,
depending on availability. It also includes JWT authentication,
static file serving with gzip compression support, and automatic
token refresh functionality.
"""
# Example: Setting up dirs, database, and loading stuff into memory.
# TIP: Be careful with the order of the setup functions.
# Load mimetypes for the web client's static files # Load mimetypes for the web client's static files
# Loading mimetypes should happen automatically but # Loading mimetypes should happen automatically but
@@ -196,3 +235,62 @@ def create_app(host: str, port: int, config: Path):
ipv6=True, ipv6=True,
ipv4=True, ipv4=True,
) )
@click.command(options_metavar="<options>", context_settings={"show_default": True})
@click.option(
"--build",
default=False,
help="Build the project.",
is_eager=True,
callback=handle_build,
is_flag=True,
)
@click.option("--host", default="0.0.0.0", help="Host to run the app on.")
@click.option("--port", default=1970, help="HTTP port to run the app on.")
@click.option(
"--config",
default=lambda: get_xdg_config_dir(),
show_default="XDG_CONFIG_HOME",
help="Path to the config file.",
type=click.Path(
exists=True,
file_okay=False,
dir_okay=True,
writable=True,
resolve_path=True,
allow_dash=False,
path_type=pathlib.Path,
),
)
@click.option(
"--password-reset",
is_flag=True,
help="Reset the password.",
is_eager=True,
callback=handle_password_reset,
)
@click.option(
"--version",
is_flag=True,
default=False,
callback=print_version,
help="Show the version and exit",
is_eager=True,
)
def run(*args, **kwargs):
"""
Swing Music entry point. All commandline arguments are handled
here by the click decorators and configuration.
"""
# INFO: Set the config dir as an environment variable
os.environ["SWINGMUSIC_XDG_CONFIG_DIR"] = str(
pathlib.Path(kwargs["config"]).resolve()
)
start_swingmusic(kwargs["host"], kwargs["port"])
if __name__ == "__main__":
multiprocessing.freeze_support()
multiprocessing.set_start_method("spawn")
run()
@@ -9,13 +9,13 @@ from flask_compress import Compress
from flask_openapi3 import Info from flask_openapi3 import Info
from flask_openapi3 import OpenAPI from flask_openapi3 import OpenAPI
from flask_jwt_extended import JWTManager from flask_jwt_extended import JWTManager
from app.config import UserConfig from swingmusic.config import UserConfig
from app.db.userdata import UserTable from swingmusic.db.userdata import UserTable
from app.settings import Info as AppInfo from swingmusic.settings import Info as AppInfo
from .plugins import lyrics as lyrics_plugin from .plugins import lyrics as lyrics_plugin
from .plugins import mixes as mixes_plugin from .plugins import mixes as mixes_plugin
from app.api import ( from swingmusic.api import (
album, album,
artist, artist,
collections, collections,
+13 -13
View File
@@ -9,20 +9,20 @@ import random
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from flask_openapi3 import Tag from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
from app.api.apischemas import AlbumHashSchema, AlbumLimitSchema, ArtistHashSchema from swingmusic.api.apischemas import AlbumHashSchema, AlbumLimitSchema, ArtistHashSchema
from app.config import UserConfig from swingmusic.config import UserConfig
from app.db.userdata import SimilarArtistTable from swingmusic.db.userdata import SimilarArtistTable
from app.models.album import Album from swingmusic.models.album import Album
from app.settings import Defaults from swingmusic.settings import Defaults
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.artists import ArtistStore from swingmusic.store.artists import ArtistStore
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
from app.utils.hashing import create_hash from swingmusic.utils.hashing import create_hash
from app.lib.albumslib import sort_by_track_no from swingmusic.lib.albumslib import sort_by_track_no
from app.serializers.album import serialize_for_card_many from swingmusic.serializers.album import serialize_for_card_many
from app.serializers.track import serialize_tracks from swingmusic.serializers.track import serialize_tracks
from app.utils.stats import get_track_group_stats from swingmusic.utils.stats import get_track_group_stats
bp_tag = Tag(name="Album", description="Single album") bp_tag = Tag(name="Album", description="Single album")
@@ -4,7 +4,7 @@ Reusable Pydantic basic schemas for the API
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from app.settings import Defaults from swingmusic.settings import Defaults
class AlbumHashSchema(BaseModel): class AlbumHashSchema(BaseModel):
+11 -11
View File
@@ -11,25 +11,25 @@ from typing import Any
from flask_openapi3 import APIBlueprint, Tag from flask_openapi3 import APIBlueprint, Tag
from pydantic import Field from pydantic import Field
from app.api.apischemas import ( from swingmusic.api.apischemas import (
AlbumLimitSchema, AlbumLimitSchema,
ArtistHashSchema, ArtistHashSchema,
ArtistLimitSchema, ArtistLimitSchema,
TrackLimitSchema, TrackLimitSchema,
) )
from app.config import UserConfig from swingmusic.config import UserConfig
from app.db.userdata import SimilarArtistTable from swingmusic.db.userdata import SimilarArtistTable
from app.lib.sortlib import sort_tracks from swingmusic.lib.sortlib import sort_tracks
from app.serializers.album import serialize_for_card_many from swingmusic.serializers.album import serialize_for_card_many
from app.serializers.artist import serialize_for_cards, serialize_for_card from swingmusic.serializers.artist import serialize_for_cards, serialize_for_card
from app.serializers.track import serialize_track from swingmusic.serializers.track import serialize_track
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.artists import ArtistStore from swingmusic.store.artists import ArtistStore
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
from app.utils.stats import get_track_group_stats from swingmusic.utils.stats import get_track_group_stats
bp_tag = Tag(name="Artist", description="Single artist") bp_tag = Tag(name="Artist", description="Single artist")
api = APIBlueprint("artist", __name__, url_prefix="/artist", abp_tags=[bp_tag]) api = APIBlueprint("artist", __name__, url_prefix="/artist", abp_tags=[bp_tag])
+3 -3
View File
@@ -14,9 +14,9 @@ from pydantic import BaseModel, Field
from flask_openapi3 import Tag from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
from app.db.userdata import UserTable from swingmusic.db.userdata import UserTable
from app.utils.auth import check_password, hash_password from swingmusic.utils.auth import check_password, hash_password
from app.config import UserConfig from swingmusic.config import UserConfig
bp_tag = Tag(name="Auth", description="Authentication stuff") bp_tag = Tag(name="Auth", description="Authentication stuff")
api = APIBlueprint("auth", __name__, url_prefix="/auth", abp_tags=[bp_tag]) api = APIBlueprint("auth", __name__, url_prefix="/auth", abp_tags=[bp_tag])
@@ -7,13 +7,13 @@ import shutil
from time import time from time import time
from flask_openapi3 import Tag from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
from app.api.auth import admin_required from swingmusic.api.auth import admin_required
from app.db.userdata import FavoritesTable, PlaylistTable, ScrobbleTable from swingmusic.db.userdata import FavoritesTable, PlaylistTable, ScrobbleTable
from app.lib.index import index_everything from swingmusic.lib.index import index_everything
from app.settings import Paths from swingmusic.settings import Paths
from datetime import datetime from datetime import datetime
from app.utils.dates import timestamp_to_time_passed from swingmusic.utils.dates import timestamp_to_time_passed
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from typing import Optional from typing import Optional
@@ -8,9 +8,9 @@ from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from app.db.userdata import CollectionTable from swingmusic.db.userdata import CollectionTable
from app.lib.pagelib import recover_page_items, remove_page_items, validate_page_items from swingmusic.lib.pagelib import recover_page_items, remove_page_items, validate_page_items
from app.utils.auth import get_current_userid from swingmusic.utils.auth import get_current_userid
bp_tag = Tag(name="Collections", description="Collections") bp_tag = Tag(name="Collections", description="Collections")
api = APIBlueprint( api = APIBlueprint(
@@ -1,7 +1,7 @@
from flask_openapi3 import Tag from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
from app.api.apischemas import AlbumHashSchema from swingmusic.api.apischemas import AlbumHashSchema
from app.store.albums import AlbumStore as Store from swingmusic.store.albums import AlbumStore as Store
bp_tag = Tag(name="Colors", description="Get item colors") bp_tag = Tag(name="Colors", description="Get item colors")
api = APIBlueprint("colors", __name__, url_prefix="/colors", abp_tags=[bp_tag]) api = APIBlueprint("colors", __name__, url_prefix="/colors", abp_tags=[bp_tag])
@@ -4,23 +4,23 @@ from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from app.api.apischemas import GenericLimitSchema from swingmusic.api.apischemas import GenericLimitSchema
from app.db.userdata import FavoritesTable from swingmusic.db.userdata import FavoritesTable
from app.lib.extras import get_extra_info from swingmusic.lib.extras import get_extra_info
from app.models import FavType from swingmusic.models import FavType
from app.settings import Defaults from swingmusic.settings import Defaults
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.artists import ArtistStore from swingmusic.store.artists import ArtistStore
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
from app.serializers.track import serialize_track, serialize_tracks from swingmusic.serializers.track import serialize_track, serialize_tracks
from app.serializers.artist import ( from swingmusic.serializers.artist import (
serialize_for_card as serialize_artist, serialize_for_card as serialize_artist,
serialize_for_cards, serialize_for_cards,
) )
from app.utils.dates import timestamp_to_time_passed from swingmusic.utils.dates import timestamp_to_time_passed
from app.serializers.album import serialize_for_card, serialize_for_card_many from swingmusic.serializers.album import serialize_for_card, serialize_for_card_many
bp_tag = Tag(name="Favorites", description="Your favorite items") bp_tag = Tag(name="Favorites", description="Your favorite items")
api = APIBlueprint("favorites", __name__, url_prefix="/favorites", abp_tags=[bp_tag]) api = APIBlueprint("favorites", __name__, url_prefix="/favorites", abp_tags=[bp_tag])
@@ -12,14 +12,14 @@ from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
from showinfm import show_in_file_manager from showinfm import show_in_file_manager
from app import settings from swingmusic import settings
from app.config import UserConfig from swingmusic.config import UserConfig
from app.db.libdata import TrackTable from swingmusic.db.libdata import TrackTable
from app.db.userdata import FavoritesTable, PlaylistTable from swingmusic.db.userdata import FavoritesTable, PlaylistTable
from app.lib.folderslib import get_files_and_dirs, get_folders from swingmusic.lib.folderslib import get_files_and_dirs, get_folders
from app.serializers.track import serialize_track, serialize_tracks from swingmusic.serializers.track import serialize_track, serialize_tracks
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
from app.utils.wintools import is_windows, win_replace_slash from swingmusic.utils.wintools import is_windows, win_replace_slash
tag = Tag(name="Folders", description="Get folders and tracks in a directory") tag = Tag(name="Folders", description="Get folders and tracks in a directory")
api = APIBlueprint("folder", __name__, url_prefix="/folder", abp_tags=[tag]) api = APIBlueprint("folder", __name__, url_prefix="/folder", abp_tags=[tag])
@@ -3,14 +3,14 @@ from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from datetime import datetime from datetime import datetime
from app.api.apischemas import GenericLimitSchema from swingmusic.api.apischemas import GenericLimitSchema
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.artists import ArtistStore from swingmusic.store.artists import ArtistStore
from app.serializers.album import serialize_for_card as serialize_album from swingmusic.serializers.album import serialize_for_card as serialize_album
from app.serializers.artist import serialize_for_card as serialize_artist from swingmusic.serializers.artist import serialize_for_card as serialize_artist
from app.utils import format_number from swingmusic.utils import format_number
from app.utils.dates import ( from swingmusic.utils.dates import (
create_new_date, create_new_date,
date_string_to_time_passed, date_string_to_time_passed,
seconds_to_time_string, seconds_to_time_string,
@@ -2,10 +2,10 @@ from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from app.api.apischemas import GenericLimitSchema from swingmusic.api.apischemas import GenericLimitSchema
from app.lib.home.recentlyadded import get_recently_added_items from swingmusic.lib.home.recentlyadded import get_recently_added_items
from app.lib.home.get_recently_played import get_recently_played from swingmusic.lib.home.get_recently_played import get_recently_played
from app.store.homepage import HomepageStore from swingmusic.store.homepage import HomepageStore
bp_tag = Tag(name="Home", description="Homepage items") bp_tag = Tag(name="Home", description="Homepage items")
api = APIBlueprint("home", __name__, url_prefix="/nothome", abp_tags=[bp_tag]) api = APIBlueprint("home", __name__, url_prefix="/nothome", abp_tags=[bp_tag])
@@ -5,10 +5,10 @@ from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from flask import send_from_directory from flask import send_from_directory
from app.settings import Defaults, Paths from swingmusic.settings import Defaults, Paths
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
from app.utils.threading import background from swingmusic.utils.threading import background
from PIL import Image from PIL import Image
bp_tag = Tag( bp_tag = Tag(
@@ -2,8 +2,8 @@ from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
from pydantic import Field from pydantic import Field
from app.api.apischemas import TrackHashSchema from swingmusic.api.apischemas import TrackHashSchema
from app.lib.lyrics import ( from swingmusic.lib.lyrics import (
get_lyrics, get_lyrics,
check_lyrics_file, check_lyrics_file,
get_lyrics_from_duplicates, get_lyrics_from_duplicates,
@@ -14,21 +14,21 @@ from pydantic import BaseModel, Field, GetCoreSchemaHandler
from flask_openapi3 import Tag from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint, FileStorage as _FileStorage from flask_openapi3 import APIBlueprint, FileStorage as _FileStorage
from app import models from swingmusic import models
from app.api.apischemas import GenericLimitSchema from swingmusic.api.apischemas import GenericLimitSchema
from app.db.userdata import PlaylistTable from swingmusic.db.userdata import PlaylistTable
from app.lib import playlistlib from swingmusic.lib import playlistlib
from app.lib.albumslib import sort_by_track_no from swingmusic.lib.albumslib import sort_by_track_no
from app.lib.home.recentlyadded import get_recently_added_playlist from swingmusic.lib.home.recentlyadded import get_recently_added_playlist
from app.lib.home.recentlyplayed import get_recently_played_playlist from swingmusic.lib.home.recentlyplayed import get_recently_played_playlist
from app.lib.sortlib import sort_tracks from swingmusic.lib.sortlib import sort_tracks
from app.models.playlist import Playlist from swingmusic.models.playlist import Playlist
from app.serializers.playlist import serialize_for_card from swingmusic.serializers.playlist import serialize_for_card
from app.serializers.track import serialize_tracks from swingmusic.serializers.track import serialize_tracks
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
from app.utils.dates import create_new_date, date_string_to_time_passed from swingmusic.utils.dates import create_new_date, date_string_to_time_passed
from app.settings import Paths from swingmusic.settings import Paths
tag = Tag(name="Playlists", description="Get and manage playlists") tag = Tag(name="Playlists", description="Get and manage playlists")
api = APIBlueprint("playlists", __name__, url_prefix="/playlists", abp_tags=[tag]) api = APIBlueprint("playlists", __name__, url_prefix="/playlists", abp_tags=[tag])
@@ -1,11 +1,11 @@
from flask_openapi3 import Tag from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from app.api.auth import admin_required from swingmusic.api.auth import admin_required
from app.config import UserConfig from swingmusic.config import UserConfig
from app.db.userdata import PluginTable from swingmusic.db.userdata import PluginTable
from app.plugins.lastfm import LastFmPlugin from swingmusic.plugins.lastfm import LastFmPlugin
from app.utils.auth import get_current_userid from swingmusic.utils.auth import get_current_userid
bp_tag = Tag(name="Plugins", description="Manage plugins") bp_tag = Tag(name="Plugins", description="Manage plugins")
api = APIBlueprint("plugins", __name__, url_prefix="/plugins", abp_tags=[bp_tag]) api = APIBlueprint("plugins", __name__, url_prefix="/plugins", abp_tags=[bp_tag])
@@ -1,12 +1,12 @@
from flask_openapi3 import Tag from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
from pydantic import Field from pydantic import Field
from app.api.apischemas import TrackHashSchema from swingmusic.api.apischemas import TrackHashSchema
from app.lib.lyrics import format_synced_lyrics from swingmusic.lib.lyrics import format_synced_lyrics
from app.plugins.lyrics import Lyrics from swingmusic.plugins.lyrics import Lyrics
from app.settings import Defaults from swingmusic.settings import Defaults
from app.utils.hashing import create_hash from swingmusic.utils.hashing import create_hash
bp_tag = Tag(name="Lyrics Plugin", description="Musixmatch lyrics plugin") bp_tag = Tag(name="Lyrics Plugin", description="Musixmatch lyrics plugin")
api = APIBlueprint( api = APIBlueprint(
@@ -3,10 +3,10 @@ from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from app.db.userdata import MixTable from swingmusic.db.userdata import MixTable
from app.plugins.mixes import MixesPlugin from swingmusic.plugins.mixes import MixesPlugin
from app.store.homepage import HomepageStore from swingmusic.store.homepage import HomepageStore
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
bp_tag = Tag(name="Mixes Plugin", description="Mixes plugin hehe") bp_tag = Tag(name="Mixes Plugin", description="Mixes plugin hehe")
@@ -3,30 +3,30 @@ from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
import pendulum import pendulum
from pydantic import Field, BaseModel from pydantic import Field, BaseModel
from app.api.apischemas import TrackHashSchema from swingmusic.api.apischemas import TrackHashSchema
from typing import Literal from typing import Literal
import locale import locale
from app.db.userdata import FavoritesTable, ScrobbleTable from swingmusic.db.userdata import FavoritesTable, ScrobbleTable
from app.lib.extras import get_extra_info from swingmusic.lib.extras import get_extra_info
from app.lib.recipes.recents import RecentlyPlayed from swingmusic.lib.recipes.recents import RecentlyPlayed
from app.models.album import Album from swingmusic.models.album import Album
from app.models.stats import StatItem from swingmusic.models.stats import StatItem
from app.models.track import Track from swingmusic.models.track import Track
from app.plugins.lastfm import LastFmPlugin from swingmusic.plugins.lastfm import LastFmPlugin
from app.serializers.artist import serialize_for_card from swingmusic.serializers.artist import serialize_for_card
from app.serializers.album import serialize_for_card as serialize_for_album_card from swingmusic.serializers.album import serialize_for_card as serialize_for_album_card
from app.serializers.track import serialize_track, serialize_tracks from swingmusic.serializers.track import serialize_track, serialize_tracks
from app.settings import Defaults from swingmusic.settings import Defaults
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.artists import ArtistStore from swingmusic.store.artists import ArtistStore
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
from app.utils.dates import ( from swingmusic.utils.dates import (
get_date_range, get_date_range,
get_duration_in_seconds, get_duration_in_seconds,
seconds_to_time_string, seconds_to_time_string,
) )
from app.utils.stats import ( from swingmusic.utils.stats import (
calculate_album_trend, calculate_album_trend,
calculate_artist_trend, calculate_artist_trend,
calculate_new_albums, calculate_new_albums,
@@ -8,12 +8,12 @@ from pydantic import Field
from flask_openapi3 import Tag from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
from app import models from swingmusic import models
from app.api.apischemas import GenericLimitSchema from swingmusic.api.apischemas import GenericLimitSchema
from app.lib import searchlib from swingmusic.lib import searchlib
from app.serializers.artist import serialize_for_cards from swingmusic.serializers.artist import serialize_for_cards
from app.settings import Defaults from swingmusic.settings import Defaults
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
tag = Tag(name="Search", description="Search for tracks, albums and artists") tag = Tag(name="Search", description="Search for tracks, albums and artists")
@@ -3,13 +3,13 @@ from typing import Any
from flask_openapi3 import Tag from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from app.api.auth import admin_required from swingmusic.api.auth import admin_required
from app.db.userdata import PluginTable from swingmusic.db.userdata import PluginTable
from app.lib.index import index_everything from swingmusic.lib.index import index_everything
from app.settings import Info from swingmusic.settings import Info
from app.config import UserConfig from swingmusic.config import UserConfig
from app.utils.auth import get_current_userid from swingmusic.utils.auth import get_current_userid
bp_tag = Tag(name="Settings", description="Customize stuff") bp_tag = Tag(name="Settings", description="Customize stuff")
api = APIBlueprint("settings", __name__, url_prefix="/notsettings", abp_tags=[bp_tag]) api = APIBlueprint("settings", __name__, url_prefix="/notsettings", abp_tags=[bp_tag])
@@ -12,12 +12,12 @@ from flask import send_file, request, Response, send_from_directory
from flask_openapi3 import APIBlueprint, Tag from flask_openapi3 import APIBlueprint, Tag
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
import werkzeug.wsgi import werkzeug.wsgi
from app.api.apischemas import TrackHashSchema from swingmusic.api.apischemas import TrackHashSchema
from app.lib.trackslib import get_silence_paddings from swingmusic.lib.trackslib import get_silence_paddings
from app.lib.transcoder import start_transcoding from swingmusic.lib.transcoder import start_transcoding
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
from app.utils.files import guess_mime_type from swingmusic.utils.files import guess_mime_type
bp_tag = Tag(name="File", description="Audio files") bp_tag = Tag(name="File", description="Audio files")
api = APIBlueprint("track", __name__, url_prefix="/file", abp_tags=[bp_tag]) api = APIBlueprint("track", __name__, url_prefix="/file", abp_tags=[bp_tag])
@@ -8,13 +8,13 @@ from getpass import getpass
import click import click
import PyInstaller.__main__ as bundler import PyInstaller.__main__ as bundler
from app import settings from swingmusic import settings
from app.db.userdata import UserTable from swingmusic.db.userdata import UserTable
from app.logger import log from swingmusic.logger import log
from app.setup.sqlite import setup_sqlite from swingmusic.setup.sqlite import setup_sqlite
from app.utils.auth import hash_password from swingmusic.utils.auth import hash_password
from app.utils.paths import getFlaskOpenApiPath from swingmusic.utils.paths import getFlaskOpenApiPath
from app.utils.wintools import is_windows from swingmusic.utils.wintools import is_windows
ALLARGS = settings.ALLARGS ALLARGS = settings.ALLARGS
ARGS = sys.argv[1:] ARGS = sys.argv[1:]
@@ -52,7 +52,7 @@ def handle_build(*args, **kwargs):
try: try:
# write the info to the config file # write the info to the config file
with open("./app/configs.py", "w", encoding="utf-8") as file: with open("./swingmusic/configs.py", "w", encoding="utf-8") as file:
# copy the api keys to the config file # copy the api keys to the config file
file.writelines(lines) file.writelines(lines)
@@ -63,7 +63,7 @@ def handle_build(*args, **kwargs):
bundler.run( bundler.run(
[ [
"main.py", "run.py",
"--onefile", "--onefile",
"--name", "--name",
"swingmusic", "swingmusic",
@@ -73,13 +73,17 @@ def handle_build(*args, **kwargs):
f"--add-data=version.txt{_s}.", f"--add-data=version.txt{_s}.",
f"--add-data={flask_openapi_path}/templates/static{_s}flask_openapi3/templates/static", f"--add-data={flask_openapi_path}/templates/static{_s}flask_openapi3/templates/static",
f"--hidden-import={server_module}", f"--hidden-import={server_module}",
"--collect-submodules=swingmusic",
"--icon=assets/logo-fill.light.ico", "--icon=assets/logo-fill.light.ico",
"-y", "-y",
] ]
) )
except Exception as e:
print(f"Error building the project: {e}")
sys.exit(0)
finally: finally:
# revert and remove the api keys for dev mode # revert and remove the api keys for dev mode
with open("./app/configs.py", "w", encoding="utf-8") as file: with open("./swingmusic/configs.py", "w", encoding="utf-8") as file:
lines = [f'{key} = ""\n' for key in info_keys] lines = [f'{key} = ""\n' for key in info_keys]
file.writelines(lines) file.writelines(lines)
@@ -1,10 +1,10 @@
import time import time
import schedule import schedule
from app.crons.mixes import Mixes from swingmusic.crons.mixes import Mixes
from app.lib.recipes.recents import RecentlyAdded, RecentlyPlayed from swingmusic.lib.recipes.recents import RecentlyAdded, RecentlyPlayed
from app.lib.recipes.topstreamed import TopArtists from swingmusic.lib.recipes.topstreamed import TopArtists
from app.utils.threading import background from swingmusic.utils.threading import background
@background @background
@@ -1,6 +1,6 @@
from app.crons.cron import CronJob from swingmusic.crons.cron import CronJob
from app.lib.recipes.artistmixes import ArtistMixes from swingmusic.lib.recipes.artistmixes import ArtistMixes
from app.lib.recipes.because import BecauseYouListened from swingmusic.lib.recipes.because import BecauseYouListened
class Mixes(CronJob): class Mixes(CronJob):
@@ -8,7 +8,7 @@ from sqlalchemy import (
) )
from sqlalchemy.orm import DeclarativeBase, MappedAsDataclass from sqlalchemy.orm import DeclarativeBase, MappedAsDataclass
from app.db.engine import DbEngine from swingmusic.db.engine import DbEngine
class Base(MappedAsDataclass, DeclarativeBase): class Base(MappedAsDataclass, DeclarativeBase):
+1 -1
View File
@@ -2,7 +2,7 @@ from contextlib import contextmanager
from sqlalchemy import Engine, create_engine, event from sqlalchemy import Engine, create_engine, event
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
from app.settings import DbPaths from swingmusic.settings import DbPaths
@event.listens_for(Engine, "connect") @event.listens_for(Engine, "connect")
@@ -1,7 +1,7 @@
from app.config import UserConfig from swingmusic.config import UserConfig
from app.db import Base from swingmusic.db import Base
from app.db.utils import track_to_dataclass, tracks_to_dataclasses from swingmusic.db.utils import track_to_dataclass, tracks_to_dataclasses
from app.db.engine import DbEngine from swingmusic.db.engine import DbEngine
from sqlalchemy import JSON, Integer, String, delete, select from sqlalchemy import JSON, Integer, String, delete, select
from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.orm import Mapped, mapped_column
@@ -1,10 +1,10 @@
from app.db import Base from swingmusic.db import Base
from sqlalchemy import Integer, insert, select, update from sqlalchemy import Integer, insert, select, update
from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.orm import Mapped, mapped_column
from app.db.engine import DbEngine from swingmusic.db.engine import DbEngine
class MigrationTable(Base): class MigrationTable(Base):
@@ -2,7 +2,7 @@
Reads and saves the latest database migrations version. Reads and saves the latest database migrations version.
""" """
from app.db.sqlite.utils import SQLiteManager from swingmusic.db.sqlite.utils import SQLiteManager
class MigrationManager: class MigrationManager:
@@ -7,8 +7,8 @@ from sqlite3 import Connection, Cursor
import time import time
from typing import Optional from typing import Optional
from app.models import Album, Playlist, Track from swingmusic.models import Album, Playlist, Track
from app import settings from swingmusic import settings
def tuple_to_track(track: tuple): def tuple_to_track(track: tuple):
@@ -17,8 +17,8 @@ from sqlalchemy import (
from sqlalchemy.orm import Mapped, mapped_column, sessionmaker from sqlalchemy.orm import Mapped, mapped_column, sessionmaker
from app.db.engine import DbEngine from swingmusic.db.engine import DbEngine
from app.db.utils import ( from swingmusic.db.utils import (
favorite_to_dataclass, favorite_to_dataclass,
favorites_to_dataclass, favorites_to_dataclass,
playlist_to_dataclass, playlist_to_dataclass,
@@ -28,9 +28,9 @@ from app.db.utils import (
user_to_dataclass, user_to_dataclass,
) )
from app.db import Base from swingmusic.db import Base
from app.models.mix import Mix from swingmusic.models.mix import Mix
from app.utils.auth import get_current_userid, hash_password from swingmusic.utils.auth import get_current_userid, hash_password
class UserTable(Base): class UserTable(Base):
+8 -8
View File
@@ -1,13 +1,13 @@
from typing import Any from typing import Any
from app.config import UserConfig from swingmusic.config import UserConfig
from app.models import Album as AlbumModel, Artist as ArtistModel, Track as TrackModel from swingmusic.models import Album as AlbumModel, Artist as ArtistModel, Track as TrackModel
from app.models.favorite import Favorite from swingmusic.models.favorite import Favorite
from app.models.lastfm import SimilarArtist from swingmusic.models.lastfm import SimilarArtist
from app.models.logger import TrackLog from swingmusic.models.logger import TrackLog
from app.models.playlist import Playlist from swingmusic.models.playlist import Playlist
from app.models.plugins import Plugin from swingmusic.models.plugins import Plugin
from app.models.user import User from swingmusic.models.user import User
def row_to_dict(row: Any): def row_to_dict(row: Any):
@@ -3,7 +3,7 @@ Contains methods relating to albums.
""" """
from app.models.track import Track from swingmusic.models.track import Track
def remove_duplicate_on_merge_versions(tracks: list[Track]): def remove_duplicate_on_merge_versions(tracks: list[Track]):
@@ -12,16 +12,16 @@ from PIL import Image, PngImagePlugin, UnidentifiedImageError
from requests.exceptions import ConnectionError as RequestConnectionError from requests.exceptions import ConnectionError as RequestConnectionError
from requests.exceptions import ReadTimeout from requests.exceptions import ReadTimeout
from app import settings from swingmusic import settings
from app.models.artist import Artist from swingmusic.models.artist import Artist
from app.store.artists import ArtistStore from swingmusic.store.artists import ArtistStore
# from app.db.libdata import ArtistTable # from swingmusic.db.libdata import ArtistTable
# from app.store import artists as artist_store # from swingmusic.store import artists as artist_store
# from app.store.tracks import TrackStore # from swingmusic.store.tracks import TrackStore
from app.utils.hashing import create_hash from swingmusic.utils.hashing import create_hash
from app.utils.progressbar import tqdm from swingmusic.utils.progressbar import tqdm
LARGE_ENOUGH_NUMBER = 100 LARGE_ENOUGH_NUMBER = 100
@@ -6,13 +6,13 @@ from pathlib import Path
import colorgram import colorgram
from app import settings from swingmusic import settings
from app.db.userdata import LibDataTable from swingmusic.db.userdata import LibDataTable
from app.logger import log from swingmusic.logger import log
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.artists import ArtistStore from swingmusic.store.artists import ArtistStore
from app.utils.progressbar import tqdm from swingmusic.utils.progressbar import tqdm
def get_image_colors(image: str, count=1) -> list[str]: def get_image_colors(image: str, count=1) -> list[str]:
"""Extracts n number of the most dominant colors from an image.""" """Extracts n number of the most dominant colors from an image."""
@@ -1,7 +1,7 @@
from typing import Any from typing import Any
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.artists import ArtistStore from swingmusic.store.artists import ArtistStore
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
def get_extra_info(hash: str, type: str): def get_extra_info(hash: str, type: str):
@@ -1,13 +1,13 @@
import os import os
from pathlib import Path from pathlib import Path
from app.lib.sortlib import sort_folders, sort_tracks from swingmusic.lib.sortlib import sort_folders, sort_tracks
from app.logger import log from swingmusic.logger import log
from app.models import Folder from swingmusic.models import Folder
from app.serializers.track import serialize_tracks from swingmusic.serializers.track import serialize_tracks
from app.utils.filesystem import SUPPORTED_FILES from swingmusic.utils.filesystem import SUPPORTED_FILES
from app.store.folder import FolderStore from swingmusic.store.folder import FolderStore
from app.utils.wintools import win_replace_slash from swingmusic.utils.wintools import win_replace_slash
def create_folder(path: str, trackcount=0) -> Folder: def create_folder(path: str, trackcount=0) -> Folder:
@@ -1,12 +1,12 @@
from app.db.userdata import MixTable from swingmusic.db.userdata import MixTable
from app.plugins.mixes import MixesPlugin from swingmusic.plugins.mixes import MixesPlugin
def find_mix(mixid: str, sourcehash: str): def find_mix(mixid: str, sourcehash: str):
""" """
Find a mix in the homepage store or the db. Find a mix in the homepage store or the db.
""" """
from app.store.homepage import HomepageStore from swingmusic.store.homepage import HomepageStore
mixtype = "custom_mixes" if mixid[0] == "t" else "artist_mixes" mixtype = "custom_mixes" if mixid[0] == "t" else "artist_mixes"
@@ -1,12 +1,12 @@
import os import os
from app.db.userdata import PlaylistTable from swingmusic.db.userdata import PlaylistTable
from app.lib.home import find_mix from swingmusic.lib.home import find_mix
from app.lib.home.recentlyadded import get_recently_added_playlist from swingmusic.lib.home.recentlyadded import get_recently_added_playlist
from app.lib.home.recentlyplayed import get_recently_played_playlist from swingmusic.lib.home.recentlyplayed import get_recently_played_playlist
from app.models.logger import TrackLog from swingmusic.models.logger import TrackLog
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.artists import ArtistStore from swingmusic.store.artists import ArtistStore
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
def create_items(entries: list[TrackLog], limit: int): def create_items(entries: list[TrackLog], limit: int):
@@ -1,6 +1,6 @@
from app.db.userdata import ScrobbleTable from swingmusic.db.userdata import ScrobbleTable
from app.lib.home.create_items import create_items from swingmusic.lib.home.create_items import create_items
from app.models.logger import TrackLog from swingmusic.models.logger import TrackLog
def get_recently_played( def get_recently_played(
@@ -1,17 +1,17 @@
from datetime import datetime from datetime import datetime
from app.lib.playlistlib import get_first_4_images from swingmusic.lib.playlistlib import get_first_4_images
from app.models.playlist import Playlist from swingmusic.models.playlist import Playlist
from app.models.track import Track from swingmusic.models.track import Track
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.artists import ArtistStore from swingmusic.store.artists import ArtistStore
from itertools import groupby from itertools import groupby
from app.utils import flatten from swingmusic.utils import flatten
from app.utils.dates import ( from swingmusic.utils.dates import (
create_new_date, create_new_date,
date_string_to_time_passed, date_string_to_time_passed,
) )
@@ -1,13 +1,13 @@
from datetime import datetime from datetime import datetime
from app.models.playlist import Playlist from swingmusic.models.playlist import Playlist
from app.lib.playlistlib import get_first_4_images from swingmusic.lib.playlistlib import get_first_4_images
from app.utils.dates import ( from swingmusic.utils.dates import (
create_new_date, create_new_date,
date_string_to_time_passed, date_string_to_time_passed,
) )
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
def get_recently_played_playlist(limit: int = 100): def get_recently_played_playlist(limit: int = 100):
@@ -1,17 +1,17 @@
from app.db.userdata import FavoritesTable, MixTable, PlaylistTable from swingmusic.db.userdata import FavoritesTable, MixTable, PlaylistTable
from app.lib.home import find_mix from swingmusic.lib.home import find_mix
from app.lib.home.recentlyadded import get_recently_added_playlist from swingmusic.lib.home.recentlyadded import get_recently_added_playlist
from app.lib.home.recentlyplayed import get_recently_played_playlist from swingmusic.lib.home.recentlyplayed import get_recently_played_playlist
from app.lib.playlistlib import get_first_4_images from swingmusic.lib.playlistlib import get_first_4_images
from app.serializers.album import album_serializer from swingmusic.serializers.album import album_serializer
from app.serializers.artist import serialize_for_card from swingmusic.serializers.artist import serialize_for_card
from app.serializers.playlist import serialize_for_card as serialize_playlist from swingmusic.serializers.playlist import serialize_for_card as serialize_playlist
from app.serializers.track import serialize_track from swingmusic.serializers.track import serialize_track
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.artists import ArtistStore from swingmusic.store.artists import ArtistStore
from app.store.folder import FolderStore from swingmusic.store.folder import FolderStore
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
from app.utils.dates import timestamp_to_time_passed from swingmusic.utils.dates import timestamp_to_time_passed
def recover_items(items: list[dict]): def recover_items(items: list[dict]):
+9 -9
View File
@@ -1,19 +1,19 @@
import gc import gc
from time import time from time import time
from app.lib.mapstuff import ( from swingmusic.lib.mapstuff import (
map_album_colors, map_album_colors,
map_artist_colors, map_artist_colors,
map_favorites, map_favorites,
map_scrobble_data, map_scrobble_data,
) )
from app.lib.populate import CordinateMedia from swingmusic.lib.populate import CordinateMedia
from app.lib.recipes.recents import RecentlyAdded from swingmusic.lib.recipes.recents import RecentlyAdded
from app.lib.tagger import IndexTracks from swingmusic.lib.tagger import IndexTracks
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.artists import ArtistStore from swingmusic.store.artists import ArtistStore
from app.store.folder import FolderStore from swingmusic.store.folder import FolderStore
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
from app.utils.threading import background from swingmusic.utils.threading import background
class IndexEverything: class IndexEverything:
@@ -1,7 +1,7 @@
from pathlib import Path from pathlib import Path
from typing import Iterable from typing import Iterable
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
def split_line(line: str): def split_line(line: str):
@@ -1,7 +1,7 @@
from app.db.userdata import LibDataTable, FavoritesTable, ScrobbleTable from swingmusic.db.userdata import LibDataTable, FavoritesTable, ScrobbleTable
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.artists import ArtistStore from swingmusic.store.artists import ArtistStore
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
from typing import Any from typing import Any
@@ -1,10 +1,10 @@
import json import json
from typing import Any from typing import Any
from app.serializers.album import serialize_for_card from swingmusic.serializers.album import serialize_for_card
from app.serializers.artist import serialize_for_card as serialize_artist from swingmusic.serializers.artist import serialize_for_card as serialize_artist
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.artists import ArtistStore from swingmusic.store.artists import ArtistStore
from app.utils.hashing import create_hash from swingmusic.utils.hashing import create_hash
def validate_page_items(items: list[dict[str, str]], existing: list[dict[str, str]]): def validate_page_items(items: list[dict[str, str]], existing: list[dict[str, str]]):
@@ -9,10 +9,10 @@ from typing import Any
from PIL import Image, ImageSequence from PIL import Image, ImageSequence
from app import settings from swingmusic import settings
from app.models.track import Track from swingmusic.models.track import Track
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
def create_thumbnail(image: Any, img_path: str) -> str: def create_thumbnail(image: Any, img_path: str) -> str:
@@ -6,20 +6,20 @@ import platform
from requests import ConnectionError as RequestConnectionError from requests import ConnectionError as RequestConnectionError
from requests import ReadTimeout from requests import ReadTimeout
from app import settings from swingmusic import settings
from app.lib.artistlib import CheckArtistImages from swingmusic.lib.artistlib import CheckArtistImages
from app.lib.colorlib import ProcessAlbumColors, ProcessArtistColors from swingmusic.lib.colorlib import ProcessAlbumColors, ProcessArtistColors
from app.lib.taglib import extract_thumb from swingmusic.lib.taglib import extract_thumb
from app.logger import log from swingmusic.logger import log
from app.models import Album, Artist from swingmusic.models import Album, Artist
from app.models.lastfm import SimilarArtist from swingmusic.models.lastfm import SimilarArtist
from app.requests.artists import fetch_similar_artists from swingmusic.requests.artists import fetch_similar_artists
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.artists import ArtistStore from swingmusic.store.artists import ArtistStore
from app.utils.network import has_connection from swingmusic.utils.network import has_connection
from app.utils.progressbar import tqdm from swingmusic.utils.progressbar import tqdm
from app.db.userdata import SimilarArtistTable from swingmusic.db.userdata import SimilarArtistTable
class CordinateMedia: class CordinateMedia:
@@ -1,7 +1,7 @@
from app.db.userdata import UserTable from swingmusic.db.userdata import UserTable
from app.lib.recipes import HomepageRoutine from swingmusic.lib.recipes import HomepageRoutine
from app.plugins.mixes import MixesPlugin from swingmusic.plugins.mixes import MixesPlugin
from app.store.homepage import HomepageStore from swingmusic.store.homepage import HomepageStore
class ArtistMixes(HomepageRoutine): class ArtistMixes(HomepageRoutine):
@@ -1,10 +1,10 @@
from pprint import pprint from pprint import pprint
from app.db.userdata import UserTable from swingmusic.db.userdata import UserTable
from app.lib.recipes import HomepageRoutine from swingmusic.lib.recipes import HomepageRoutine
from app.lib.recipes.artistmixes import ArtistMixes from swingmusic.lib.recipes.artistmixes import ArtistMixes
from app.models.mix import Mix from swingmusic.models.mix import Mix
from app.plugins.mixes import MixesPlugin from swingmusic.plugins.mixes import MixesPlugin
from app.store.homepage import HomepageStore from swingmusic.store.homepage import HomepageStore
class BecauseYouListened(HomepageRoutine): class BecauseYouListened(HomepageRoutine):
@@ -1,9 +1,9 @@
import pprint import pprint
from app.db.userdata import ScrobbleTable, UserTable from swingmusic.db.userdata import ScrobbleTable, UserTable
from app.lib.home.recentlyadded import get_recently_added_items from swingmusic.lib.home.recentlyadded import get_recently_added_items
from app.lib.home.get_recently_played import get_recently_played from swingmusic.lib.home.get_recently_played import get_recently_played
from app.lib.recipes import HomepageRoutine from swingmusic.lib.recipes import HomepageRoutine
from app.store.homepage import HomepageStore from swingmusic.store.homepage import HomepageStore
class RecentlyPlayed(HomepageRoutine): class RecentlyPlayed(HomepageRoutine):
@@ -1,12 +1,12 @@
from gettext import ngettext from gettext import ngettext
import pendulum import pendulum
from app.crons.cron import CronJob from swingmusic.crons.cron import CronJob
from app.db.userdata import UserTable from swingmusic.db.userdata import UserTable
from app.lib.recipes import HomepageRoutine from swingmusic.lib.recipes import HomepageRoutine
from app.store.homepage import HomepageStore from swingmusic.store.homepage import HomepageStore
from app.utils.dates import get_date_range, seconds_to_time_string from swingmusic.utils.dates import get_date_range, seconds_to_time_string
from app.utils.stats import get_artists_in_period from swingmusic.utils.stats import get_artists_in_period
class TopArtists(CronJob, HomepageRoutine): class TopArtists(CronJob, HomepageRoutine):
@@ -7,27 +7,27 @@ from typing import Any, Generator, List, TypeVar
from rapidfuzz import process, utils, fuzz from rapidfuzz import process, utils, fuzz
from unidecode import unidecode from unidecode import unidecode
from app import models from swingmusic import models
from app.config import UserConfig from swingmusic.config import UserConfig
# from app.db.libdata import AlbumTable, ArtistTable, TrackTable # from swingmusic.db.libdata import AlbumTable, ArtistTable, TrackTable
# from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb # from swingmusic.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
from app.models.album import Album from swingmusic.models.album import Album
from app.models.artist import Artist from swingmusic.models.artist import Artist
from app.models.enums import FavType from swingmusic.models.enums import FavType
from app.models.playlist import Playlist from swingmusic.models.playlist import Playlist
from app.models.track import Track from swingmusic.models.track import Track
from app.serializers.album import serialize_for_card as serialize_album from swingmusic.serializers.album import serialize_for_card as serialize_album
from app.serializers.album import serialize_for_card_many as serialize_albums from swingmusic.serializers.album import serialize_for_card_many as serialize_albums
from app.serializers.artist import serialize_for_card, serialize_for_cards from swingmusic.serializers.artist import serialize_for_card, serialize_for_cards
from app.serializers.track import serialize_track, serialize_tracks from swingmusic.serializers.track import serialize_track, serialize_tracks
from app.store.albums import AlbumStore from swingmusic.store.albums import AlbumStore
from app.store.artists import ArtistStore from swingmusic.store.artists import ArtistStore
from app.store.tracks import TrackStore from swingmusic.store.tracks import TrackStore
from app.utils.remove_duplicates import remove_duplicates from swingmusic.utils.remove_duplicates import remove_duplicates
# ratio = fuzz.ratio # ratio = fuzz.ratio
# wratio = fuzz.WRatio # wratio = fuzz.WRatio

Some files were not shown because too many files have changed in this diff Show More